Integrating up through commit 90f050496
This commit is contained in:
+52
-22
@@ -16,6 +16,7 @@
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/EditContextConstants.inl>
|
||||
#include <AzFramework/API/ApplicationAPI.h>
|
||||
#include <AzToolsFramework/API/EditorCameraBus.h>
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
|
||||
@@ -33,6 +34,7 @@ namespace AZ
|
||||
}
|
||||
|
||||
EditorCommonFeaturesSystemComponent::EditorCommonFeaturesSystemComponent() = default;
|
||||
|
||||
EditorCommonFeaturesSystemComponent::~EditorCommonFeaturesSystemComponent() = default;
|
||||
|
||||
//! Main system component for the Atom Common Feature Gem's editor/tools module.
|
||||
@@ -84,49 +86,67 @@ 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::ApplicationLifecycleEvents::Bus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
void EditorCommonFeaturesSystemComponent::Deactivate()
|
||||
{
|
||||
AzToolsFramework::EditorLevelNotificationBus::Handler::BusDisconnect();
|
||||
AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusDisconnect();
|
||||
AzToolsFramework::AssetBrowser::PreviewerRequestBus::Handler::BusDisconnect();
|
||||
|
||||
m_skinnedMeshDebugDisplay.reset();
|
||||
m_previewerFactory.reset();
|
||||
m_renderer.reset();
|
||||
}
|
||||
|
||||
void EditorCommonFeaturesSystemComponent::OnNewLevelCreated()
|
||||
{
|
||||
AZ::Data::AssetCatalogRequestBus::BroadcastResult(m_levelDefaultSliceAssetId, &AZ::Data::AssetCatalogRequests::GetAssetIdByPath, m_atomLevelDefaultAssetPath.c_str(), azrtti_typeid<AZ::SliceAsset>(), false);
|
||||
bool isPrefabSystemEnabled = false;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(
|
||||
isPrefabSystemEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled);
|
||||
|
||||
if (m_levelDefaultSliceAssetId.IsValid())
|
||||
if (!isPrefabSystemEnabled)
|
||||
{
|
||||
AZ::Data::Asset<AZ::Data::AssetData> asset = AZ::Data::AssetManager::Instance().GetAsset<AZ::SliceAsset>(
|
||||
m_levelDefaultSliceAssetId,
|
||||
AZ::Data::AssetLoadBehavior::Default);
|
||||
AZ::Data::AssetCatalogRequestBus::BroadcastResult(
|
||||
m_levelDefaultSliceAssetId, &AZ::Data::AssetCatalogRequests::GetAssetIdByPath, m_atomLevelDefaultAssetPath.c_str(),
|
||||
azrtti_typeid<AZ::SliceAsset>(), false);
|
||||
|
||||
asset.BlockUntilLoadComplete();
|
||||
|
||||
if (asset)
|
||||
if (m_levelDefaultSliceAssetId.IsValid())
|
||||
{
|
||||
AZ::Vector3 cameraPosition = AZ::Vector3::CreateZero();
|
||||
bool activeCameraFound = false;
|
||||
Camera::EditorCameraRequestBus::BroadcastResult(activeCameraFound, &Camera::EditorCameraRequestBus::Events::GetActiveCameraPosition, cameraPosition);
|
||||
AZ::Data::Asset<AZ::Data::AssetData> asset = AZ::Data::AssetManager::Instance().GetAsset<AZ::SliceAsset>(
|
||||
m_levelDefaultSliceAssetId, AZ::Data::AssetLoadBehavior::Default);
|
||||
|
||||
if (activeCameraFound)
|
||||
asset.BlockUntilLoadComplete();
|
||||
|
||||
if (asset)
|
||||
{
|
||||
AZ::Transform worldTransform = AZ::Transform::CreateTranslation(cameraPosition);
|
||||
AZ::Vector3 cameraPosition = AZ::Vector3::CreateZero();
|
||||
bool activeCameraFound = false;
|
||||
Camera::EditorCameraRequestBus::BroadcastResult(
|
||||
activeCameraFound, &Camera::EditorCameraRequestBus::Events::GetActiveCameraPosition, cameraPosition);
|
||||
|
||||
AzToolsFramework::SliceEditorEntityOwnershipServiceNotificationBus::Handler::BusConnect();
|
||||
|
||||
if (IEditor* editor = GetLegacyEditor();
|
||||
!editor->IsUndoSuspended())
|
||||
if (activeCameraFound)
|
||||
{
|
||||
editor->SuspendUndo();
|
||||
}
|
||||
AZ::Transform worldTransform = AZ::Transform::CreateTranslation(cameraPosition);
|
||||
|
||||
AzToolsFramework::SliceEditorEntityOwnershipServiceRequestBus::Broadcast(
|
||||
&AzToolsFramework::SliceEditorEntityOwnershipServiceRequests::InstantiateEditorSlice, asset, worldTransform);
|
||||
AzToolsFramework::SliceEditorEntityOwnershipServiceNotificationBus::Handler::BusConnect();
|
||||
|
||||
if (IEditor* editor = GetLegacyEditor(); !editor->IsUndoSuspended())
|
||||
{
|
||||
editor->SuspendUndo();
|
||||
}
|
||||
|
||||
AzToolsFramework::SliceEditorEntityOwnershipServiceRequestBus::Broadcast(
|
||||
&AzToolsFramework::SliceEditorEntityOwnershipServiceRequests::InstantiateEditorSlice, asset,
|
||||
worldTransform);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -165,7 +185,6 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EditorCommonFeaturesSystemComponent::OnSliceInstantiationFailed(const AZ::Data::AssetId& sliceAssetId, const AzFramework::SliceInstantiationTicket& /*ticket*/)
|
||||
{
|
||||
if (m_levelDefaultSliceAssetId == sliceAssetId)
|
||||
@@ -175,5 +194,16 @@ namespace AZ
|
||||
AZ_Warning("EditorCommonFeaturesSystemComponent", false, "Failed to instantiate default Atom environment slice.");
|
||||
}
|
||||
}
|
||||
|
||||
const AzToolsFramework::AssetBrowser::PreviewerFactory* EditorCommonFeaturesSystemComponent::GetPreviewerFactory(
|
||||
const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) const
|
||||
{
|
||||
return m_previewerFactory->IsEntrySupported(entry) ? m_previewerFactory.get() : nullptr;
|
||||
}
|
||||
|
||||
void EditorCommonFeaturesSystemComponent::OnApplicationAboutToStop()
|
||||
{
|
||||
m_renderer.reset();
|
||||
}
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
+15
@@ -13,8 +13,12 @@
|
||||
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <AzFramework/Application/Application.h>
|
||||
#include <AzToolsFramework/API/EditorLevelNotificationBus.h>
|
||||
#include <AzToolsFramework/Entity/SliceEditorEntityOwnershipServiceBus.h>
|
||||
#include <AzToolsFramework/AssetBrowser/Previewer/PreviewerBus.h>
|
||||
#include <Thumbnails/Rendering/CommonThumbnailRenderer.h>
|
||||
#include <Source/Thumbnails/Preview/CommonPreviewerFactory.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -27,6 +31,8 @@ namespace AZ
|
||||
: public AZ::Component
|
||||
, public AzToolsFramework::EditorLevelNotificationBus::Handler
|
||||
, public AzToolsFramework::SliceEditorEntityOwnershipServiceNotificationBus::Handler
|
||||
, public AzToolsFramework::AssetBrowser::PreviewerRequestBus::Handler
|
||||
, public AzFramework::ApplicationLifecycleEvents::Bus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(EditorCommonFeaturesSystemComponent, "{D73D77CF-D5AF-428B-909B-324E96D3DEF5}");
|
||||
@@ -54,12 +60,21 @@ 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;
|
||||
|
||||
// AzToolsFramework::AssetBrowser::PreviewerRequestBus::Handler overrides...
|
||||
const AzToolsFramework::AssetBrowser::PreviewerFactory* GetPreviewerFactory(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) const override;
|
||||
|
||||
// AzFramework::ApplicationLifecycleEvents overrides...
|
||||
void OnApplicationAboutToStop() override;
|
||||
|
||||
private:
|
||||
AZStd::unique_ptr<SkinnedMeshDebugDisplay> m_skinnedMeshDebugDisplay;
|
||||
|
||||
AZ::Data::AssetId m_levelDefaultSliceAssetId;
|
||||
AZStd::string m_atomLevelDefaultAssetPath{ "LevelAssets/default.slice" };
|
||||
float m_envProbeHeight{ 200.0f };
|
||||
|
||||
AZStd::unique_ptr<AZ::LyIntegration::Thumbnails::CommonThumbnailRenderer> m_renderer;
|
||||
AZStd::unique_ptr<LyIntegration::CommonPreviewerFactory> m_previewerFactory;
|
||||
};
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
@@ -83,16 +83,21 @@ namespace AZ
|
||||
m_entityId = entityId;
|
||||
m_dirty = true;
|
||||
|
||||
RPI::ScenePtr scene = RPI::RPISystemInterface::Get()->GetDefaultScene();
|
||||
if (scene)
|
||||
{
|
||||
AZ::RPI::SceneNotificationBus::Handler::BusConnect(scene->GetId());
|
||||
}
|
||||
|
||||
GridComponentRequestBus::Handler::BusConnect(m_entityId);
|
||||
AZ::TransformNotificationBus::Handler::BusConnect(m_entityId);
|
||||
AZ::TickBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
void GridComponentController::Deactivate()
|
||||
{
|
||||
AZ::TickBus::Handler::BusDisconnect();
|
||||
AZ::TransformNotificationBus::Handler::BusDisconnect();
|
||||
GridComponentRequestBus::Handler::BusDisconnect();
|
||||
AZ::RPI::SceneNotificationBus::Handler::BusDisconnect();
|
||||
|
||||
m_entityId = EntityId(EntityId::InvalidEntityId);
|
||||
}
|
||||
@@ -171,11 +176,8 @@ namespace AZ
|
||||
return m_configuration.m_secondaryColor;
|
||||
}
|
||||
|
||||
void GridComponentController::OnTick(float deltaTime, AZ::ScriptTimePoint time)
|
||||
void GridComponentController::OnBeginPrepareRender()
|
||||
{
|
||||
AZ_UNUSED(time);
|
||||
AZ_UNUSED(deltaTime);
|
||||
|
||||
auto* auxGeomFP = AZ::RPI::Scene::GetFeatureProcessorForEntity<AZ::RPI::AuxGeomFeatureProcessorInterface>(m_entityId);
|
||||
if (auto auxGeom = auxGeomFP->GetDrawQueue())
|
||||
{
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <AzCore/Component/TickBus.h>
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AtomLyIntegration/CommonFeatures/Grid/GridComponentBus.h>
|
||||
#include <AtomLyIntegration/CommonFeatures/Grid/GridComponentConfig.h>
|
||||
#include <Atom/RPI.Public/SceneBus.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -25,8 +25,8 @@ namespace AZ
|
||||
//! Controls behavior and rendering of a wireframe grid
|
||||
class GridComponentController final
|
||||
: public GridComponentRequestBus::Handler
|
||||
, public AZ::TickBus::Handler
|
||||
, public AZ::TransformNotificationBus::Handler
|
||||
, public AZ::RPI::SceneNotificationBus::Handler
|
||||
{
|
||||
public:
|
||||
friend class EditorGridComponent;
|
||||
@@ -64,12 +64,12 @@ namespace AZ
|
||||
void SetSecondaryColor(const AZ::Color& gridSecondaryColor) override;
|
||||
AZ::Color GetSecondaryColor() const override;
|
||||
|
||||
// AZ::TickBus::Handler overrides ...
|
||||
void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
|
||||
|
||||
//! AZ::TransformNotificationBus::Handler overrides ...
|
||||
void OnTransformChanged(const Transform& local, const Transform& world) override;
|
||||
|
||||
// AZ::RPI::SceneNotificationBus::Handler overrides ...
|
||||
void OnBeginPrepareRender() override;
|
||||
|
||||
void BuildGrid();
|
||||
|
||||
EntityId m_entityId;
|
||||
|
||||
+84
-151
@@ -11,32 +11,26 @@
|
||||
*/
|
||||
|
||||
#include <Material/EditorMaterialComponentExporter.h>
|
||||
#include <AzFramework/API/ApplicationAPI.h>
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
#include <Atom/RPI.Edit/Common/AssetUtils.h>
|
||||
#include <Atom/RPI.Edit/Common/JsonUtils.h>
|
||||
#include <Atom/RPI.Edit/Material/MaterialPropertyId.h>
|
||||
#include <Atom/RPI.Edit/Material/MaterialSourceData.h>
|
||||
#include <Atom/RPI.Edit/Material/MaterialTypeSourceData.h>
|
||||
#include <Atom/RPI.Edit/Material/MaterialUtils.h>
|
||||
#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
|
||||
#include <Atom/RPI.Reflect/Material/MaterialPropertiesLayout.h>
|
||||
#include <Atom/RPI.Reflect/Material/MaterialTypeAsset.h>
|
||||
#include <AzQtComponents/Components/Widgets/BrowseEdit.h>
|
||||
#include <Material/EditorMaterialComponentUtil.h>
|
||||
|
||||
#include <AzFramework/API/ApplicationAPI.h>
|
||||
#include <AzQtComponents/Components/Widgets/BrowseEdit.h>
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
||||
#include <AzToolsFramework/API/EditorWindowRequestBus.h>
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
|
||||
#include <Atom/RPI.Edit/Common/AssetUtils.h>
|
||||
|
||||
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
|
||||
#include <QApplication>
|
||||
#include <QTableWidget>
|
||||
#include <QHeaderView>
|
||||
#include <QFileDialog>
|
||||
#include <QCheckBox>
|
||||
#include <QComboBox>
|
||||
#include <QFileDialog>
|
||||
#include <QHBoxLayout>
|
||||
#include <QHeaderView>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QHBoxLayout>
|
||||
#include <QTableWidget>
|
||||
#include <QVBoxLayout>
|
||||
AZ_POP_DISABLE_WARNING
|
||||
|
||||
@@ -102,28 +96,6 @@ namespace AZ
|
||||
return exportPath;
|
||||
}
|
||||
|
||||
// Returns message text based on the item state
|
||||
QString GetExportItemStatusMessage(const ExportItem& exportItem)
|
||||
{
|
||||
QFileInfo fileInfo(exportItem.m_exportPath.c_str());
|
||||
if (!exportItem.m_enabled)
|
||||
{
|
||||
return QString("Do not generate a new material.");
|
||||
}
|
||||
|
||||
if (fileInfo == QFileInfo())
|
||||
{
|
||||
return QString("A valid material file path is required.");
|
||||
}
|
||||
|
||||
if (fileInfo.exists())
|
||||
{
|
||||
return QString("\"%1\" will be replaced in the designated folder.").arg(fileInfo.fileName());
|
||||
}
|
||||
|
||||
return QString("\"%1\" will be generated in the designated folder.").arg(fileInfo.fileName());
|
||||
}
|
||||
|
||||
bool OpenExportDialog(ExportItemsContainer& exportItems)
|
||||
{
|
||||
QWidget* activeWindow = nullptr;
|
||||
@@ -133,11 +105,10 @@ namespace AZ
|
||||
QDialog dialog(activeWindow);
|
||||
dialog.setWindowTitle("Generate Source Materials");
|
||||
|
||||
const QStringList headerLabels = { "Enable", "Material Slot", "Material Filename", "Status" };
|
||||
const int EnableColumn = 0;
|
||||
const int MaterialColumn = 1;
|
||||
const int FileColumn = 2;
|
||||
const int StatusColumn = 3;
|
||||
const QStringList headerLabels = { "Material Slot", "Material Filename", "Overwrite" };
|
||||
const int MaterialSlotColumn = 0;
|
||||
const int MaterialFileColumn = 1;
|
||||
const int OverwriteFileColumn = 2;
|
||||
|
||||
// Create a table widget that will be filled with all of the data and options for each exported material
|
||||
QTableWidget* tableWidget = new QTableWidget(&dialog);
|
||||
@@ -153,8 +124,10 @@ namespace AZ
|
||||
tableWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
|
||||
|
||||
// Force the table to stretch its header to fill the entire width of the dialog
|
||||
tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
tableWidget->horizontalHeader()->setStretchLastSection(true);
|
||||
tableWidget->horizontalHeader()->setSectionResizeMode(MaterialSlotColumn, QHeaderView::ResizeToContents);
|
||||
tableWidget->horizontalHeader()->setSectionResizeMode(MaterialFileColumn, QHeaderView::Stretch);
|
||||
tableWidget->horizontalHeader()->setSectionResizeMode(OverwriteFileColumn, QHeaderView::ResizeToContents);
|
||||
tableWidget->horizontalHeader()->setStretchLastSection(false);
|
||||
|
||||
// Hide row numbers
|
||||
tableWidget->verticalHeader()->setVisible(false);
|
||||
@@ -166,46 +139,55 @@ namespace AZ
|
||||
|
||||
// Configuring initial settings based on whether or not the target file already exists
|
||||
exportItem.m_exportPath = fileInfo.absoluteFilePath().toUtf8().constData();
|
||||
exportItem.m_exists = fileInfo.exists();
|
||||
exportItem.m_overwrite = false;
|
||||
|
||||
// Populate the table with data for every column
|
||||
tableWidget->setItem(row, EnableColumn, new QTableWidgetItem(exportItem.m_enabled));
|
||||
tableWidget->setItem(row, MaterialColumn, new QTableWidgetItem(GetLabelByAssetId(exportItem.m_assetId).c_str()));
|
||||
tableWidget->setItem(row, FileColumn, new QTableWidgetItem(fileInfo.fileName()));
|
||||
tableWidget->setItem(row, MaterialSlotColumn, new QTableWidgetItem());
|
||||
tableWidget->setItem(row, MaterialFileColumn, new QTableWidgetItem());
|
||||
tableWidget->setItem(row, OverwriteFileColumn, new QTableWidgetItem());
|
||||
|
||||
// Create a check box for toggling the enabled state of this item
|
||||
QWidget* enableCheckBoxParent = new QWidget(tableWidget);
|
||||
QCheckBox* enableCheckBox = new QCheckBox(enableCheckBoxParent);
|
||||
enableCheckBox->setChecked(exportItem.m_enabled);
|
||||
|
||||
// Center checkbox in cell
|
||||
QHBoxLayout* enableCheckBoxLayout = new QHBoxLayout(enableCheckBoxParent);
|
||||
enableCheckBoxLayout->setAlignment(Qt::AlignCenter);
|
||||
enableCheckBoxLayout->addWidget(enableCheckBox);
|
||||
enableCheckBoxParent->setLayout(enableCheckBoxLayout);
|
||||
|
||||
tableWidget->setCellWidget(row, EnableColumn, enableCheckBoxParent);
|
||||
QCheckBox* materialSlotCheckBox = new QCheckBox(tableWidget);
|
||||
materialSlotCheckBox->setChecked(exportItem.m_enabled);
|
||||
materialSlotCheckBox->setText(GetLabelByAssetId(exportItem.m_assetId).c_str());
|
||||
tableWidget->setCellWidget(row, MaterialSlotColumn, materialSlotCheckBox);
|
||||
|
||||
// Create a file picker widget for selecting the save path for the exported material
|
||||
AzQtComponents::BrowseEdit* fileWidget = new AzQtComponents::BrowseEdit(tableWidget);
|
||||
fileWidget->setLineEditReadOnly(true);
|
||||
fileWidget->setClearButtonEnabled(false);
|
||||
fileWidget->setText(fileInfo.fileName());
|
||||
tableWidget->setCellWidget(row, FileColumn, fileWidget);
|
||||
AzQtComponents::BrowseEdit* materialFileWidget = new AzQtComponents::BrowseEdit(tableWidget);
|
||||
materialFileWidget->setLineEditReadOnly(true);
|
||||
materialFileWidget->setClearButtonEnabled(false);
|
||||
materialFileWidget->setEnabled(exportItem.m_enabled);
|
||||
materialFileWidget->setText(fileInfo.fileName());
|
||||
tableWidget->setCellWidget(row, MaterialFileColumn, materialFileWidget);
|
||||
|
||||
// The status widget will be used to inform the user of issues and outcomes from selected settings
|
||||
QLabel* statusWidget = new QLabel(tableWidget);
|
||||
statusWidget->setText(GetExportItemStatusMessage(exportItem));
|
||||
tableWidget->setCellWidget(row, StatusColumn, statusWidget);
|
||||
// Create a check box for toggling the overwrite state of this item
|
||||
QWidget* overwriteCheckBoxContainer = new QWidget(tableWidget);
|
||||
QCheckBox* overwriteCheckBox = new QCheckBox(overwriteCheckBoxContainer);
|
||||
overwriteCheckBox->setChecked(exportItem.m_overwrite);
|
||||
overwriteCheckBox->setEnabled(exportItem.m_enabled && exportItem.m_exists);
|
||||
|
||||
overwriteCheckBoxContainer->setLayout(new QHBoxLayout(overwriteCheckBoxContainer));
|
||||
overwriteCheckBoxContainer->layout()->addWidget(overwriteCheckBox);
|
||||
overwriteCheckBoxContainer->layout()->setAlignment(Qt::AlignCenter);
|
||||
overwriteCheckBoxContainer->layout()->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
tableWidget->setCellWidget(row, OverwriteFileColumn, overwriteCheckBoxContainer);
|
||||
|
||||
// Whenever the selection is updated, automatically apply the change to the export item
|
||||
QObject::connect(enableCheckBox, &QCheckBox::stateChanged, enableCheckBox, [&dialog, &exportItem, enableCheckBox, fileWidget, statusWidget]([[maybe_unused]] int state) {
|
||||
exportItem.m_enabled = enableCheckBox->isChecked();
|
||||
fileWidget->setEnabled(exportItem.m_enabled);
|
||||
statusWidget->setText(GetExportItemStatusMessage(exportItem));
|
||||
QObject::connect(materialSlotCheckBox, &QCheckBox::stateChanged, materialSlotCheckBox, [&]([[maybe_unused]] int state) {
|
||||
exportItem.m_enabled = materialSlotCheckBox->isChecked();
|
||||
materialFileWidget->setEnabled(exportItem.m_enabled);
|
||||
overwriteCheckBox->setEnabled(exportItem.m_enabled && exportItem.m_exists);
|
||||
});
|
||||
|
||||
// Whenever the overwrite check box is updated, automatically apply the change to the export item
|
||||
QObject::connect(overwriteCheckBox, &QCheckBox::stateChanged, overwriteCheckBox, [&]([[maybe_unused]] int state) {
|
||||
exportItem.m_overwrite = overwriteCheckBox->isChecked();
|
||||
});
|
||||
|
||||
// Whenever the browse button is clicked, open a save file dialog in the same location as the current export file setting
|
||||
QObject::connect(fileWidget, &AzQtComponents::BrowseEdit::attachedButtonTriggered, fileWidget, [&dialog, &exportItem, enableCheckBox, fileWidget, statusWidget]() {
|
||||
QObject::connect(materialFileWidget, &AzQtComponents::BrowseEdit::attachedButtonTriggered, materialFileWidget, [&]() {
|
||||
QFileInfo fileInfo = QFileDialog::getSaveFileName(&dialog,
|
||||
QString("Select Material Filename"),
|
||||
exportItem.m_exportPath.c_str(),
|
||||
@@ -213,21 +195,24 @@ namespace AZ
|
||||
nullptr,
|
||||
QFileDialog::DontConfirmOverwrite);
|
||||
|
||||
if (fileInfo != QFileInfo())
|
||||
// Only update the export data if a valid path and filename was selected
|
||||
if (!fileInfo.absoluteFilePath().isEmpty())
|
||||
{
|
||||
// Only update the export data if a valid path and filename was selected
|
||||
exportItem.m_exportPath = fileInfo.absoluteFilePath().toUtf8().constData();
|
||||
|
||||
exportItem.m_exists = fileInfo.exists();
|
||||
exportItem.m_overwrite = fileInfo.exists();
|
||||
\
|
||||
// Update the controls to display the new state
|
||||
fileWidget->setText(fileInfo.fileName());
|
||||
statusWidget->setText(GetExportItemStatusMessage(exportItem));
|
||||
materialFileWidget->setText(fileInfo.fileName());
|
||||
overwriteCheckBox->setChecked(exportItem.m_overwrite);
|
||||
overwriteCheckBox->setEnabled(exportItem.m_enabled && exportItem.m_exists);
|
||||
}
|
||||
});
|
||||
|
||||
++row;
|
||||
}
|
||||
|
||||
tableWidget->sortItems(MaterialColumn);
|
||||
tableWidget->sortItems(MaterialSlotColumn);
|
||||
|
||||
// Create the bottom row of the dialog with action buttons for exporting or canceling the operation
|
||||
QWidget* buttonRow = new QWidget(&dialog);
|
||||
@@ -245,7 +230,8 @@ namespace AZ
|
||||
buttonLayout->addWidget(cancelButton);
|
||||
|
||||
// Create a heading label for the top of the dialog
|
||||
QLabel* labelWidget = new QLabel("Select the material slots that you want to generate new source materials for. Edit the material file name and location using the file picker.", &dialog);
|
||||
QLabel* labelWidget = new QLabel("\nSelect the material slots that you want to generate new source materials for. Edit the material file name and location using the file picker.\n", &dialog);
|
||||
labelWidget->setWordWrap(true);
|
||||
|
||||
QVBoxLayout* dialogLayout = new QVBoxLayout(&dialog);
|
||||
dialogLayout->addWidget(labelWidget);
|
||||
@@ -257,7 +243,7 @@ namespace AZ
|
||||
// Temporarily settng fixed size because dialog.show/exec invokes WindowDecorationWrapper::showEvent.
|
||||
// This forces the dialog to be centered and sized based on the layout of content.
|
||||
// Resizing the dialog after show will not be centered and moving the dialog programatically doesn't m0ve the custmk frame.
|
||||
dialog.setFixedSize(1000, 200);
|
||||
dialog.setFixedSize(500, 200);
|
||||
dialog.show();
|
||||
|
||||
// Removing fixed size to allow drag resizing
|
||||
@@ -275,78 +261,25 @@ namespace AZ
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load the originating product asset from which the new source has set will be generated
|
||||
auto materialAssetOutcome = AZ::RPI::AssetUtils::LoadAsset<AZ::RPI::MaterialAsset>(exportItem.m_assetId);
|
||||
if (!materialAssetOutcome)
|
||||
if (exportItem.m_exists && !exportItem.m_overwrite)
|
||||
{
|
||||
AZ_Error("AZ::Render::EditorMaterialComponentExporter", false, "Failed to load initial material asset while attempting to export: %s", exportItem.m_exportPath.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
AZ::Data::Asset<AZ::RPI::MaterialAsset> materialAsset = materialAssetOutcome.GetValue();
|
||||
AZ::Data::Asset<AZ::RPI::MaterialTypeAsset> materialTypeAsset = materialAsset->GetMaterialTypeAsset();
|
||||
|
||||
// We need a valid path to the material type source data because it's required for to get the property layout and assign to the new material
|
||||
const AZStd::string& materialTypePath = AZ::RPI::AssetUtils::GetSourcePathByAssetId(materialTypeAsset.GetId());
|
||||
if (materialTypePath.empty())
|
||||
{
|
||||
AZ_Error("AZ::Render::EditorMaterialComponentExporter", false, "Failed to locate source material type asset while attempting to export: %s", exportItem.m_exportPath.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Getting the source info for the material type file to make sure that it exists
|
||||
// We also need to watch folder to generate a relative asset path for the material type
|
||||
bool result = false;
|
||||
AZ::Data::AssetInfo info;
|
||||
AZStd::string watchFolder;
|
||||
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(result, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, materialTypePath.c_str(), info, watchFolder);
|
||||
if (!result)
|
||||
{
|
||||
AZ_Error("AZ::Render::EditorMaterialComponentExporter", false, "Failed to get source file info and asset path while attempting to export: %s", exportItem.m_exportPath.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// At this point, we should be ready to attempt to load the material type data
|
||||
auto materialTypeOutcome = AZ::RPI::MaterialUtils::LoadMaterialTypeSourceData(materialTypePath);
|
||||
if (!materialTypeOutcome.IsSuccess())
|
||||
{
|
||||
AZ_Error("AZ::Render::EditorMaterialComponentExporter", false, "Failed to load material type source data: %s", materialTypePath.c_str());
|
||||
return false;
|
||||
}
|
||||
AZ::RPI::MaterialTypeSourceData materialTypeSourceData = materialTypeOutcome.GetValue();
|
||||
|
||||
// Construct the material source data object that will be exported
|
||||
AZ::RPI::MaterialSourceData exportData;
|
||||
exportData.m_propertyLayoutVersion = materialTypeSourceData.m_propertyLayout.m_version;
|
||||
|
||||
// Converting the absolute material type app to an asset relative path
|
||||
exportData.m_materialType = materialTypePath;
|
||||
AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::Bus::Events::MakePathRelative, exportData.m_materialType, watchFolder.c_str());
|
||||
|
||||
// Copy all of the properties from the material asset to the source data that will be exported
|
||||
result = true;
|
||||
materialTypeSourceData.EnumerateProperties([&materialAsset, &materialTypeSourceData, &exportData, &exportItem, &result](const AZStd::string& groupNameId, const AZStd::string& propertyNameId, const auto& propertyDefinition) {
|
||||
const AZ::RPI::MaterialPropertyId propertyId(groupNameId, propertyNameId);
|
||||
const AZ::RPI::MaterialPropertyIndex propertyIndex = materialAsset->GetMaterialPropertiesLayout()->FindPropertyIndex(propertyId.GetFullName());
|
||||
AZ::RPI::MaterialPropertyValue propertyValue = materialAsset->GetPropertyValues()[propertyIndex.GetIndex()];
|
||||
|
||||
if (!materialTypeSourceData.ConvertPropertyValueToSourceDataFormat(propertyDefinition, propertyValue))
|
||||
{
|
||||
AZ_Error("AZ::Render::EditorMaterialComponentExporter", false, "Failed to export: %s", exportItem.m_exportPath.c_str());
|
||||
result = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (propertyDefinition.m_value == propertyValue)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
exportData.m_properties[groupNameId][propertyDefinition.m_nameId].m_value = propertyValue;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
return result && AZ::RPI::JsonUtils::SaveObjectToFile(exportItem.m_exportPath, exportData);
|
||||
EditorMaterialComponentUtil::MaterialEditData editData;
|
||||
if (!EditorMaterialComponentUtil::LoadMaterialEditDataFromAssetId(exportItem.m_assetId, editData))
|
||||
{
|
||||
AZ_Warning("AZ::Render::EditorMaterialComponentExporter", false, "Failed to load material data.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!EditorMaterialComponentUtil::SaveSourceMaterialFromEditData(exportItem.m_exportPath, editData))
|
||||
{
|
||||
AZ_Warning("AZ::Render::EditorMaterialComponentExporter", false, "Failed to save material data.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace EditorMaterialComponentExporter
|
||||
} // namespace Render
|
||||
|
||||
+2
@@ -32,6 +32,8 @@ namespace AZ
|
||||
struct ExportItem
|
||||
{
|
||||
bool m_enabled = true;
|
||||
bool m_exists = false;
|
||||
bool m_overwrite = false;
|
||||
AZ::Data::AssetId m_assetId;
|
||||
AZStd::string m_exportPath;
|
||||
};
|
||||
|
||||
+202
-134
@@ -11,32 +11,39 @@
|
||||
*/
|
||||
|
||||
#include <Material/EditorMaterialComponentInspector.h>
|
||||
#include <AzFramework/API/ApplicationAPI.h>
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
|
||||
#include <Atom/RPI.Edit/Common/AssetUtils.h>
|
||||
#include <Atom/RPI.Edit/Common/JsonUtils.h>
|
||||
#include <Atom/RPI.Edit/Material/MaterialFunctorSourceData.h>
|
||||
#include <Atom/RPI.Edit/Material/MaterialPropertyId.h>
|
||||
#include <Atom/RPI.Edit/Material/MaterialSourceData.h>
|
||||
#include <Atom/RPI.Edit/Material/MaterialTypeSourceData.h>
|
||||
#include <Atom/RPI.Edit/Material/MaterialUtils.h>
|
||||
#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
|
||||
#include <Atom/RPI.Reflect/Material/MaterialPropertiesLayout.h>
|
||||
#include <Atom/RPI.Reflect/Material/MaterialTypeAsset.h>
|
||||
#include <Atom/RPI.Reflect/Material/MaterialFunctor.h>
|
||||
|
||||
#include <Atom/RPI.Reflect/Material/MaterialPropertiesLayout.h>
|
||||
#include <AtomToolsFramework/Inspector/InspectorPropertyGroupWidget.h>
|
||||
#include <AtomToolsFramework/Util/MaterialPropertyUtil.h>
|
||||
|
||||
#include <AtomToolsFramework/Util/Util.h>
|
||||
#include <AzFramework/API/ApplicationAPI.h>
|
||||
#include <AzQtComponents/Components/Widgets/Text.h>
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
||||
#include <AzToolsFramework/API/EditorWindowRequestBus.h>
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
#include <AzToolsFramework/AssetBrowser/Thumbnails/ProductThumbnail.h>
|
||||
#include <AzToolsFramework/Thumbnails/ThumbnailContext.h>
|
||||
#include <AzToolsFramework/Thumbnails/ThumbnailWidget.h>
|
||||
#include <AzToolsFramework/Thumbnails/ThumbnailerBus.h>
|
||||
|
||||
#include <AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentRequestBus.h>
|
||||
|
||||
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
|
||||
#include <QApplication>
|
||||
#include <QDialog>
|
||||
#include <QPushButton>
|
||||
#include <QFileInfo>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QMenu>
|
||||
#include <QToolButton>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
AZ_POP_DISABLE_WARNING
|
||||
|
||||
namespace AZ
|
||||
@@ -45,8 +52,11 @@ namespace AZ
|
||||
{
|
||||
namespace EditorMaterialComponentInspector
|
||||
{
|
||||
MaterialPropertyInspector::MaterialPropertyInspector(const AZ::Data::AssetId& assetId, PropertyChangedCallback propertyChangedCallback, QWidget* parent)
|
||||
MaterialPropertyInspector::MaterialPropertyInspector(
|
||||
const AZStd::string& slotName, const AZ::Data::AssetId& assetId, PropertyChangedCallback propertyChangedCallback,
|
||||
QWidget* parent)
|
||||
: AtomToolsFramework::InspectorWidget(parent)
|
||||
, m_slotName(slotName)
|
||||
, m_materialAssetId(assetId)
|
||||
, m_propertyChangedCallback(propertyChangedCallback)
|
||||
{
|
||||
@@ -59,65 +69,25 @@ namespace AZ
|
||||
|
||||
bool MaterialPropertyInspector::LoadMaterial()
|
||||
{
|
||||
if (!m_materialAssetId.IsValid())
|
||||
if (!EditorMaterialComponentUtil::LoadMaterialEditDataFromAssetId(m_materialAssetId, m_editData))
|
||||
{
|
||||
AZ_Warning("AZ::Render::EditorMaterialComponentInspector", false, "Attempted to load material data for invalid asset id.");
|
||||
AZ_Warning("AZ::Render::EditorMaterialComponentInspector", false, "Failed to load material data.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load the originating product asset from which the new source has set will be generated
|
||||
auto materialAssetOutcome = AZ::RPI::AssetUtils::LoadAsset<AZ::RPI::MaterialAsset>(m_materialAssetId);
|
||||
if (!materialAssetOutcome)
|
||||
{
|
||||
AZ_Error("AZ::Render::EditorMaterialComponentInspector", false, "Failed to load material asset: %s", m_materialAssetId.ToString<AZStd::string>().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
m_materialAsset = materialAssetOutcome.GetValue();
|
||||
m_materialTypeAsset = m_materialAsset->GetMaterialTypeAsset();
|
||||
m_parentMaterialAsset = {};
|
||||
|
||||
// The material instance is still needed for functor execution
|
||||
m_materialInstance = AZ::RPI::Material::Create(m_materialAsset);
|
||||
m_materialInstance = AZ::RPI::Material::Create(m_editData.m_materialAsset);
|
||||
if (!m_materialInstance)
|
||||
{
|
||||
AZ_Error("AZ::Render::EditorMaterialComponentInspector", false, "Material instance could not be created.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// We need a valid path to the material type source data because it's required for to get the property layout and assign to the new material
|
||||
const AZStd::string& materialTypePath = AZ::RPI::AssetUtils::GetSourcePathByAssetId(m_materialTypeAsset.GetId());
|
||||
if (materialTypePath.empty())
|
||||
{
|
||||
AZ_Error("AZ::Render::EditorMaterialComponentInspector", false, "Failed to locate source material type asset: %s", m_materialAssetId.ToString<AZStd::string>().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Getting the source info for the material type file to make sure that it exists
|
||||
// We also need to watch folder to generate a relative asset path for the material type
|
||||
bool result = false;
|
||||
AZ::Data::AssetInfo info;
|
||||
AZStd::string watchFolder;
|
||||
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(result, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, materialTypePath.c_str(), info, watchFolder);
|
||||
if (!result)
|
||||
{
|
||||
AZ_Error("AZ::Render::EditorMaterialComponentInspector", false, "Failed to get source file info and asset path: %s", materialTypePath.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// At this point, we should be ready to attempt to load the material type data
|
||||
auto materialTypeOutcome = AZ::RPI::MaterialUtils::LoadMaterialTypeSourceData(materialTypePath);
|
||||
if (!materialTypeOutcome.IsSuccess())
|
||||
{
|
||||
AZ_Error("AZ::Render::EditorMaterialComponentInspector", false, "Failed to load material type source data: %s", materialTypePath.c_str());
|
||||
return false;
|
||||
}
|
||||
m_materialTypeSourceData = materialTypeOutcome.GetValue();
|
||||
|
||||
// Get a list of all the editor functors to be used for property editor states
|
||||
auto propertyLayout = m_materialAsset->GetMaterialPropertiesLayout();
|
||||
const AZ::RPI::MaterialFunctorSourceData::EditorContext editorContext = AZ::RPI::MaterialFunctorSourceData::EditorContext(materialTypePath, propertyLayout);
|
||||
for (AZ::RPI::Ptr<AZ::RPI::MaterialFunctorSourceDataHolder> functorData : m_materialTypeSourceData.m_materialFunctorSourceData)
|
||||
auto propertyLayout = m_editData.m_materialAsset->GetMaterialPropertiesLayout();
|
||||
const AZ::RPI::MaterialFunctorSourceData::EditorContext editorContext =
|
||||
AZ::RPI::MaterialFunctorSourceData::EditorContext(m_editData.m_materialTypeSourcePath, propertyLayout);
|
||||
for (AZ::RPI::Ptr<AZ::RPI::MaterialFunctorSourceDataHolder> functorData : m_editData.m_materialTypeSourceData.m_materialFunctorSourceData)
|
||||
{
|
||||
AZ::RPI::MaterialFunctorSourceData::FunctorResult createResult = functorData->CreateFunctor(editorContext);
|
||||
|
||||
@@ -131,7 +101,7 @@ namespace AZ
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error("AZ::Render::EditorMaterialComponentInspector", false, "Material functors were not created: '%s'.", materialTypePath.c_str());
|
||||
AZ_Error("AZ::Render::EditorMaterialComponentInspector", false, "Material functors were not created: '%s'.", m_editData.m_materialTypeSourcePath.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,40 +123,61 @@ namespace AZ
|
||||
const AZStd::string& groupNameId = "Details";
|
||||
const AZStd::string& groupDisplayName = "Details";
|
||||
const AZStd::string& groupDescription = "";
|
||||
auto& group = m_groups[groupNameId];
|
||||
|
||||
AtomToolsFramework::DynamicPropertyConfig propertyConfig;
|
||||
propertyConfig.m_dataType = AtomToolsFramework::DynamicPropertyType::Asset;
|
||||
propertyConfig.m_id = "details.materialType";
|
||||
propertyConfig.m_nameId = "materialType";
|
||||
propertyConfig.m_displayName = "Material Type";
|
||||
propertyConfig.m_description = propertyConfig.m_displayName;
|
||||
propertyConfig.m_defaultValue = AZStd::any(m_materialAsset->GetMaterialTypeAsset());
|
||||
propertyConfig.m_originalValue = propertyConfig.m_defaultValue;
|
||||
propertyConfig.m_parentValue = propertyConfig.m_defaultValue;
|
||||
propertyConfig.m_readOnly = true;
|
||||
group.m_properties.emplace_back(propertyConfig);
|
||||
auto propertyGroupContainer = new QWidget(this);
|
||||
propertyGroupContainer->setLayout(new QHBoxLayout());
|
||||
|
||||
propertyConfig = {};
|
||||
propertyConfig.m_dataType = AtomToolsFramework::DynamicPropertyType::Asset;
|
||||
propertyConfig.m_id = "details.parentMaterial";
|
||||
propertyConfig.m_nameId = "parentMaterial";
|
||||
propertyConfig.m_displayName = "Parent Material";
|
||||
propertyConfig.m_description = propertyConfig.m_displayName;
|
||||
propertyConfig.m_defaultValue = AZStd::any(m_parentMaterialAsset);
|
||||
propertyConfig.m_originalValue = propertyConfig.m_defaultValue;
|
||||
propertyConfig.m_parentValue = propertyConfig.m_defaultValue;
|
||||
propertyConfig.m_readOnly = true;
|
||||
group.m_properties.emplace_back(propertyConfig);
|
||||
AzToolsFramework::Thumbnailer::SharedThumbnailKey thumbnailKey =
|
||||
MAKE_TKEY(AzToolsFramework::AssetBrowser::ProductThumbnailKey, m_editData.m_materialAssetId);
|
||||
auto thumbnailWidget = new AzToolsFramework::Thumbnailer::ThumbnailWidget(this);
|
||||
thumbnailWidget->setFixedSize(QSize(120, 120));
|
||||
thumbnailWidget->setVisible(true);
|
||||
thumbnailWidget->SetThumbnailKey(thumbnailKey, AzToolsFramework::Thumbnailer::ThumbnailContext::DefaultContext);
|
||||
propertyGroupContainer->layout()->addWidget(thumbnailWidget);
|
||||
|
||||
// Passing in same group as main and comparison instance to enable custom value comparison for highlighting modified properties
|
||||
auto propertyGroupWidget = new AtomToolsFramework::InspectorPropertyGroupWidget(&group, &group, group.TYPEINFO_Uuid(), this, this,
|
||||
[this](const AzToolsFramework::InstanceDataNode* source, const AzToolsFramework::InstanceDataNode* target) {
|
||||
AZ_UNUSED(source);
|
||||
const AtomToolsFramework::DynamicProperty* property = AtomToolsFramework::FindDynamicPropertyForInstanceDataNode(target);
|
||||
return property && AtomToolsFramework::ArePropertyValuesEqual(property->GetValue(), property->GetConfig().m_parentValue);
|
||||
});
|
||||
AddGroup(groupNameId, groupDisplayName, groupDescription, propertyGroupWidget);
|
||||
auto materialInfoWidget = new QLabel(this);
|
||||
QSizePolicy sizePolicy1(QSizePolicy::Ignored, QSizePolicy::Preferred);
|
||||
sizePolicy1.setHorizontalStretch(0);
|
||||
sizePolicy1.setVerticalStretch(0);
|
||||
sizePolicy1.setHeightForWidth(materialInfoWidget->sizePolicy().hasHeightForWidth());
|
||||
materialInfoWidget->setSizePolicy(sizePolicy1);
|
||||
materialInfoWidget->setMinimumSize(QSize(0, 0));
|
||||
materialInfoWidget->setMaximumSize(QSize(16777215, 16777215));
|
||||
materialInfoWidget->setTextFormat(Qt::AutoText);
|
||||
materialInfoWidget->setScaledContents(false);
|
||||
materialInfoWidget->setAlignment(Qt::AlignLeading | Qt::AlignLeft | Qt::AlignTop);
|
||||
materialInfoWidget->setWordWrap(true);
|
||||
|
||||
QFileInfo materialFileInfo(AZ::RPI::AssetUtils::GetProductPathByAssetId(m_editData.m_materialAsset.GetId()).c_str());
|
||||
QFileInfo materialSourceFileInfo(m_editData.m_materialSourcePath.c_str());
|
||||
QFileInfo materialTypeSourceFileInfo(m_editData.m_materialTypeSourcePath.c_str());
|
||||
QFileInfo materialParentSourceFileInfo(AZ::RPI::AssetUtils::GetSourcePathByAssetId(m_editData.m_materialParentAsset.GetId()).c_str());
|
||||
|
||||
QString materialInfo;
|
||||
materialInfo += tr("<table>");
|
||||
materialInfo += tr("<tr><td><b>Material Slot </b></td><td>%1</td></tr>").arg(m_slotName.c_str());
|
||||
if (!materialFileInfo.fileName().isEmpty())
|
||||
{
|
||||
materialInfo += tr("<tr><td><b>Material </b></td><td>%1</td></tr>").arg(materialFileInfo.fileName());
|
||||
}
|
||||
if (!materialTypeSourceFileInfo.fileName().isEmpty())
|
||||
{
|
||||
materialInfo += tr("<tr><td><b>Material Type </b></td><td>%1</td></tr>").arg(materialTypeSourceFileInfo.fileName());
|
||||
}
|
||||
if (!materialSourceFileInfo.fileName().isEmpty())
|
||||
{
|
||||
materialInfo += tr("<tr><td><b>Material Source </b></td><td>%1</td></tr>").arg(materialSourceFileInfo.fileName());
|
||||
}
|
||||
if (!materialParentSourceFileInfo.fileName().isEmpty())
|
||||
{
|
||||
materialInfo += tr("<tr><td><b>Material Parent </b></td><td>%1</td></tr>").arg(materialParentSourceFileInfo.fileName());
|
||||
}
|
||||
materialInfo += tr("</table>");
|
||||
materialInfoWidget->setText(materialInfo);
|
||||
|
||||
propertyGroupContainer->layout()->addWidget(materialInfoWidget);
|
||||
|
||||
AddGroup(groupNameId, groupDisplayName, groupDescription, propertyGroupContainer);
|
||||
}
|
||||
|
||||
void MaterialPropertyInspector::AddUvNamesGroup()
|
||||
@@ -196,7 +187,7 @@ namespace AZ
|
||||
const AZStd::string groupDescription = "UV set names in this material, which can be renamed to match those in the model.";
|
||||
auto& group = m_groups[groupNameId];
|
||||
|
||||
const RPI::MaterialUvNameMap& uvNameMap = m_materialAsset->GetMaterialTypeAsset()->GetUvNameMap();
|
||||
const RPI::MaterialUvNameMap& uvNameMap = m_editData.m_materialAsset->GetMaterialTypeAsset()->GetUvNameMap();
|
||||
group.m_properties.reserve(uvNameMap.size());
|
||||
|
||||
for (const RPI::UvNamePair& uvNamePair : uvNameMap)
|
||||
@@ -237,14 +228,14 @@ namespace AZ
|
||||
AddUvNamesGroup();
|
||||
|
||||
// Copy all of the properties from the material asset to the source data that will be exported
|
||||
for (const auto& groupDefinition : m_materialTypeSourceData.GetGroupDefinitionsInDisplayOrder())
|
||||
for (const auto& groupDefinition : m_editData.m_materialTypeSourceData.GetGroupDefinitionsInDisplayOrder())
|
||||
{
|
||||
const AZStd::string& groupNameId = groupDefinition.m_nameId;
|
||||
const AZStd::string& groupDisplayName = !groupDefinition.m_displayName.empty() ? groupDefinition.m_displayName : groupNameId;
|
||||
const AZStd::string& groupDescription = !groupDefinition.m_description.empty() ? groupDefinition.m_description : groupDisplayName;
|
||||
auto& group = m_groups[groupNameId];
|
||||
|
||||
const auto& propertyLayout = m_materialTypeSourceData.m_propertyLayout;
|
||||
const auto& propertyLayout = m_editData.m_materialTypeSourceData.m_propertyLayout;
|
||||
const auto& propertyListItr = propertyLayout.m_properties.find(groupNameId);
|
||||
if (propertyListItr != propertyLayout.m_properties.end())
|
||||
{
|
||||
@@ -255,10 +246,10 @@ namespace AZ
|
||||
AtomToolsFramework::ConvertToPropertyConfig(propertyConfig, propertyDefinition);
|
||||
|
||||
propertyConfig.m_id = AZ::RPI::MaterialPropertyId(groupNameId, propertyDefinition.m_nameId).GetFullName();
|
||||
const auto& propertyIndex = m_materialAsset->GetMaterialPropertiesLayout()->FindPropertyIndex(propertyConfig.m_id);
|
||||
propertyConfig.m_defaultValue = AtomToolsFramework::ConvertToEditableType(m_materialTypeAsset->GetDefaultPropertyValues()[propertyIndex.GetIndex()]);
|
||||
propertyConfig.m_parentValue = AtomToolsFramework::ConvertToEditableType(m_materialTypeAsset->GetDefaultPropertyValues()[propertyIndex.GetIndex()]);
|
||||
propertyConfig.m_originalValue = AtomToolsFramework::ConvertToEditableType(m_materialAsset->GetPropertyValues()[propertyIndex.GetIndex()]);
|
||||
const auto& propertyIndex = m_editData.m_materialAsset->GetMaterialPropertiesLayout()->FindPropertyIndex(propertyConfig.m_id);
|
||||
propertyConfig.m_defaultValue = AtomToolsFramework::ConvertToEditableType(m_editData.m_materialTypeAsset->GetDefaultPropertyValues()[propertyIndex.GetIndex()]);
|
||||
propertyConfig.m_parentValue = AtomToolsFramework::ConvertToEditableType(m_editData.m_materialTypeAsset->GetDefaultPropertyValues()[propertyIndex.GetIndex()]);
|
||||
propertyConfig.m_originalValue = AtomToolsFramework::ConvertToEditableType(m_editData.m_materialAsset->GetPropertyValues()[propertyIndex.GetIndex()]);
|
||||
group.m_properties.emplace_back(propertyConfig);
|
||||
}
|
||||
}
|
||||
@@ -283,7 +274,7 @@ namespace AZ
|
||||
{
|
||||
if (m_propertyChangedCallback)
|
||||
{
|
||||
m_propertyChangedCallback(m_materialPropertyOverrideMap);
|
||||
m_propertyChangedCallback(m_editData.m_materialPropertyOverrideMap);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,15 +356,15 @@ namespace AZ
|
||||
|
||||
void MaterialPropertyInspector::SetOverrides(const MaterialPropertyOverrideMap& propertyOverrideMap)
|
||||
{
|
||||
m_materialPropertyOverrideMap = propertyOverrideMap;
|
||||
m_editData.m_materialPropertyOverrideMap = propertyOverrideMap;
|
||||
|
||||
for (auto& group : m_groups)
|
||||
{
|
||||
for (auto& property : group.second.m_properties)
|
||||
{
|
||||
const AtomToolsFramework::DynamicPropertyConfig& propertyConfig = property.GetConfig();
|
||||
const auto overrideItr = m_materialPropertyOverrideMap.find(propertyConfig.m_id);
|
||||
const auto& editValue = overrideItr != m_materialPropertyOverrideMap.end() ? overrideItr->second : propertyConfig.m_originalValue;
|
||||
const auto overrideItr = m_editData.m_materialPropertyOverrideMap.find(propertyConfig.m_id);
|
||||
const auto& editValue = overrideItr != m_editData.m_materialPropertyOverrideMap.end() ? overrideItr->second : propertyConfig.m_originalValue;
|
||||
|
||||
// This first converts to an acceptable runtime type in case the value came from script
|
||||
const auto propertyIndex = m_materialInstance->FindPropertyIndex(property.GetId());
|
||||
@@ -400,6 +391,82 @@ namespace AZ
|
||||
RebuildAll();
|
||||
}
|
||||
|
||||
bool MaterialPropertyInspector::SaveMaterial() const
|
||||
{
|
||||
const QString defaultPath = AtomToolsFramework::GetUniqueFileInfo(
|
||||
QString(AZ::IO::FileIOBase::GetInstance()->GetAlias("@devassets@")) +
|
||||
AZ_CORRECT_FILESYSTEM_SEPARATOR + "Materials" +
|
||||
AZ_CORRECT_FILESYSTEM_SEPARATOR + "untitled." +
|
||||
AZ::RPI::MaterialSourceData::Extension).absoluteFilePath();
|
||||
|
||||
const QString saveFilePath = AtomToolsFramework::GetSaveFileInfo(defaultPath).absoluteFilePath();
|
||||
if (saveFilePath.isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!EditorMaterialComponentUtil::SaveSourceMaterialFromEditData(saveFilePath.toUtf8().constData(), m_editData))
|
||||
{
|
||||
AZ_Warning("AZ::Render::EditorMaterialComponentInspector", false, "Failed to save material data.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MaterialPropertyInspector::SaveMaterialToSource() const
|
||||
{
|
||||
const QString saveFilePath = AtomToolsFramework::GetSaveFileInfo(m_editData.m_materialSourcePath.c_str()).absoluteFilePath();
|
||||
if (saveFilePath.isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!EditorMaterialComponentUtil::SaveSourceMaterialFromEditData(saveFilePath.toUtf8().constData(), m_editData))
|
||||
{
|
||||
AZ_Warning("AZ::Render::EditorMaterialComponentInspector", false, "Failed to save material data.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MaterialPropertyInspector::HasMaterialSource() const
|
||||
{
|
||||
return !m_editData.m_materialSourcePath.empty() &&
|
||||
AZ::StringFunc::Path::IsExtension(m_editData.m_materialSourcePath.c_str(), AZ::RPI::MaterialSourceData::Extension);
|
||||
}
|
||||
|
||||
bool MaterialPropertyInspector::HasMaterialParentSource() const
|
||||
{
|
||||
return !m_editData.m_materialParentSourcePath.empty() &&
|
||||
AZ::StringFunc::Path::IsExtension(
|
||||
m_editData.m_materialParentSourcePath.c_str(), AZ::RPI::MaterialSourceData::Extension);
|
||||
}
|
||||
|
||||
void MaterialPropertyInspector::OpenMaterialSourceInEditor() const
|
||||
{
|
||||
if (HasMaterialSource())
|
||||
{
|
||||
EditorMaterialSystemComponentRequestBus::Broadcast(
|
||||
&EditorMaterialSystemComponentRequestBus::Events::OpenInMaterialEditor, m_editData.m_materialSourcePath);
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialPropertyInspector::OpenMaterialParentSourceInEditor() const
|
||||
{
|
||||
if (HasMaterialParentSource())
|
||||
{
|
||||
EditorMaterialSystemComponentRequestBus::Broadcast(
|
||||
&EditorMaterialSystemComponentRequestBus::Events::OpenInMaterialEditor, m_editData.m_materialParentSourcePath);
|
||||
}
|
||||
}
|
||||
|
||||
const EditorMaterialComponentUtil::MaterialEditData& MaterialPropertyInspector::GetEditData() const
|
||||
{
|
||||
return m_editData;
|
||||
}
|
||||
|
||||
void MaterialPropertyInspector::BeforePropertyModified(AzToolsFramework::InstanceDataNode* pNode)
|
||||
{
|
||||
// For some reason the reflected property editor notifications are not symmetrical
|
||||
@@ -422,7 +489,7 @@ namespace AZ
|
||||
{
|
||||
if (m_activeProperty == property)
|
||||
{
|
||||
m_materialPropertyOverrideMap[m_activeProperty->GetId()] = m_activeProperty->GetValue();
|
||||
m_editData.m_materialPropertyOverrideMap[m_activeProperty->GetId()] = m_activeProperty->GetValue();
|
||||
UpdateMaterialInstanceProperty(*m_activeProperty);
|
||||
RunPropertyChangedCallback();
|
||||
}
|
||||
@@ -438,7 +505,7 @@ namespace AZ
|
||||
{
|
||||
if (m_activeProperty == property)
|
||||
{
|
||||
m_materialPropertyOverrideMap[m_activeProperty->GetId()] = m_activeProperty->GetValue();
|
||||
m_editData.m_materialPropertyOverrideMap[m_activeProperty->GetId()] = m_activeProperty->GetValue();
|
||||
UpdateMaterialInstanceProperty(*m_activeProperty);
|
||||
RunPropertyChangedCallback();
|
||||
RunEditorMaterialFunctors();
|
||||
@@ -447,7 +514,9 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
bool OpenInspectorDialog(const AZ::Data::AssetId& assetId, MaterialPropertyOverrideMap propertyOverrideMap, PropertyChangedCallback propertyChangedCallback)
|
||||
bool OpenInspectorDialog(
|
||||
const AZStd::string& slotName, const AZ::Data::AssetId& assetId, MaterialPropertyOverrideMap propertyOverrideMap,
|
||||
PropertyChangedCallback propertyChangedCallback)
|
||||
{
|
||||
QWidget* activeWindow = nullptr;
|
||||
AzToolsFramework::EditorWindowRequestBus::BroadcastResult(activeWindow, &AzToolsFramework::EditorWindowRequests::GetAppMainWindow);
|
||||
@@ -456,7 +525,7 @@ namespace AZ
|
||||
QDialog dialog(activeWindow);
|
||||
dialog.setWindowTitle("Material Inspector");
|
||||
|
||||
MaterialPropertyInspector* inspector = new MaterialPropertyInspector(assetId, propertyChangedCallback, &dialog);
|
||||
MaterialPropertyInspector* inspector = new MaterialPropertyInspector(slotName, assetId, propertyChangedCallback, &dialog);
|
||||
if (!inspector->LoadMaterial())
|
||||
{
|
||||
return false;
|
||||
@@ -465,48 +534,47 @@ namespace AZ
|
||||
inspector->Populate();
|
||||
inspector->SetOverrides(propertyOverrideMap);
|
||||
|
||||
// Create the bottom row of the dialog with action buttons for exporting or canceling the operation
|
||||
QWidget* buttonRow = new QWidget(&dialog);
|
||||
buttonRow->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
|
||||
// Create the menu bottom row with actions for exporting or canceling the operation
|
||||
QToolButton* menuButton = new QToolButton(&dialog);
|
||||
menuButton->setAutoRaise(true);
|
||||
menuButton->setIcon(QIcon(":/Cards/img/UI20/Cards/menu_ico.svg"));
|
||||
menuButton->setVisible(true);
|
||||
QObject::connect(menuButton, &QToolButton::clicked, &dialog, [&]() {
|
||||
QAction* action = nullptr;
|
||||
|
||||
QPushButton* revertButton = new QPushButton("Revert", buttonRow);
|
||||
QObject::connect(revertButton, &QPushButton::clicked, revertButton, [inspector, propertyOverrideMap] {
|
||||
inspector->SetOverrides(propertyOverrideMap);
|
||||
});
|
||||
QMenu menu(&dialog);
|
||||
action = menu.addAction("Clear Overrides", [&] { inspector->SetOverrides(MaterialPropertyOverrideMap()); });
|
||||
action = menu.addAction("Revert Changes", [&] { inspector->SetOverrides(propertyOverrideMap); });
|
||||
|
||||
QPushButton* clearButton = new QPushButton("Clear", buttonRow);
|
||||
QObject::connect(clearButton, &QPushButton::clicked, clearButton, [inspector] {
|
||||
inspector->SetOverrides(MaterialPropertyOverrideMap());
|
||||
});
|
||||
menu.addSeparator();
|
||||
action = menu.addAction("Confirm Changes", [&] { dialog.accept(); });
|
||||
action = menu.addAction("Cancel Changes", [&] { dialog.reject(); });
|
||||
|
||||
QPushButton* confirmButton = new QPushButton("Confirm", buttonRow);
|
||||
QObject::connect(confirmButton, &QPushButton::clicked, confirmButton, [&dialog] {
|
||||
dialog.accept();
|
||||
});
|
||||
menu.addSeparator();
|
||||
action = menu.addAction("Save Material", [&] { inspector->SaveMaterial(); });
|
||||
action = menu.addAction("Save Material To Source", [&] { inspector->SaveMaterialToSource(); });
|
||||
action->setEnabled(inspector->HasMaterialSource());
|
||||
|
||||
QPushButton* cancelButton = new QPushButton("Cancel", buttonRow);
|
||||
QObject::connect(cancelButton, &QPushButton::clicked, cancelButton, [inspector, propertyOverrideMap, &dialog] {
|
||||
inspector->SetOverrides(propertyOverrideMap);
|
||||
dialog.reject();
|
||||
});
|
||||
menu.addSeparator();
|
||||
action = menu.addAction("Open Source Material In Editor", [&] { inspector->OpenMaterialSourceInEditor(); });
|
||||
action->setEnabled(inspector->HasMaterialSource());
|
||||
action = menu.addAction("Open Parent Material In Editor", [&] { inspector->OpenMaterialParentSourceInEditor(); });
|
||||
action->setEnabled(inspector->HasMaterialParentSource());
|
||||
menu.exec(QCursor::pos());
|
||||
});
|
||||
|
||||
QHBoxLayout* buttonLayout = new QHBoxLayout(buttonRow);
|
||||
buttonLayout->addStretch();
|
||||
buttonLayout->addWidget(revertButton);
|
||||
buttonLayout->addWidget(clearButton);
|
||||
buttonLayout->addWidget(confirmButton);
|
||||
buttonLayout->addWidget(cancelButton);
|
||||
QObject::connect(&dialog, &QDialog::rejected, &dialog, [&] { inspector->SetOverrides(propertyOverrideMap); });
|
||||
|
||||
QVBoxLayout* dialogLayout = new QVBoxLayout(&dialog);
|
||||
dialogLayout->addWidget(menuButton);
|
||||
dialogLayout->addWidget(inspector);
|
||||
dialogLayout->addWidget(buttonRow);
|
||||
dialog.setLayout(dialogLayout);
|
||||
|
||||
// Forcing the initial dialog size to accomodate typical content.
|
||||
// Temporarily settng fixed size because dialog.show/exec invokes WindowDecorationWrapper::showEvent.
|
||||
// This forces the dialog to be centered and sized based on the layout of content.
|
||||
// Resizing the dialog after show will not be centered and moving the dialog programatically doesn't m0ve the custmk frame.
|
||||
dialog.setFixedSize(300, 600);
|
||||
dialog.setFixedSize(500, 800);
|
||||
dialog.show();
|
||||
|
||||
// Removing fixed size to allow drag resizing
|
||||
|
||||
+23
-18
@@ -13,19 +13,15 @@
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <Atom/Feature/Material/MaterialAssignment.h>
|
||||
#include <Atom/RPI.Edit/Material/MaterialSourceData.h>
|
||||
#include <Atom/RPI.Edit/Material/MaterialTypeSourceData.h>
|
||||
#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
|
||||
|
||||
#include <AzCore/std/containers/unordered_map.h>
|
||||
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI_Internals.h>
|
||||
|
||||
#include <AtomToolsFramework/DynamicProperty/DynamicPropertyGroup.h>
|
||||
#include <AtomToolsFramework/Inspector/InspectorWidget.h>
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <AzCore/std/containers/unordered_map.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzCore/std/function/function_base.h>
|
||||
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI_Internals.h>
|
||||
#include <Material/EditorMaterialComponentUtil.h>
|
||||
#endif
|
||||
|
||||
namespace AZ
|
||||
@@ -44,7 +40,9 @@ namespace AZ
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(MaterialPropertyInspector, AZ::SystemAllocator, 0);
|
||||
|
||||
explicit MaterialPropertyInspector(const AZ::Data::AssetId& assetId, PropertyChangedCallback propertyChangedCallback, QWidget* parent = nullptr);
|
||||
explicit MaterialPropertyInspector(
|
||||
const AZStd::string& slotName, const AZ::Data::AssetId& assetId, PropertyChangedCallback propertyChangedCallback,
|
||||
QWidget* parent = nullptr);
|
||||
~MaterialPropertyInspector() override;
|
||||
|
||||
bool LoadMaterial();
|
||||
@@ -56,6 +54,14 @@ namespace AZ
|
||||
|
||||
void SetOverrides(const MaterialPropertyOverrideMap& propertyOverrideMap);
|
||||
|
||||
bool SaveMaterial() const;
|
||||
bool SaveMaterialToSource() const;
|
||||
bool HasMaterialSource() const;
|
||||
bool HasMaterialParentSource() const;
|
||||
void OpenMaterialSourceInEditor() const;
|
||||
void OpenMaterialParentSourceInEditor() const;
|
||||
const EditorMaterialComponentUtil::MaterialEditData& GetEditData() const;
|
||||
|
||||
private:
|
||||
|
||||
// AzToolsFramework::IPropertyEditorNotify overrides...
|
||||
@@ -76,20 +82,19 @@ namespace AZ
|
||||
// Tracking the property that is actively being edited in the inspector
|
||||
const AtomToolsFramework::DynamicProperty* m_activeProperty = {};
|
||||
|
||||
AZStd::string m_slotName;
|
||||
AZ::Data::AssetId m_materialAssetId = {};
|
||||
MaterialPropertyOverrideMap m_materialPropertyOverrideMap = {};
|
||||
EditorMaterialComponentUtil::MaterialEditData m_editData;
|
||||
PropertyChangedCallback m_propertyChangedCallback = {};
|
||||
AZ::Data::Asset<AZ::RPI::MaterialAsset> m_materialAsset = {};
|
||||
AZ::Data::Asset<AZ::RPI::MaterialTypeAsset> m_materialTypeAsset = {};
|
||||
AZ::Data::Asset<AZ::RPI::MaterialAsset> m_parentMaterialAsset = {};
|
||||
AZ::Data::Instance<AZ::RPI::Material> m_materialInstance = {};
|
||||
AZ::RPI::MaterialTypeSourceData m_materialTypeSourceData;
|
||||
AZStd::vector<AZ::RPI::Ptr<AZ::RPI::MaterialFunctor>> m_editorFunctors = {};
|
||||
AZ::RPI::MaterialPropertyFlags m_dirtyPropertyFlags = {};
|
||||
AZStd::unordered_map<AZStd::string, AtomToolsFramework::DynamicPropertyGroup> m_groups = {};
|
||||
};
|
||||
|
||||
bool OpenInspectorDialog(const AZ::Data::AssetId& assetId, MaterialPropertyOverrideMap propertyOverrideMap, PropertyChangedCallback propertyChangedCallback);
|
||||
bool OpenInspectorDialog(
|
||||
const AZStd::string& slotName, const AZ::Data::AssetId& assetId, MaterialPropertyOverrideMap propertyOverrideMap,
|
||||
PropertyChangedCallback propertyChangedCallback);
|
||||
} // namespace EditorMaterialComponentInspector
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
+1
-1
@@ -242,7 +242,7 @@ namespace AZ
|
||||
|
||||
if (m_materialAsset.GetId().IsValid())
|
||||
{
|
||||
if (EditorMaterialComponentInspector::OpenInspectorDialog(m_materialAsset.GetId(), m_propertyOverrides, applyPropertyChangedCallback))
|
||||
if (EditorMaterialComponentInspector::OpenInspectorDialog(GetLabel(), m_materialAsset.GetId(), m_propertyOverrides, applyPropertyChangedCallback))
|
||||
{
|
||||
OnMaterialChanged();
|
||||
}
|
||||
|
||||
+176
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Material/EditorMaterialComponentUtil.h>
|
||||
|
||||
#include <Atom/RPI.Edit/Common/AssetUtils.h>
|
||||
#include <Atom/RPI.Edit/Common/JsonUtils.h>
|
||||
#include <Atom/RPI.Edit/Material/MaterialPropertyId.h>
|
||||
#include <Atom/RPI.Edit/Material/MaterialSourceData.h>
|
||||
#include <Atom/RPI.Edit/Material/MaterialTypeSourceData.h>
|
||||
#include <Atom/RPI.Edit/Material/MaterialUtils.h>
|
||||
#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
|
||||
#include <Atom/RPI.Reflect/Material/MaterialPropertiesLayout.h>
|
||||
#include <Atom/RPI.Reflect/Material/MaterialTypeAsset.h>
|
||||
#include <AzFramework/API/ApplicationAPI.h>
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
namespace EditorMaterialComponentUtil
|
||||
{
|
||||
bool LoadMaterialEditDataFromAssetId(const AZ::Data::AssetId& assetId, MaterialEditData& editData)
|
||||
{
|
||||
editData = MaterialEditData();
|
||||
|
||||
if (!assetId.IsValid())
|
||||
{
|
||||
AZ_Warning("AZ::Render::EditorMaterialComponentUtil", false, "Attempted to load material data for invalid asset id.");
|
||||
return false;
|
||||
}
|
||||
|
||||
editData.m_materialAssetId = assetId;
|
||||
|
||||
// Load the originating product asset from which the new source has set will be generated
|
||||
auto materialAssetOutcome = AZ::RPI::AssetUtils::LoadAsset<AZ::RPI::MaterialAsset>(editData.m_materialAssetId);
|
||||
if (!materialAssetOutcome)
|
||||
{
|
||||
AZ_Error("AZ::Render::EditorMaterialComponentUtil", false, "Failed to load material asset: %s", editData.m_materialAssetId.ToString<AZStd::string>().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
editData.m_materialAsset = materialAssetOutcome.GetValue();
|
||||
editData.m_materialTypeAsset = editData.m_materialAsset->GetMaterialTypeAsset();
|
||||
editData.m_materialParentAsset = {};
|
||||
|
||||
editData.m_materialSourcePath = AZ::RPI::AssetUtils::GetSourcePathByAssetId(editData.m_materialAsset.GetId());
|
||||
if (AzFramework::StringFunc::Path::IsExtension(
|
||||
editData.m_materialSourcePath.c_str(), AZ::RPI::MaterialSourceData::Extension))
|
||||
{
|
||||
if (!AZ::RPI::JsonUtils::LoadObjectFromFile(editData.m_materialSourcePath, editData.m_materialSourceData))
|
||||
{
|
||||
AZ_Error("AZ::Render::EditorMaterialComponentUtil", false, "Material source data could not be loaded: '%s'.", editData.m_materialSourcePath.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!editData.m_materialSourceData.m_parentMaterial.empty())
|
||||
{
|
||||
// There is a parent for this material
|
||||
auto parentMaterialResult = AZ::RPI::AssetUtils::LoadAsset<AZ::RPI::MaterialAsset>(editData.m_materialSourcePath, editData.m_materialSourceData.m_parentMaterial);
|
||||
if (!parentMaterialResult)
|
||||
{
|
||||
AZ_Error("AZ::Render::EditorMaterialComponentUtil", false, "Parent material asset could not be loaded: '%s'.", editData.m_materialSourceData.m_parentMaterial.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
editData.m_materialParentAsset = parentMaterialResult.GetValue();
|
||||
editData.m_materialParentSourcePath = AZ::RPI::AssetUtils::GetSourcePathByAssetId(editData.m_materialParentAsset.GetId());
|
||||
}
|
||||
|
||||
// We need a valid path to the material type source data to get the property layout and assign to the new material
|
||||
editData.m_materialTypeSourcePath = AZ::RPI::AssetUtils::GetSourcePathByAssetId(editData.m_materialTypeAsset.GetId());
|
||||
if (editData.m_materialTypeSourcePath.empty())
|
||||
{
|
||||
AZ_Error("AZ::Render::EditorMaterialComponentUtil", false, "Failed to locate source material type asset: %s", editData.m_materialAssetId.ToString<AZStd::string>().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load the material type source data
|
||||
auto materialTypeOutcome = AZ::RPI::MaterialUtils::LoadMaterialTypeSourceData(editData.m_materialTypeSourcePath);
|
||||
if (!materialTypeOutcome.IsSuccess())
|
||||
{
|
||||
AZ_Error("AZ::Render::EditorMaterialComponentUtil", false, "Failed to load material type source data: %s", editData.m_materialTypeSourcePath.c_str());
|
||||
return false;
|
||||
}
|
||||
editData.m_materialTypeSourceData = materialTypeOutcome.GetValue();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SaveSourceMaterialFromEditData(const AZStd::string& path, const MaterialEditData& editData)
|
||||
{
|
||||
// Getting the source info for the material type file to make sure that it exists
|
||||
// We also need to watch folder to generate a relative asset path for the material type
|
||||
bool result = false;
|
||||
AZ::Data::AssetInfo info;
|
||||
AZStd::string watchFolder;
|
||||
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
|
||||
result, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath,
|
||||
editData.m_materialTypeSourcePath.c_str(), info, watchFolder);
|
||||
if (!result)
|
||||
{
|
||||
AZ_Error("AZ::Render::EditorMaterialComponentUtil", false, "Failed to get source file info and asset path while attempting to export: %s", path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Construct the material source data object that will be exported
|
||||
AZ::RPI::MaterialSourceData exportData;
|
||||
exportData.m_propertyLayoutVersion = editData.m_materialTypeSourceData.m_propertyLayout.m_version;
|
||||
|
||||
// Converting absolute material paths to asset relative paths
|
||||
exportData.m_materialType = editData.m_materialTypeSourcePath;
|
||||
AzFramework::ApplicationRequests::Bus::Broadcast(
|
||||
&AzFramework::ApplicationRequests::Bus::Events::MakePathRelative, exportData.m_materialType, watchFolder.c_str());
|
||||
|
||||
exportData.m_parentMaterial = editData.m_materialParentSourcePath;
|
||||
AzFramework::ApplicationRequests::Bus::Broadcast(
|
||||
&AzFramework::ApplicationRequests::Bus::Events::MakePathRelative, exportData.m_parentMaterial, watchFolder.c_str());
|
||||
|
||||
// Copy all of the properties from the material asset to the source data that will be exported
|
||||
result = true;
|
||||
editData.m_materialTypeSourceData.EnumerateProperties([&](const AZStd::string& groupNameId, const AZStd::string& propertyNameId, const auto& propertyDefinition) {
|
||||
const AZ::RPI::MaterialPropertyId propertyId(groupNameId, propertyNameId);
|
||||
const AZ::RPI::MaterialPropertyIndex propertyIndex =
|
||||
editData.m_materialAsset->GetMaterialPropertiesLayout()->FindPropertyIndex(propertyId.GetFullName());
|
||||
|
||||
AZ::RPI::MaterialPropertyValue propertyValue = editData.m_materialAsset->GetPropertyValues()[propertyIndex.GetIndex()];
|
||||
|
||||
AZ::RPI::MaterialPropertyValue propertyValueDefault = propertyDefinition.m_value;
|
||||
if (editData.m_materialParentAsset.IsReady())
|
||||
{
|
||||
propertyValueDefault = editData.m_materialParentAsset->GetPropertyValues()[propertyIndex.GetIndex()];
|
||||
}
|
||||
|
||||
// Check for and apply any property overrides before saving property values
|
||||
auto propertyOverrideItr = editData.m_materialPropertyOverrideMap.find(propertyId.GetFullName());
|
||||
if(propertyOverrideItr != editData.m_materialPropertyOverrideMap.end())
|
||||
{
|
||||
propertyValue = AZ::RPI::MaterialPropertyValue::FromAny(propertyOverrideItr->second);
|
||||
}
|
||||
|
||||
if (!editData.m_materialTypeSourceData.ConvertPropertyValueToSourceDataFormat(propertyDefinition, propertyValue))
|
||||
{
|
||||
AZ_Error("AZ::Render::EditorMaterialComponentUtil", false, "Failed to export: %s", path.c_str());
|
||||
result = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't export values if they are the same as the material type or parent
|
||||
if (propertyValueDefault == propertyValue)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
exportData.m_properties[groupNameId][propertyDefinition.m_nameId].m_value = propertyValue;
|
||||
return true;
|
||||
});
|
||||
|
||||
return result && AZ::RPI::JsonUtils::SaveObjectToFile(path, exportData);
|
||||
}
|
||||
} // namespace EditorMaterialComponentUtil
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
//#include <AtomLyIntegration/CommonFeatures/moc_EditorMaterialComponentUtil.cpp>
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Atom/Feature/Material/MaterialAssignment.h>
|
||||
#include <Atom/RPI.Edit/Material/MaterialSourceData.h>
|
||||
#include <Atom/RPI.Edit/Material/MaterialTypeSourceData.h>
|
||||
#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
|
||||
#include <Atom/RPI.Reflect/Material/MaterialTypeAsset.h>
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
namespace EditorMaterialComponentUtil
|
||||
{
|
||||
struct MaterialEditData
|
||||
{
|
||||
AZ::Data::AssetId m_materialAssetId = {};
|
||||
AZ::Data::Asset<AZ::RPI::MaterialAsset> m_materialAsset = {};
|
||||
AZ::Data::Asset<AZ::RPI::MaterialTypeAsset> m_materialTypeAsset = {};
|
||||
AZ::Data::Asset<AZ::RPI::MaterialAsset> m_materialParentAsset = {};
|
||||
AZ::RPI::MaterialSourceData m_materialSourceData;
|
||||
AZ::RPI::MaterialTypeSourceData m_materialTypeSourceData;
|
||||
AZStd::string m_materialSourcePath;
|
||||
AZStd::string m_materialTypeSourcePath;
|
||||
AZStd::string m_materialParentSourcePath;
|
||||
MaterialPropertyOverrideMap m_materialPropertyOverrideMap = {};
|
||||
};
|
||||
|
||||
bool LoadMaterialEditDataFromAssetId(const AZ::Data::AssetId& assetId, MaterialEditData& editData);
|
||||
bool SaveSourceMaterialFromEditData(const AZStd::string& path, const MaterialEditData& editData);
|
||||
} // namespace EditorMaterialComponentUtil
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
+4
-13
@@ -25,7 +25,7 @@
|
||||
|
||||
#include <AtomToolsFramework/Util/Util.h>
|
||||
|
||||
#include <Material/Thumbnails/MaterialThumbnail.h>
|
||||
#include <Material/MaterialThumbnail.h>
|
||||
|
||||
// Disables warning messages triggered by the Qt library
|
||||
// 4251: class needs to have dll-interface to be used by clients of class
|
||||
@@ -95,8 +95,6 @@ namespace AZ
|
||||
{
|
||||
AzFramework::TargetManagerClient::Bus::Handler::BusConnect();
|
||||
EditorMaterialSystemComponentRequestBus::Handler::BusConnect();
|
||||
m_materialPreviewerFactory = AZStd::make_unique <LyIntegration::MaterialPreviewerFactory>();
|
||||
AzToolsFramework::AssetBrowser::PreviewerRequestBus::Handler::BusConnect();
|
||||
AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusConnect();
|
||||
AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusConnect();
|
||||
AzToolsFramework::EditorMenuNotificationBus::Handler::BusConnect();
|
||||
@@ -108,11 +106,9 @@ namespace AZ
|
||||
{
|
||||
AzFramework::TargetManagerClient::Bus::Handler::BusDisconnect();
|
||||
EditorMaterialSystemComponentRequestBus::Handler::BusDisconnect();
|
||||
AzToolsFramework::AssetBrowser::PreviewerRequestBus::Handler::BusDisconnect();
|
||||
AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusDisconnect();
|
||||
AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusDisconnect();
|
||||
AzToolsFramework::EditorMenuNotificationBus::Handler::BusDisconnect();
|
||||
m_materialPreviewerFactory.reset();
|
||||
|
||||
TeardownThumbnails();
|
||||
|
||||
@@ -157,16 +153,11 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
const AzToolsFramework::AssetBrowser::PreviewerFactory* EditorMaterialSystemComponent::GetPreviewerFactory(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) const
|
||||
{
|
||||
return m_materialPreviewerFactory->IsEntrySupported(entry) ? m_materialPreviewerFactory.get() : nullptr;
|
||||
}
|
||||
|
||||
void EditorMaterialSystemComponent::OnApplicationAboutToStop()
|
||||
{
|
||||
TeardownThumbnails();
|
||||
}
|
||||
|
||||
|
||||
void EditorMaterialSystemComponent::OnPopulateToolMenuItems()
|
||||
{
|
||||
if (!m_openMaterialEditorAction)
|
||||
@@ -198,7 +189,7 @@ namespace AZ
|
||||
using namespace LyIntegration;
|
||||
|
||||
ThumbnailerRequestsBus::Broadcast(&ThumbnailerRequests::RegisterThumbnailProvider,
|
||||
MAKE_TCACHE(MaterialThumbnailCache),
|
||||
MAKE_TCACHE(Thumbnails::MaterialThumbnailCache),
|
||||
ThumbnailContext::DefaultContext);
|
||||
}
|
||||
|
||||
@@ -208,7 +199,7 @@ namespace AZ
|
||||
using namespace LyIntegration;
|
||||
|
||||
ThumbnailerRequestsBus::Broadcast(&ThumbnailerRequests::UnregisterThumbnailProvider,
|
||||
MaterialThumbnailCache::ProviderName,
|
||||
Thumbnails::MaterialThumbnailCache::ProviderName,
|
||||
ThumbnailContext::DefaultContext);
|
||||
}
|
||||
|
||||
|
||||
+1
-11
@@ -16,16 +16,12 @@
|
||||
#include <AzFramework/Application/Application.h>
|
||||
#include <AzFramework/TargetManagement/TargetManagementAPI.h>
|
||||
|
||||
#include <AzToolsFramework/AssetBrowser/Previewer/PreviewerBus.h>
|
||||
#include <AzToolsFramework/Thumbnails/Thumbnail.h>
|
||||
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
|
||||
#include <AzToolsFramework/Viewport/ActionBus.h>
|
||||
|
||||
#include <AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentRequestBus.h>
|
||||
|
||||
#include <Material/Preview/MaterialPreviewerFactory.h>
|
||||
#include <Material/Thumbnails/MaterialThumbnail.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
@@ -35,7 +31,6 @@ namespace AZ
|
||||
: public AZ::Component
|
||||
, private EditorMaterialSystemComponentRequestBus::Handler
|
||||
, private AzFramework::TargetManagerClient::Bus::Handler
|
||||
, private AzToolsFramework::AssetBrowser::PreviewerRequestBus::Handler
|
||||
, private AzFramework::ApplicationLifecycleEvents::Bus::Handler
|
||||
, public AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler
|
||||
, public AzToolsFramework::EditorMenuNotificationBus::Handler
|
||||
@@ -63,10 +58,7 @@ namespace AZ
|
||||
//! AzFramework::TargetManagerClient::Bus::Handler overrides...
|
||||
void TargetJoinedNetwork(AzFramework::TargetInfo info) override;
|
||||
void TargetLeftNetwork(AzFramework::TargetInfo info) override;
|
||||
|
||||
// AzToolsFramework::AssetBrowser::PreviewerRequestBus::Handler overrides...
|
||||
const AzToolsFramework::AssetBrowser::PreviewerFactory* GetPreviewerFactory(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) const override;
|
||||
|
||||
|
||||
// AzFramework::ApplicationLifecycleEvents overrides...
|
||||
void OnApplicationAboutToStop() override;
|
||||
|
||||
@@ -83,8 +75,6 @@ namespace AZ
|
||||
// Material Editor target for interprocess communication with MaterialEditor
|
||||
AzFramework::TargetInfo m_materialEditorTarget;
|
||||
|
||||
AZStd::unique_ptr<LyIntegration::MaterialPreviewerFactory> m_materialPreviewerFactory;
|
||||
|
||||
QAction* m_openMaterialEditorAction = nullptr;
|
||||
};
|
||||
} // namespace Render
|
||||
|
||||
+5
@@ -67,6 +67,11 @@ namespace AZ
|
||||
incompatible.push_back(AZ_CRC("MaterialProviderService", 0x64849a6b));
|
||||
}
|
||||
|
||||
void MaterialComponentController::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
|
||||
{
|
||||
required.push_back(AZ_CRC("MaterialReceiverService", 0x0d1a6a74));
|
||||
}
|
||||
|
||||
MaterialComponentController::MaterialComponentController(const MaterialComponentConfig& config)
|
||||
: m_configuration(config)
|
||||
{
|
||||
|
||||
+1
@@ -38,6 +38,7 @@ namespace AZ
|
||||
static void Reflect(ReflectContext* context);
|
||||
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
|
||||
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
|
||||
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
|
||||
|
||||
MaterialComponentController() = default;
|
||||
MaterialComponentController(const MaterialComponentConfig& config);
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
#include <Source/Material/MaterialThumbnail.h>
|
||||
#include <Source/Thumbnails/ThumbnailUtils.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace LyIntegration
|
||||
{
|
||||
namespace Thumbnails
|
||||
{
|
||||
const int MaterialThumbnailSize = 200;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// MaterialThumbnail
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
MaterialThumbnail::MaterialThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey key, int thumbnailSize)
|
||||
: Thumbnail(key, thumbnailSize)
|
||||
{
|
||||
m_assetId = GetAssetId(key, RPI::MaterialAsset::RTTI_Type());
|
||||
if (!m_assetId.IsValid())
|
||||
{
|
||||
AZ_Error("MaterialThumbnail", false, "Failed to find matching assetId for the thumbnailKey.");
|
||||
m_state = State::Failed;
|
||||
return;
|
||||
}
|
||||
|
||||
AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Handler::BusConnect(key);
|
||||
AzFramework::AssetCatalogEventBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
void MaterialThumbnail::LoadThread()
|
||||
{
|
||||
AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::QueueEvent(
|
||||
RPI::MaterialAsset::RTTI_Type(),
|
||||
&AzToolsFramework::Thumbnailer::ThumbnailerRendererRequests::RenderThumbnail,
|
||||
m_key,
|
||||
m_thumbnailSize);
|
||||
// wait for response from thumbnail renderer
|
||||
m_renderWait.acquire();
|
||||
}
|
||||
|
||||
MaterialThumbnail::~MaterialThumbnail()
|
||||
{
|
||||
AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Handler::BusDisconnect();
|
||||
AzFramework::AssetCatalogEventBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void MaterialThumbnail::ThumbnailRendered(QPixmap& thumbnailImage)
|
||||
{
|
||||
m_pixmap = thumbnailImage;
|
||||
m_renderWait.release();
|
||||
}
|
||||
|
||||
void MaterialThumbnail::ThumbnailFailedToRender()
|
||||
{
|
||||
m_state = State::Failed;
|
||||
m_renderWait.release();
|
||||
}
|
||||
|
||||
void MaterialThumbnail::OnCatalogAssetChanged([[maybe_unused]] const AZ::Data::AssetId& assetId)
|
||||
{
|
||||
if (m_assetId == assetId &&
|
||||
m_state == State::Ready)
|
||||
{
|
||||
m_state = State::Unloaded;
|
||||
Load();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// MaterialThumbnailCache
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
MaterialThumbnailCache::MaterialThumbnailCache()
|
||||
: ThumbnailCache<MaterialThumbnail>()
|
||||
{
|
||||
}
|
||||
|
||||
MaterialThumbnailCache::~MaterialThumbnailCache() = default;
|
||||
|
||||
int MaterialThumbnailCache::GetPriority() const
|
||||
{
|
||||
// Material thumbnails override default source thumbnails, so carry higher priority
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char* MaterialThumbnailCache::GetProviderName() const
|
||||
{
|
||||
return ProviderName;
|
||||
}
|
||||
|
||||
bool MaterialThumbnailCache::IsSupportedThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey key) const
|
||||
{
|
||||
return
|
||||
GetAssetId(key, RPI::MaterialAsset::RTTI_Type()).IsValid() &&
|
||||
// in case it's a source fbx, it will contain both material and model products
|
||||
// model thumbnails are handled by MeshThumbnail
|
||||
!GetAssetId(key, RPI::ModelAsset::RTTI_Type()).IsValid();
|
||||
}
|
||||
} // namespace Thumbnails
|
||||
} // namespace LyIntegration
|
||||
} // namespace AZ
|
||||
|
||||
#include <Material/moc_MaterialThumbnail.cpp>
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/std/parallel/binary_semaphore.h>
|
||||
#include <AzFramework/Asset/AssetCatalogBus.h>
|
||||
#include <AzToolsFramework/Thumbnails/Thumbnail.h>
|
||||
#include <AzToolsFramework/Thumbnails/ThumbnailerBus.h>
|
||||
#include <Thumbnails/Rendering/CommonThumbnailRenderer.h>
|
||||
#endif
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace LyIntegration
|
||||
{
|
||||
namespace Thumbnails
|
||||
{
|
||||
/**
|
||||
* Custom material or model thumbnail that detects when an asset changes and updates the thumbnail
|
||||
*/
|
||||
class MaterialThumbnail
|
||||
: public AzToolsFramework::Thumbnailer::Thumbnail
|
||||
, public AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Handler
|
||||
, private AzFramework::AssetCatalogEventBus::Handler
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MaterialThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey key, int thumbnailSize);
|
||||
~MaterialThumbnail() override;
|
||||
|
||||
//! AzToolsFramework::ThumbnailerRendererNotificationBus::Handler overrides...
|
||||
void ThumbnailRendered(QPixmap& thumbnailImage) override;
|
||||
void ThumbnailFailedToRender() override;
|
||||
|
||||
protected:
|
||||
void LoadThread() override;
|
||||
|
||||
private:
|
||||
// AzFramework::AssetCatalogEventBus::Handler interface overrides...
|
||||
void OnCatalogAssetChanged(const AZ::Data::AssetId& assetId) override;
|
||||
|
||||
AZStd::binary_semaphore m_renderWait;
|
||||
Data::AssetId m_assetId;
|
||||
};
|
||||
|
||||
/**
|
||||
* Cache configuration for large material thumbnails
|
||||
*/
|
||||
class MaterialThumbnailCache
|
||||
: public AzToolsFramework::Thumbnailer::ThumbnailCache<MaterialThumbnail>
|
||||
{
|
||||
public:
|
||||
MaterialThumbnailCache();
|
||||
~MaterialThumbnailCache() override;
|
||||
|
||||
int GetPriority() const override;
|
||||
const char* GetProviderName() const override;
|
||||
|
||||
static constexpr const char* ProviderName = "Material Thumbnails";
|
||||
|
||||
protected:
|
||||
bool IsSupportedThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey key) const override;
|
||||
};
|
||||
} // namespace Thumbnails
|
||||
} // namespace LyIntegration
|
||||
} // namespace AZ
|
||||
-150
@@ -1,150 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
|
||||
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
|
||||
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
|
||||
#include <AzCore/Math/MatrixUtils.h>
|
||||
#include <AzToolsFramework/Thumbnails/ThumbnailContext.h>
|
||||
#include <AzToolsFramework/AssetBrowser/Thumbnails/SourceThumbnail.h>
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
||||
|
||||
#include <Source/Material/Preview/MaterialPreviewer.h>
|
||||
|
||||
// Disables warning messages triggered by the Qt library
|
||||
// 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 <Source/Material/Preview/ui_MaterialPreviewer.h>
|
||||
#include <QString>
|
||||
#include <QResizeEvent>
|
||||
AZ_POP_DISABLE_WARNING
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace LyIntegration
|
||||
{
|
||||
static constexpr int CharWidth = 6;
|
||||
|
||||
MaterialPreviewer::MaterialPreviewer(QWidget* parent)
|
||||
: Previewer(parent)
|
||||
, m_ui(new Ui::MaterialPreviewerClass())
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
}
|
||||
|
||||
MaterialPreviewer::~MaterialPreviewer()
|
||||
{
|
||||
}
|
||||
|
||||
void MaterialPreviewer::Display(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry)
|
||||
{
|
||||
using namespace AzToolsFramework::AssetBrowser;
|
||||
|
||||
if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Source)
|
||||
{
|
||||
const auto source = azrtti_cast<const SourceAssetBrowserEntry*>(entry);
|
||||
if (source->GetChildCount() > 0)
|
||||
{
|
||||
const auto product = azrtti_cast<const ProductAssetBrowserEntry*>(source->GetChild(0));
|
||||
if (product)
|
||||
{
|
||||
DisplayInternal(product);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Product)
|
||||
{
|
||||
const auto product = azrtti_cast<const ProductAssetBrowserEntry*>(entry);
|
||||
DisplayInternal(product);
|
||||
}
|
||||
}
|
||||
|
||||
const QString& MaterialPreviewer::GetName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
void MaterialPreviewer::resizeEvent([[maybe_unused]] QResizeEvent* event)
|
||||
{
|
||||
m_ui->m_materialPreviewWidget->setMaximumHeight(m_ui->m_materialPreviewWidget->width());
|
||||
|
||||
UpdateFileInfo();
|
||||
}
|
||||
|
||||
void MaterialPreviewer::DisplayInternal(const AzToolsFramework::AssetBrowser::ProductAssetBrowserEntry* product)
|
||||
{
|
||||
using namespace AzToolsFramework;
|
||||
using namespace Thumbnailer;
|
||||
|
||||
if (product->GetAssetId() == m_assetId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_assetId = product->GetAssetId();
|
||||
m_fileInfo = QString::fromUtf8(product->GetParent()->GetName().c_str());
|
||||
|
||||
bool result = false;
|
||||
AZ::Data::AssetInfo assetInfo;
|
||||
AZ::Data::AssetType assetType;
|
||||
AZStd::string rootFilePath;
|
||||
const AZStd::string platformName = ""; // Empty for default
|
||||
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(result, &AzToolsFramework::AssetSystemRequestBus::Events::GetAssetInfoById,
|
||||
m_assetId, assetType, platformName, assetInfo, rootFilePath);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AZStd::string fullSourcePath = AZStd::string::format("%s/%s", rootFilePath.c_str(), assetInfo.m_relativePath.c_str());
|
||||
SharedThumbnailKey thumbnailKey = MAKE_TKEY(AzToolsFramework::AssetBrowser::SourceThumbnailKey, fullSourcePath.c_str());
|
||||
m_ui->m_materialPreviewWidget->SetThumbnailKey(thumbnailKey, Thumbnailer::ThumbnailContext::DefaultContext);
|
||||
|
||||
UpdateFileInfo();
|
||||
}
|
||||
|
||||
void MaterialPreviewer::UpdateFileInfo() const
|
||||
{
|
||||
m_ui->m_fileInfoLabel->setText(WordWrap(m_fileInfo, m_ui->m_fileInfoLabel->width() / CharWidth));
|
||||
}
|
||||
|
||||
QString MaterialPreviewer::WordWrap(const QString& string, int maxLength)
|
||||
{
|
||||
QString result;
|
||||
int length = 0;
|
||||
|
||||
for (const QChar& c : string)
|
||||
{
|
||||
if (c == '\n')
|
||||
{
|
||||
length = 0;
|
||||
}
|
||||
else if (length > maxLength)
|
||||
{
|
||||
result.append('\n');
|
||||
length = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
length++;
|
||||
}
|
||||
result.append(c);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} // namespace LyIntegration
|
||||
} // namespace AZ
|
||||
|
||||
#include <Source/Material/Preview/moc_MaterialPreviewer.cpp>
|
||||
-52
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
|
||||
|
||||
#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
|
||||
#include <Atom/RPI.Edit/Material/MaterialSourceData.h>
|
||||
|
||||
#include <Source/Material/Preview/MaterialPreviewer.h>
|
||||
#include <Source/Material/Preview/MaterialPreviewerFactory.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace LyIntegration
|
||||
{
|
||||
AzToolsFramework::AssetBrowser::Previewer* MaterialPreviewerFactory::CreatePreviewer(QWidget* parent) const
|
||||
{
|
||||
return new MaterialPreviewer(parent);
|
||||
}
|
||||
|
||||
bool MaterialPreviewerFactory::IsEntrySupported(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) const
|
||||
{
|
||||
using namespace AzToolsFramework::AssetBrowser;
|
||||
|
||||
switch (entry->GetEntryType())
|
||||
{
|
||||
case AssetBrowserEntry::AssetEntryType::Source:
|
||||
{
|
||||
const auto source = azrtti_cast<const SourceAssetBrowserEntry*>(entry);
|
||||
return source->GetPrimaryAssetType() == RPI::MaterialAsset::RTTI_Type();
|
||||
}
|
||||
case AssetBrowserEntry::AssetEntryType::Product:
|
||||
const auto product = azrtti_cast<const ProductAssetBrowserEntry*>(entry);
|
||||
return product->GetAssetType() == RPI::MaterialAsset::RTTI_Type();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const QString& MaterialPreviewerFactory::GetName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
} // namespace LyIntegration
|
||||
} // namespace AZ
|
||||
-132
@@ -1,132 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <QPixmap>
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
|
||||
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
||||
|
||||
#include <Atom/RPI.Public/Material/Material.h>
|
||||
|
||||
#include <Source/Material/Thumbnails/MaterialThumbnail.h>
|
||||
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace LyIntegration
|
||||
{
|
||||
using namespace AzToolsFramework::Thumbnailer;
|
||||
using namespace AzToolsFramework::AssetBrowser;
|
||||
|
||||
const int MaterialThumbnailSize = 200;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// MaterialThumbnail
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
MaterialThumbnail::MaterialThumbnail(SharedThumbnailKey key, int thumbnailSize)
|
||||
: Thumbnail(key, thumbnailSize)
|
||||
{
|
||||
const SourceThumbnailKey* sourceThumbnailKey = azrtti_cast<const SourceThumbnailKey*>(m_key.data());
|
||||
if (!sourceThumbnailKey)
|
||||
{
|
||||
AZ_Error("MaterialThumbnail", sourceThumbnailKey, "Incorrect key type, excpected SourceThumbnailKey");
|
||||
m_state = State::Failed;
|
||||
return;
|
||||
}
|
||||
|
||||
Data::AssetInfo assetInfo;
|
||||
AZStd::string watchFolder;
|
||||
bool hasResult = false;
|
||||
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(hasResult, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetSourceInfoBySourcePath,
|
||||
sourceThumbnailKey->GetFileName().c_str(), assetInfo, watchFolder);
|
||||
|
||||
if (!hasResult)
|
||||
{
|
||||
AZ_Error("MaterialThumbnail", hasResult, "AssetInfo for %s could not be found", sourceThumbnailKey->GetFileName().c_str());
|
||||
m_state = State::Failed;
|
||||
return;
|
||||
}
|
||||
|
||||
m_assetType = AZ::AzTypeInfo<AZ::RPI::MaterialAsset>::Uuid();
|
||||
m_assetId = assetInfo.m_assetId;
|
||||
|
||||
ThumbnailerRendererNotificationBus::Handler::BusConnect(m_assetId);
|
||||
AzFramework::AssetCatalogEventBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
void MaterialThumbnail::LoadThread()
|
||||
{
|
||||
ThumbnailerRendererRequestBus::QueueEvent(m_assetType, &ThumbnailerRendererRequests::RenderThumbnail, m_assetId, m_thumbnailSize);
|
||||
// wait for response from thumbnail renderer
|
||||
m_renderWait.acquire();
|
||||
}
|
||||
|
||||
MaterialThumbnail::~MaterialThumbnail()
|
||||
{
|
||||
ThumbnailerRendererNotificationBus::Handler::BusDisconnect(m_assetId);
|
||||
AzFramework::AssetCatalogEventBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void MaterialThumbnail::ThumbnailRendered(QPixmap& thumbnailImage)
|
||||
{
|
||||
m_pixmap = thumbnailImage;
|
||||
m_renderWait.release();
|
||||
}
|
||||
|
||||
void MaterialThumbnail::ThumbnailFailedToRender()
|
||||
{
|
||||
m_state = State::Failed;
|
||||
m_renderWait.release();
|
||||
}
|
||||
|
||||
void MaterialThumbnail::OnCatalogAssetChanged(const AZ::Data::AssetId& assetId)
|
||||
{
|
||||
if (m_assetId == assetId &&
|
||||
m_state == State::Ready)
|
||||
{
|
||||
m_state = State::Unloaded;
|
||||
Load();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// MaterialThumbnailCache
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
MaterialThumbnailCache::MaterialThumbnailCache()
|
||||
: ThumbnailCache<MaterialThumbnail, SourceKeyHash, SourceKeyEqual>()
|
||||
, m_renderer(AZStd::make_unique<MaterialThumbnailRenderer>())
|
||||
{
|
||||
}
|
||||
|
||||
MaterialThumbnailCache::~MaterialThumbnailCache() = default;
|
||||
|
||||
int MaterialThumbnailCache::GetPriority() const
|
||||
{
|
||||
// Material thumbnails override default source thumbnails, so carry higher priority
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char* MaterialThumbnailCache::GetProviderName() const
|
||||
{
|
||||
return ProviderName;
|
||||
}
|
||||
|
||||
bool MaterialThumbnailCache::IsSupportedThumbnail(SharedThumbnailKey key) const
|
||||
{
|
||||
auto sourceKey = azrtti_cast<const AzToolsFramework::AssetBrowser::SourceThumbnailKey*>(key.data());
|
||||
return sourceKey && sourceKey->GetExtension() == ".material";
|
||||
}
|
||||
} // namespace LyIntegration
|
||||
} // namespace AZ
|
||||
|
||||
#include <Source/Material/Thumbnails/moc_MaterialThumbnail.cpp>
|
||||
-82
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/std/parallel/binary_semaphore.h>
|
||||
#include <AzFramework/Asset/AssetCatalogBus.h>
|
||||
|
||||
#include <AzToolsFramework/Thumbnails/Thumbnail.h>
|
||||
#include <AzToolsFramework/Thumbnails/ThumbnailerBus.h>
|
||||
#include <AzToolsFramework/AssetBrowser/Thumbnails/SourceThumbnail.h>
|
||||
|
||||
#include <Material/Thumbnails/MaterialThumbnailRenderer.h>
|
||||
#endif
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace LyIntegration
|
||||
{
|
||||
/**
|
||||
* Custom material thumbnail that detects when a material asset changes and updates the thumbnail
|
||||
*/
|
||||
class MaterialThumbnail
|
||||
: public AzToolsFramework::Thumbnailer::Thumbnail
|
||||
, public AzToolsFramework::ThumbnailerRendererNotificationBus::Handler
|
||||
, private AzFramework::AssetCatalogEventBus::Handler
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MaterialThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey key, int thumbnailSize);
|
||||
~MaterialThumbnail() override;
|
||||
|
||||
//! AzToolsFramework::ThumbnailerRendererNotificationBus::Handler overrides...
|
||||
void ThumbnailRendered(QPixmap& thumbnailImage) override;
|
||||
void ThumbnailFailedToRender() override;
|
||||
|
||||
protected:
|
||||
void LoadThread() override;
|
||||
|
||||
private:
|
||||
// AzFramework::AssetCatalogEventBus::Handler interface overrides...
|
||||
void OnCatalogAssetChanged(const AZ::Data::AssetId& assetId) override;
|
||||
|
||||
Data::AssetId m_assetId;
|
||||
Data::AssetType m_assetType;
|
||||
AZStd::binary_semaphore m_renderWait;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Cache configuration for large material thumbnails
|
||||
*/
|
||||
class MaterialThumbnailCache
|
||||
: public AzToolsFramework::Thumbnailer::ThumbnailCache<MaterialThumbnail, AzToolsFramework::AssetBrowser::SourceKeyHash, AzToolsFramework::AssetBrowser::SourceKeyEqual>
|
||||
{
|
||||
public:
|
||||
MaterialThumbnailCache();
|
||||
~MaterialThumbnailCache() override;
|
||||
|
||||
int GetPriority() const override;
|
||||
const char* GetProviderName() const override;
|
||||
|
||||
static constexpr const char* ProviderName = "Material Thumbnails";
|
||||
|
||||
protected:
|
||||
bool IsSupportedThumbnail(AzToolsFramework::SharedThumbnailKey key) const override;
|
||||
|
||||
private:
|
||||
AZStd::unique_ptr<MaterialThumbnailRenderer> m_renderer;
|
||||
};
|
||||
} // namespace LyIntegration
|
||||
} // namespace AZ
|
||||
-359
@@ -1,359 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
|
||||
#include <AzFramework/Components/TransformComponent.h>
|
||||
|
||||
#include <AzCore/Math/MatrixUtils.h>
|
||||
#include <Atom/RHI/RHISystemInterface.h>
|
||||
#include <Atom/RPI.Public/Pass/Specific/SwapChainPass.h>
|
||||
#include <Atom/RPI.Public/RPISystemInterface.h>
|
||||
#include <Atom/RPI.Public/RenderPipeline.h>
|
||||
#include <Atom/RPI.Public/Scene.h>
|
||||
#include <Atom/RPI.Public/Material/Material.h>
|
||||
#include <Atom/RPI.Reflect/Asset/AssetUtils.h>
|
||||
#include <Atom/RPI.Public/View.h>
|
||||
#include <Atom/Feature/ImageBasedLights/ImageBasedLightFeatureProcessorInterface.h>
|
||||
#include <Atom/Feature/CoreLights/DirectionalLightFeatureProcessorInterface.h>
|
||||
#include <Atom/Feature/PostProcess/PostProcessFeatureProcessorInterface.h>
|
||||
#include <Mesh/MeshComponent.h>
|
||||
#include <Material/MaterialComponent.h>
|
||||
#include <Atom/RPI.Public/Material/Material.h>
|
||||
|
||||
#include <Source/Material/Thumbnails/MaterialThumbnailRenderer.h>
|
||||
#include "Atom/Feature/Utils/FrameCaptureBus.h"
|
||||
#include "Atom/Feature/SkyBox/SkyBoxFeatureProcessorInterface.h"
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace LyIntegration
|
||||
{
|
||||
using namespace AzToolsFramework::Thumbnailer;
|
||||
|
||||
static constexpr const char* ModelPath = "materialeditor/viewportmodels/quadsphere.azmodel";
|
||||
static constexpr const char* LightingPresetPath = "lightingpresets/default.lightingpreset.azasset";
|
||||
static constexpr float AspectRatio = 1.0f;
|
||||
static constexpr float NearDist = 0.1f;
|
||||
static constexpr float FarDist = 100.0f;
|
||||
|
||||
MaterialThumbnailRenderer::MaterialThumbnailRenderer()
|
||||
{
|
||||
m_entityContext = AZStd::make_unique<AzFramework::EntityContext>();
|
||||
m_entityContext->InitContext();
|
||||
|
||||
Data::AssetType materialAssetType = AzTypeInfo<RPI::MaterialAsset>::Uuid();
|
||||
ThumbnailerRendererRequestBus::Handler::BusConnect(materialAssetType);
|
||||
SystemTickBus::Handler::BusConnect();
|
||||
|
||||
m_shouldPullNextAsset = true;
|
||||
}
|
||||
|
||||
MaterialThumbnailRenderer::~MaterialThumbnailRenderer()
|
||||
{
|
||||
ThumbnailerRendererRequestBus::Handler::BusDisconnect();
|
||||
SystemTickBus::Handler::BusDisconnect();
|
||||
AZ::Data::AssetBus::Handler::BusDisconnect();
|
||||
Render::MaterialComponentNotificationBus::Handler::BusDisconnect();
|
||||
m_materialAssetToRender.Release();
|
||||
|
||||
if (m_initialized)
|
||||
{
|
||||
Render::FrameCaptureNotificationBus::Handler::BusDisconnect();
|
||||
TickBus::Handler::BusDisconnect();
|
||||
|
||||
if (m_modelEntity)
|
||||
{
|
||||
AzFramework::EntityContextRequestBus::Event(m_entityContext->GetContextId(),
|
||||
&AzFramework::EntityContextRequestBus::Events::DestroyEntity, m_modelEntity);
|
||||
m_modelEntity = nullptr;
|
||||
}
|
||||
|
||||
m_frameworkScene->UnsetSubsystem<RPI::Scene>();
|
||||
|
||||
m_scene->Deactivate();
|
||||
m_scene->RemoveRenderPipeline(m_renderPipeline->GetId());
|
||||
RPI::RPISystemInterface::Get()->UnregisterScene(m_scene);
|
||||
bool sceneRemovedSuccessfully = false;
|
||||
AzFramework::SceneSystemRequestBus::BroadcastResult(sceneRemovedSuccessfully, &AzFramework::SceneSystemRequests::RemoveScene, m_sceneName);
|
||||
m_scene = nullptr;
|
||||
m_renderPipeline = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool MaterialThumbnailRenderer::Installed() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void MaterialThumbnailRenderer::OnSystemTick()
|
||||
{
|
||||
ThumbnailerRendererRequestBus::ExecuteQueuedEvents();
|
||||
}
|
||||
|
||||
void MaterialThumbnailRenderer::OnTick(float deltaTime, AZ::ScriptTimePoint time)
|
||||
{
|
||||
m_deltaTime = deltaTime;
|
||||
m_simulateTime = time.GetSeconds();
|
||||
|
||||
if (m_shouldPullNextAsset && !m_assetIdQueue.empty())
|
||||
{
|
||||
m_shouldPullNextAsset = false;
|
||||
|
||||
const auto assetId = m_assetIdQueue.front();
|
||||
m_assetIdQueue.pop();
|
||||
|
||||
m_materialAssetToRender.Release();
|
||||
AZ::Data::AssetBus::Handler::BusDisconnect();
|
||||
|
||||
if (assetId.IsValid())
|
||||
{
|
||||
m_materialAssetToRender.Create(assetId);
|
||||
m_materialAssetToRender.QueueLoad();
|
||||
AZ::Data::AssetBus::Handler::BusConnect(assetId);
|
||||
}
|
||||
}
|
||||
else if (m_readyToCapture)
|
||||
{
|
||||
m_renderPipeline->AddToRenderTickOnce();
|
||||
|
||||
RPI::AttachmentReadback::CallbackFunction readbackCallback = [&](const RPI::AttachmentReadback::ReadbackResult& result)
|
||||
{
|
||||
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);
|
||||
ThumbnailerRendererNotificationBus::Event(m_materialAssetToRender.GetId(),
|
||||
&ThumbnailerRendererNotifications::ThumbnailRendered, pixmap);
|
||||
};
|
||||
|
||||
Render::FrameCaptureNotificationBus::Handler::BusConnect();
|
||||
bool startedCapture = false;
|
||||
Render::FrameCaptureRequestBus::BroadcastResult(
|
||||
startedCapture,
|
||||
&Render::FrameCaptureRequestBus::Events::CapturePassAttachmentWithCallback,
|
||||
m_passHierarchy, AZStd::string("Output"), readbackCallback);
|
||||
// Reset the capture flag the capture requst was successful. Otherwise try capture it again next tick.
|
||||
if (startedCapture)
|
||||
{
|
||||
m_readyToCapture = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialThumbnailRenderer::OnAssetReady(AZ::Data::Asset<AZ::Data::AssetData> asset)
|
||||
{
|
||||
m_materialAssetToRender = asset;
|
||||
AZ::Data::AssetBus::Handler::BusDisconnect();
|
||||
|
||||
Render::MaterialComponentRequestBus::Event(m_modelEntity->GetId(),
|
||||
&Render::MaterialComponentRequestBus::Events::SetDefaultMaterialOverride,
|
||||
m_materialAssetToRender.GetId());
|
||||
|
||||
// listen to material override finished notification.
|
||||
Render::MaterialComponentNotificationBus::Handler::BusConnect(m_modelEntity->GetId());
|
||||
}
|
||||
|
||||
void MaterialThumbnailRenderer::OnAssetError(AZ::Data::Asset<AZ::Data::AssetData> asset)
|
||||
{
|
||||
OnAssetCanceled(asset.GetId());
|
||||
}
|
||||
|
||||
void MaterialThumbnailRenderer::OnAssetCanceled([[maybe_unused]] AZ::Data::AssetId assetId)
|
||||
{
|
||||
m_readyToCapture = false;
|
||||
m_shouldPullNextAsset = true;
|
||||
m_materialAssetToRender.Release();
|
||||
AZ::Data::AssetBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void MaterialThumbnailRenderer::OnCaptureFinished([[maybe_unused]] Render::FrameCaptureResult result, [[maybe_unused]] const AZStd::string& info)
|
||||
{
|
||||
m_shouldPullNextAsset = true;
|
||||
m_renderPipeline->RemoveFromRenderTick();
|
||||
Render::FrameCaptureNotificationBus::Handler::BusDisconnect();
|
||||
if (m_assetIdQueue.empty())
|
||||
{
|
||||
TickBus::Handler::BusDisconnect();
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialThumbnailRenderer::Init()
|
||||
{
|
||||
using namespace Data;
|
||||
|
||||
// Create and register a scene with minimum required feature processors
|
||||
RPI::SceneDescriptor sceneDesc;
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::TransformServiceFeatureProcessor");
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::MeshFeatureProcessor");
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::PointLightFeatureProcessor");
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::SpotLightFeatureProcessor");
|
||||
// There is currently a bug where having multiple DirectionalLightFeatureProcessors active can result in shadow flickering [ATOM-13568]
|
||||
// as well as continually rebuilding MeshDrawPackets [ATOM-13633]. Lets just disable the directional light FP for now.
|
||||
// Possibly re-enable with [GFX TODO][ATOM-13639]
|
||||
// sceneDesc.m_featureProcessorNames.push_back("AZ::Render::DirectionalLightFeatureProcessor");
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::DiskLightFeatureProcessor");
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::CapsuleLightFeatureProcessor");
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::QuadLightFeatureProcessor");
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::DecalTextureArrayFeatureProcessor");
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::ImageBasedLightFeatureProcessor");
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::PostProcessFeatureProcessor");
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::SkyBoxFeatureProcessor");
|
||||
m_scene = RPI::Scene::CreateScene(sceneDesc);
|
||||
|
||||
// Setup scene srg modification callback (to push per-frame values to the shaders)
|
||||
RPI::ShaderResourceGroupCallback callback = [this](RPI::ShaderResourceGroup* srg)
|
||||
{
|
||||
if (srg == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
bool needCompile = false;
|
||||
RHI::ShaderInputConstantIndex timeIndex = srg->FindShaderInputConstantIndex(Name{ "m_time" });
|
||||
if (timeIndex.IsValid())
|
||||
{
|
||||
srg->SetConstant(timeIndex, (float)m_simulateTime);
|
||||
needCompile = true;
|
||||
}
|
||||
RHI::ShaderInputConstantIndex deltaTimeIndex = srg->FindShaderInputConstantIndex(Name{ "m_deltaTime" });
|
||||
if (deltaTimeIndex.IsValid())
|
||||
{
|
||||
srg->SetConstant(deltaTimeIndex, m_deltaTime);
|
||||
needCompile = true;
|
||||
}
|
||||
|
||||
if (needCompile)
|
||||
{
|
||||
srg->Compile();
|
||||
}
|
||||
};
|
||||
m_scene->SetShaderResourceGroupCallback(callback);
|
||||
|
||||
// Bind m_defaultScene to the GameEntityContext's AzFramework::Scene
|
||||
Outcome<AzFramework::Scene*, AZStd::string> createSceneOutcome;
|
||||
AzFramework::SceneSystemRequestBus::BroadcastResult(createSceneOutcome, &AzFramework::SceneSystemRequests::CreateScene,
|
||||
m_sceneName);
|
||||
AZ_Assert(createSceneOutcome, createSceneOutcome.GetError().c_str()); // This should never happen unless scene creation has changed.
|
||||
createSceneOutcome.GetValue()->SetSubsystem(m_scene.get());
|
||||
m_frameworkScene = createSceneOutcome.GetValue();
|
||||
m_frameworkScene->SetSubsystem(m_scene.get());
|
||||
|
||||
m_entityContext->InitContext();
|
||||
|
||||
bool success = false;
|
||||
AzFramework::SceneSystemRequestBus::BroadcastResult(success, &AzFramework::SceneSystemRequests::SetSceneForEntityContextId,
|
||||
m_entityContext->GetContextId(), m_frameworkScene);
|
||||
AZ_Assert(success, "Unable to set entity context on AzFramework::Scene: %s", m_sceneName.c_str());
|
||||
|
||||
// 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
|
||||
Name viewName = Name("MainCamera");
|
||||
m_view = RPI::View::CreateView(viewName, RPI::View::UsageCamera);
|
||||
m_transform = Transform::CreateFromQuaternionAndTranslation(Quaternion::CreateIdentity(), Vector3::CreateZero());
|
||||
m_view->SetCameraTransform(Matrix3x4::CreateFromTransform(m_transform));
|
||||
|
||||
Matrix4x4 viewToClipMatrix;
|
||||
MakePerspectiveFovMatrixRH(viewToClipMatrix,
|
||||
Constants::HalfPi,
|
||||
AspectRatio,
|
||||
NearDist,
|
||||
FarDist, true);
|
||||
m_view->SetViewToClipMatrix(viewToClipMatrix);
|
||||
|
||||
m_renderPipeline->SetDefaultView(m_view);
|
||||
|
||||
// Create lighting preset
|
||||
m_lightingPresetAsset = AZ::RPI::AssetUtils::LoadAssetByProductPath<AZ::RPI::AnyAsset>(LightingPresetPath);
|
||||
if (m_lightingPresetAsset.IsReady())
|
||||
{
|
||||
auto preset = m_lightingPresetAsset->GetDataAs<AZ::Render::LightingPreset>();
|
||||
if (preset)
|
||||
{
|
||||
auto iblFeatureProcessor = m_scene->GetFeatureProcessor<AZ::Render::ImageBasedLightFeatureProcessorInterface>();
|
||||
auto postProcessFeatureProcessor = m_scene->GetFeatureProcessor<AZ::Render::PostProcessFeatureProcessorInterface>();
|
||||
auto exposureControlSettingInterface = postProcessFeatureProcessor->GetOrCreateSettingsInterface(AZ::EntityId())->GetOrCreateExposureControlSettingsInterface();
|
||||
auto directionalLightFeatureProcessor = m_scene->GetFeatureProcessor<AZ::Render::DirectionalLightFeatureProcessorInterface>();
|
||||
auto skyboxFeatureProcessor = m_scene->GetFeatureProcessor<AZ::Render::SkyBoxFeatureProcessorInterface>();
|
||||
skyboxFeatureProcessor->Enable(true);
|
||||
skyboxFeatureProcessor->SetSkyboxMode(AZ::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<AZ::Render::DirectionalLightFeatureProcessorInterface::LightHandle> lightHandles;
|
||||
|
||||
preset->ApplyLightingPreset(
|
||||
iblFeatureProcessor,
|
||||
skyboxFeatureProcessor,
|
||||
exposureControlSettingInterface,
|
||||
directionalLightFeatureProcessor,
|
||||
cameraConfig,
|
||||
lightHandles);
|
||||
}
|
||||
}
|
||||
|
||||
// Create preview model
|
||||
AzFramework::EntityContextRequestBus::EventResult(m_modelEntity, m_entityContext->GetContextId(),
|
||||
&AzFramework::EntityContextRequestBus::Events::CreateEntity, "PreviewModel");
|
||||
m_modelEntity->CreateComponent(Render::MeshComponentTypeId);
|
||||
m_modelEntity->CreateComponent(Render::MaterialComponentTypeId);
|
||||
m_modelEntity->CreateComponent(azrtti_typeid<AzFramework::TransformComponent>());
|
||||
m_modelEntity->Init();
|
||||
m_modelEntity->Activate();
|
||||
TransformBus::Event(m_modelEntity->GetId(), &TransformBus::Events::SetLocalTM,
|
||||
Transform::CreateTranslation(Vector3(0, 0.8f, -0.5f)));
|
||||
|
||||
Render::MeshComponentRequestBus::Event(m_modelEntity->GetId(), &Render::MeshComponentRequestBus::Events::SetModelAssetPath, ModelPath);
|
||||
}
|
||||
|
||||
void MaterialThumbnailRenderer::RenderThumbnail(Data::AssetId assetId, [[maybe_unused]] int thumbnailSize)
|
||||
{
|
||||
if (!m_initialized)
|
||||
{
|
||||
Init();
|
||||
m_initialized = true;
|
||||
}
|
||||
|
||||
if (m_assetIdQueue.empty())
|
||||
{
|
||||
m_shouldPullNextAsset = true;
|
||||
TickBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
m_assetIdQueue.emplace(assetId);
|
||||
}
|
||||
|
||||
void MaterialThumbnailRenderer::OnMaterialsUpdated([[maybe_unused]] const Render::MaterialAssignmentMap& materials)
|
||||
{
|
||||
m_readyToCapture = true;
|
||||
Render::MaterialComponentNotificationBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
} // namespace LyIntegration
|
||||
} // namespace AZ
|
||||
-112
@@ -1,112 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
|
||||
#include <AzFramework/Entity/EntityContext.h>
|
||||
#include <AzFramework/Scene/Scene.h>
|
||||
|
||||
#include <AzToolsFramework/Thumbnails/Thumbnail.h>
|
||||
#include <AzToolsFramework/Thumbnails/ThumbnailerBus.h>
|
||||
#include <AzToolsFramework/AssetBrowser/Thumbnails/SourceThumbnail.h>
|
||||
|
||||
#include <AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h>
|
||||
|
||||
#include <Atom/RPI.Public/Base.h>
|
||||
#include <Atom/Feature/Utils/FrameCaptureBus.h>
|
||||
#include <Atom/Feature/Utils/LightingPreset.h>
|
||||
|
||||
// Disables warning messages triggered by the Qt library
|
||||
// 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>
|
||||
AZ_POP_DISABLE_WARNING
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace LyIntegration
|
||||
{
|
||||
//! Provides custom rendering of material thumbnails
|
||||
class MaterialThumbnailRenderer
|
||||
: public AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::Handler
|
||||
, public SystemTickBus::Handler
|
||||
, public TickBus::Handler
|
||||
, public AZ::Data::AssetBus::Handler
|
||||
, public Render::FrameCaptureNotificationBus::Handler
|
||||
, public Render::MaterialComponentNotificationBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(MaterialThumbnailRenderer, AZ::SystemAllocator, 0)
|
||||
|
||||
MaterialThumbnailRenderer();
|
||||
~MaterialThumbnailRenderer();
|
||||
|
||||
bool Installed() const override;
|
||||
|
||||
//! ThumbnailerRendererRequestsBus::Handler interface overrides...
|
||||
void RenderThumbnail(AZ::Data::AssetId assetId, int thumbnailSize) override;
|
||||
|
||||
//! SystemTickBus::Handler interface overrides...
|
||||
void OnSystemTick() override;
|
||||
|
||||
//! AZ::TickBus::Handler interface overrides...
|
||||
void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
|
||||
|
||||
// AZ::Data::AssetBus::Handler
|
||||
void OnAssetReady(AZ::Data::Asset<AZ::Data::AssetData> asset) override;
|
||||
void OnAssetError(AZ::Data::Asset<AZ::Data::AssetData> asset) override;
|
||||
void OnAssetCanceled(AZ::Data::AssetId assetId) override;
|
||||
|
||||
//! Render::FrameCaptureNotificationBus::Handler overrides...
|
||||
void OnCaptureFinished(Render::FrameCaptureResult result, const AZStd::string& info) override;
|
||||
|
||||
private:
|
||||
// MaterialComponentNotificationBus::Handler overrides...
|
||||
void OnMaterialsUpdated(const Render::MaterialAssignmentMap& materials) override;
|
||||
|
||||
void Init();
|
||||
|
||||
RPI::ScenePtr m_scene;
|
||||
AZStd::string m_sceneName = "Material Thumbnail Scene";
|
||||
AZStd::string m_pipelineName = "Material Thumbnail Pipeline";
|
||||
AzFramework::Scene* m_frameworkScene = nullptr;
|
||||
RPI::RenderPipelinePtr m_renderPipeline;
|
||||
AZStd::unique_ptr<AzFramework::EntityContext> m_entityContext;
|
||||
AZStd::vector<AZStd::string> m_passHierarchy;
|
||||
|
||||
AZ::Data::Asset<AZ::RPI::AnyAsset> m_lightingPresetAsset;
|
||||
|
||||
RPI::ViewPtr m_view = nullptr;
|
||||
Entity* m_modelEntity = nullptr;
|
||||
Transform m_transform;
|
||||
|
||||
//! Ready to process next request, this value is accessed from different threads.
|
||||
AZStd::atomic<bool> m_shouldPullNextAsset;
|
||||
//! Is renderer initialized. Initialization is only performed once the first thumbnail request is submitted.
|
||||
bool m_initialized = false;
|
||||
//! It takes an extra frame to load a mesh and apply material, this variable is set to true once we are ready to render pipeline to texture.
|
||||
bool m_readyToCapture = false;
|
||||
|
||||
//! Incoming thumbnail requests are appended to this queue and processed one at a time in OnTick function.
|
||||
AZStd::queue<Data::AssetId> m_assetIdQueue;
|
||||
//! Current material asset being rendered.
|
||||
Data::Asset<RPI::MaterialAsset> m_materialAssetToRender;
|
||||
|
||||
double m_simulateTime = 0.0f;
|
||||
float m_deltaTime = 0.0f;
|
||||
};
|
||||
} // namespace LyIntegration
|
||||
} // namespace AZ
|
||||
@@ -198,5 +198,14 @@ namespace AZ
|
||||
AzToolsFramework::Refresh_EntireTree);
|
||||
}
|
||||
|
||||
AZ::u32 EditorMeshComponent::OnConfigurationChanged()
|
||||
{
|
||||
// temp variable is needed to hold reference to m_modelAsset while it's being loaded.
|
||||
// Otherwise it gets released in Deactivate function, and instantly re-activating the component
|
||||
// places it in a bad state, which happens in OnConfigurationChanged base function.
|
||||
// This is a bug with AssetManager [LYN-2249]
|
||||
auto temp = m_controller.m_configuration.m_modelAsset;
|
||||
return BaseClass::OnConfigurationChanged();
|
||||
}
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
@@ -64,6 +64,8 @@ namespace AZ
|
||||
// MeshComponentNotificationBus overrides ...
|
||||
void OnModelReady(const Data::Asset<RPI::ModelAsset>& modelAsset, const Data::Instance<RPI::Model>& model) override;
|
||||
|
||||
AZ::u32 OnConfigurationChanged() override;
|
||||
|
||||
AZ::Crc32 AddEditorMaterialComponent();
|
||||
bool HasEditorMaterialComponent() const;
|
||||
AZ::u32 GetEditorMaterialComponentVisibility() const;
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/EditContextConstants.inl>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
#include <AzToolsFramework/Thumbnails/ThumbnailContext.h>
|
||||
#include <Source/Mesh/EditorMeshSystemComponent.h>
|
||||
#include <Source/Mesh/MeshThumbnail.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
//! Main system component for the Atom Common Feature Gem's editor/tools module.
|
||||
void EditorMeshSystemComponent::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serialize->Class<EditorMeshSystemComponent, AZ::Component>()
|
||||
->Version(0);
|
||||
|
||||
if (AZ::EditContext* ec = serialize->GetEditContext())
|
||||
{
|
||||
ec->Class<EditorMeshSystemComponent>("EditorMeshSystemComponent", "System component that sets up necessary logic related to EditorMeshComponent..")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("System"))
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EditorMeshSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
|
||||
{
|
||||
provided.push_back(AZ_CRC_CE("EditorMeshSystem"));
|
||||
}
|
||||
|
||||
void EditorMeshSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
|
||||
{
|
||||
incompatible.push_back(AZ_CRC_CE("EditorMeshSystem"));
|
||||
}
|
||||
|
||||
void EditorMeshSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
|
||||
{
|
||||
required.push_back(AZ_CRC_CE("ThumbnailerService"));
|
||||
}
|
||||
|
||||
void EditorMeshSystemComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)
|
||||
{
|
||||
AZ_UNUSED(dependent);
|
||||
}
|
||||
|
||||
void EditorMeshSystemComponent::Activate()
|
||||
{
|
||||
AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusConnect();
|
||||
SetupThumbnails();
|
||||
}
|
||||
|
||||
void EditorMeshSystemComponent::Deactivate()
|
||||
{
|
||||
TeardownThumbnails();
|
||||
AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void EditorMeshSystemComponent::OnApplicationAboutToStop()
|
||||
{
|
||||
TeardownThumbnails();
|
||||
}
|
||||
|
||||
void EditorMeshSystemComponent::SetupThumbnails()
|
||||
{
|
||||
using namespace AzToolsFramework::Thumbnailer;
|
||||
using namespace LyIntegration;
|
||||
|
||||
ThumbnailerRequestsBus::Broadcast(&ThumbnailerRequests::RegisterThumbnailProvider,
|
||||
MAKE_TCACHE(Thumbnails::MeshThumbnailCache),
|
||||
ThumbnailContext::DefaultContext);
|
||||
}
|
||||
|
||||
void EditorMeshSystemComponent::TeardownThumbnails()
|
||||
{
|
||||
using namespace AzToolsFramework::Thumbnailer;
|
||||
using namespace LyIntegration;
|
||||
|
||||
ThumbnailerRequestsBus::Broadcast(&ThumbnailerRequests::UnregisterThumbnailProvider,
|
||||
Thumbnails::MeshThumbnailCache::ProviderName,
|
||||
ThumbnailContext::DefaultContext);
|
||||
}
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <AzFramework/Application/Application.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
//! System component that sets up necessary logic related to EditorMeshComponent.
|
||||
class EditorMeshSystemComponent
|
||||
: public AZ::Component
|
||||
, private AzFramework::ApplicationLifecycleEvents::Bus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(EditorMeshSystemComponent, "{4D332E3D-C4FC-410B-A915-8E234CBDD4EC}");
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
|
||||
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
|
||||
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
|
||||
static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
|
||||
|
||||
protected:
|
||||
// AZ::Component interface overrides...
|
||||
void Activate() override;
|
||||
void Deactivate() override;
|
||||
|
||||
private:
|
||||
// AzFramework::ApplicationLifecycleEvents overrides...
|
||||
void OnApplicationAboutToStop() override;
|
||||
|
||||
void SetupThumbnails();
|
||||
void TeardownThumbnails();
|
||||
};
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
@@ -124,7 +124,6 @@ namespace AZ
|
||||
|
||||
void MeshComponentController::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)
|
||||
{
|
||||
dependent.push_back(AZ_CRC("MaterialProviderService", 0x64849a6b));
|
||||
dependent.push_back(AZ_CRC("TransformService", 0x8ee22c50));
|
||||
}
|
||||
|
||||
@@ -181,12 +180,14 @@ namespace AZ
|
||||
m_meshFeatureProcessor = RPI::Scene::GetFeatureProcessorForEntity<MeshFeatureProcessorInterface>(m_entityId);
|
||||
AZ_Error("MeshComponentController", m_meshFeatureProcessor, "Unable to find a MeshFeatureProcessorInterface on the entityId.");
|
||||
|
||||
RegisterModel();
|
||||
MeshComponentRequestBus::Handler::BusConnect(m_entityId);
|
||||
TransformNotificationBus::Handler::BusConnect(m_entityId);
|
||||
MaterialReceiverRequestBus::Handler::BusConnect(m_entityId);
|
||||
MaterialComponentNotificationBus::Handler::BusConnect(m_entityId);
|
||||
AzFramework::BoundsRequestBus::Handler::BusConnect(m_entityId);
|
||||
|
||||
//Buses must be connected before RegisterModel in case requests are made as a result of HandleModelChange
|
||||
RegisterModel();
|
||||
}
|
||||
|
||||
void MeshComponentController::Deactivate()
|
||||
@@ -196,6 +197,7 @@ namespace AZ
|
||||
TransformNotificationBus::Handler::BusDisconnect();
|
||||
MaterialReceiverRequestBus::Handler::BusDisconnect();
|
||||
MaterialComponentNotificationBus::Handler::BusDisconnect();
|
||||
|
||||
UnregisterModel();
|
||||
|
||||
m_meshFeatureProcessor = nullptr;
|
||||
@@ -229,7 +231,8 @@ namespace AZ
|
||||
|
||||
AZStd::unordered_set<AZ::Name> MeshComponentController::GetModelUvNames() const
|
||||
{
|
||||
return GetModel()->GetUvNames();
|
||||
const Data::Instance<RPI::Model> model = GetModel();
|
||||
return model ? model->GetUvNames() : AZStd::unordered_set<AZ::Name>();
|
||||
}
|
||||
|
||||
void MeshComponentController::OnMaterialsUpdated([[maybe_unused]] const MaterialAssignmentMap& materials)
|
||||
@@ -263,16 +266,16 @@ namespace AZ
|
||||
m_meshHandle = m_meshFeatureProcessor->AcquireMesh(m_configuration.m_modelAsset, materials);
|
||||
m_meshFeatureProcessor->ConnectModelChangeEventHandler(m_meshHandle, m_changeEventHandler);
|
||||
|
||||
// [GFX TODO] This should happen automatically. m_changeEventHandler should be passed to AcquireMesh
|
||||
// If the model instance or asset already exists, announce a model change to let others know it's loaded.
|
||||
HandleModelChange(m_meshFeatureProcessor->GetModel(m_meshHandle));
|
||||
|
||||
const AZ::Transform& transform = m_transformInterface ? m_transformInterface->GetWorldTM() : Transform::Identity();
|
||||
m_meshFeatureProcessor->SetTransform(m_meshHandle, transform);
|
||||
m_meshFeatureProcessor->SetSortKey(m_meshHandle, m_configuration.m_sortKey);
|
||||
m_meshFeatureProcessor->SetLodOverride(m_meshHandle, m_configuration.m_lodOverride);
|
||||
m_meshFeatureProcessor->SetExcludeFromReflectionCubeMaps(m_meshHandle, m_configuration.m_excludeFromReflectionCubeMaps);
|
||||
m_meshFeatureProcessor->SetUseForwardPassIblSpecular(m_meshHandle, m_configuration.m_useForwardPassIblSpecular);
|
||||
|
||||
// [GFX TODO] This should happen automatically. m_changeEventHandler should be passed to AcquireMesh
|
||||
// If the model instance or asset already exists, announce a model change to let others know it's loaded.
|
||||
HandleModelChange(m_meshFeatureProcessor->GetModel(m_meshHandle));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
||||
#include <Atom/RPI.Reflect/Model/ModelAsset.h>
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
#include <Source/Mesh/MeshThumbnail.h>
|
||||
#include <Source/Thumbnails/ThumbnailUtils.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace LyIntegration
|
||||
{
|
||||
namespace Thumbnails
|
||||
{
|
||||
const int MeshThumbnailSize = 200;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// MeshThumbnail
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
MeshThumbnail::MeshThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey key, int thumbnailSize)
|
||||
: Thumbnail(key, thumbnailSize)
|
||||
{
|
||||
m_assetId = GetAssetId(key, RPI::ModelAsset::RTTI_Type());
|
||||
if (!m_assetId.IsValid())
|
||||
{
|
||||
AZ_Error("MeshThumbnail", false, "Failed to find matching assetId for the thumbnailKey.");
|
||||
m_state = State::Failed;
|
||||
return;
|
||||
}
|
||||
|
||||
AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Handler::BusConnect(key);
|
||||
AzFramework::AssetCatalogEventBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
void MeshThumbnail::LoadThread()
|
||||
{
|
||||
AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::QueueEvent(
|
||||
RPI::ModelAsset::RTTI_Type(),
|
||||
&AzToolsFramework::Thumbnailer::ThumbnailerRendererRequests::RenderThumbnail,
|
||||
m_key,
|
||||
m_thumbnailSize);
|
||||
// wait for response from thumbnail renderer
|
||||
m_renderWait.acquire();
|
||||
}
|
||||
|
||||
MeshThumbnail::~MeshThumbnail()
|
||||
{
|
||||
AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Handler::BusDisconnect();
|
||||
AzFramework::AssetCatalogEventBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void MeshThumbnail::ThumbnailRendered(QPixmap& thumbnailImage)
|
||||
{
|
||||
m_pixmap = thumbnailImage;
|
||||
m_renderWait.release();
|
||||
}
|
||||
|
||||
void MeshThumbnail::ThumbnailFailedToRender()
|
||||
{
|
||||
m_state = State::Failed;
|
||||
m_renderWait.release();
|
||||
}
|
||||
|
||||
void MeshThumbnail::OnCatalogAssetChanged([[maybe_unused]] const AZ::Data::AssetId& assetId)
|
||||
{
|
||||
if (m_assetId == assetId &&
|
||||
m_state == State::Ready)
|
||||
{
|
||||
m_state = State::Unloaded;
|
||||
Load();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// MeshThumbnailCache
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
MeshThumbnailCache::MeshThumbnailCache()
|
||||
: ThumbnailCache<MeshThumbnail>()
|
||||
{
|
||||
}
|
||||
|
||||
MeshThumbnailCache::~MeshThumbnailCache() = default;
|
||||
|
||||
int MeshThumbnailCache::GetPriority() const
|
||||
{
|
||||
// Material thumbnails override default source thumbnails, so carry higher priority
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char* MeshThumbnailCache::GetProviderName() const
|
||||
{
|
||||
return ProviderName;
|
||||
}
|
||||
|
||||
bool MeshThumbnailCache::IsSupportedThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey key) const
|
||||
{
|
||||
return GetAssetId(key, RPI::ModelAsset::RTTI_Type()).IsValid();
|
||||
}
|
||||
} // namespace Thumbnails
|
||||
} // namespace LyIntegration
|
||||
} // namespace AZ
|
||||
|
||||
#include <Mesh/moc_MeshThumbnail.cpp>
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/std/parallel/binary_semaphore.h>
|
||||
#include <AzFramework/Asset/AssetCatalogBus.h>
|
||||
#include <AzToolsFramework/Thumbnails/Thumbnail.h>
|
||||
#include <AzToolsFramework/Thumbnails/ThumbnailerBus.h>
|
||||
#endif
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace LyIntegration
|
||||
{
|
||||
namespace Thumbnails
|
||||
{
|
||||
/**
|
||||
* Custom material or model thumbnail that detects when an asset changes and updates the thumbnail
|
||||
*/
|
||||
class MeshThumbnail
|
||||
: public AzToolsFramework::Thumbnailer::Thumbnail
|
||||
, public AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Handler
|
||||
, private AzFramework::AssetCatalogEventBus::Handler
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MeshThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey key, int thumbnailSize);
|
||||
~MeshThumbnail() override;
|
||||
|
||||
//! AzToolsFramework::ThumbnailerRendererNotificationBus::Handler overrides...
|
||||
void ThumbnailRendered(QPixmap& thumbnailImage) override;
|
||||
void ThumbnailFailedToRender() override;
|
||||
|
||||
protected:
|
||||
void LoadThread() override;
|
||||
|
||||
private:
|
||||
// AzFramework::AssetCatalogEventBus::Handler interface overrides...
|
||||
void OnCatalogAssetChanged(const AZ::Data::AssetId& assetId) override;
|
||||
|
||||
AZStd::binary_semaphore m_renderWait;
|
||||
Data::AssetId m_assetId;
|
||||
};
|
||||
|
||||
/**
|
||||
* Cache configuration for large material thumbnails
|
||||
*/
|
||||
class MeshThumbnailCache
|
||||
: public AzToolsFramework::Thumbnailer::ThumbnailCache<MeshThumbnail>
|
||||
{
|
||||
public:
|
||||
MeshThumbnailCache();
|
||||
~MeshThumbnailCache() override;
|
||||
|
||||
int GetPriority() const override;
|
||||
const char* GetProviderName() const override;
|
||||
|
||||
static constexpr const char* ProviderName = "Mesh Thumbnails";
|
||||
|
||||
protected:
|
||||
bool IsSupportedThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey key) const override;
|
||||
};
|
||||
} // namespace Thumbnails
|
||||
} // namespace LyIntegration
|
||||
} // namespace AZ
|
||||
@@ -55,6 +55,7 @@
|
||||
#include <Material/EditorMaterialComponent.h>
|
||||
#include <Material/EditorMaterialSystemComponent.h>
|
||||
#include <Mesh/EditorMeshComponent.h>
|
||||
#include <Mesh/EditorMeshSystemComponent.h>
|
||||
#include <ReflectionProbe/EditorReflectionProbeComponent.h>
|
||||
#include <PostProcess/EditorPostFxLayerComponent.h>
|
||||
#include <PostProcess/Bloom/EditorBloomComponent.h>
|
||||
@@ -131,6 +132,7 @@ namespace AZ
|
||||
EditorImageBasedLightComponent::CreateDescriptor(),
|
||||
EditorMaterialComponent::CreateDescriptor(),
|
||||
EditorMaterialSystemComponent::CreateDescriptor(),
|
||||
EditorMeshSystemComponent::CreateDescriptor(),
|
||||
EditorMeshComponent::CreateDescriptor(),
|
||||
EditorPhysicalSkyComponent::CreateDescriptor(),
|
||||
EditorPointLightComponent::CreateDescriptor(),
|
||||
@@ -153,6 +155,7 @@ namespace AZ
|
||||
azrtti_typeid<AtomLyIntegrationCommonFeaturesSystemComponent>(),
|
||||
#ifdef ATOMLYINTEGRATION_FEATURE_COMMON_EDITOR
|
||||
azrtti_typeid<EditorMaterialSystemComponent>(),
|
||||
azrtti_typeid<EditorMeshSystemComponent>(),
|
||||
azrtti_typeid<EditorCommonFeaturesSystemComponent>(),
|
||||
azrtti_typeid<EditorPostFxSystemComponent>(),
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@
|
||||
#include <AtomLyIntegration/CommonFeatures/PostProcess/LookModification/LookModificationComponentConfig.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <Atom/Feature/ACES/Aces.h>
|
||||
#include <ACES/Aces.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
|
||||
#include <Atom/RPI.Public/Scene.h>
|
||||
|
||||
#include <Atom/Feature/ACES/Aces.h>
|
||||
#include <ACES/Aces.h>
|
||||
|
||||
#include <PostProcess/LookModification/LookModificationComponentController.h>
|
||||
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
#include <AtomLyIntegration/CommonFeatures/PostProcess/LookModification/LookModificationBus.h>
|
||||
#include <AtomLyIntegration/CommonFeatures/PostProcess/LookModification/LookModificationComponentConfig.h>
|
||||
|
||||
#include <Atom/Feature/ACES/Aces.h>
|
||||
#include <ACES/Aces.h>
|
||||
#include <Atom/Feature/PostProcess/LookModification/LookModificationSettingsInterface.h>
|
||||
#include <Atom/Feature/PostProcess/PostProcessSettingsInterface.h>
|
||||
#include <Atom/Feature/PostProcess/PostProcessFeatureProcessorInterface.h>
|
||||
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
|
||||
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
|
||||
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
|
||||
#include <AzToolsFramework/Thumbnails/ThumbnailContext.h>
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
||||
#include <AzToolsFramework/Thumbnails/Thumbnail.h>
|
||||
|
||||
#include <Source/Thumbnails/Preview/CommonPreviewer.h>
|
||||
#include <Source/Thumbnails/ThumbnailUtils.h>
|
||||
|
||||
// Disables warning messages triggered by the Qt library
|
||||
// 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 <Source/Thumbnails/Preview/ui_CommonPreviewer.h>
|
||||
#include <QString>
|
||||
#include <QResizeEvent>
|
||||
AZ_POP_DISABLE_WARNING
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace LyIntegration
|
||||
{
|
||||
static constexpr int CharWidth = 6;
|
||||
|
||||
CommonPreviewer::CommonPreviewer(QWidget* parent)
|
||||
: Previewer(parent)
|
||||
, m_ui(new Ui::CommonPreviewerClass())
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
}
|
||||
|
||||
CommonPreviewer::~CommonPreviewer()
|
||||
{
|
||||
}
|
||||
|
||||
void CommonPreviewer::Display(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry)
|
||||
{
|
||||
using namespace AzToolsFramework::AssetBrowser;
|
||||
using namespace AzToolsFramework::Thumbnailer;
|
||||
|
||||
auto thumbnailKey = entry->GetThumbnailKey();
|
||||
m_ui->m_previewWidget->SetThumbnailKey(thumbnailKey, ThumbnailContext::DefaultContext);
|
||||
m_fileInfo = QString::fromUtf8(entry->GetName().c_str());
|
||||
UpdateFileInfo();
|
||||
}
|
||||
|
||||
const QString& CommonPreviewer::GetName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
void CommonPreviewer::resizeEvent([[maybe_unused]] QResizeEvent* event)
|
||||
{
|
||||
m_ui->m_previewWidget->setMaximumHeight(m_ui->m_previewWidget->width());
|
||||
|
||||
UpdateFileInfo();
|
||||
}
|
||||
|
||||
void CommonPreviewer::UpdateFileInfo() const
|
||||
{
|
||||
m_ui->m_fileInfoLabel->setText(Thumbnails::WordWrap(m_fileInfo, m_ui->m_fileInfoLabel->width() / CharWidth));
|
||||
}
|
||||
} // namespace LyIntegration
|
||||
} // namespace AZ
|
||||
|
||||
#include <Source/Thumbnails/Preview/moc_CommonPreviewer.cpp>
|
||||
+7
-12
@@ -24,7 +24,7 @@ AZ_POP_DISABLE_WARNING
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class MaterialPreviewerClass;
|
||||
class CommonPreviewerClass;
|
||||
}
|
||||
|
||||
namespace AzToolsFramework
|
||||
@@ -43,15 +43,15 @@ namespace AZ
|
||||
{
|
||||
namespace LyIntegration
|
||||
{
|
||||
class MaterialPreviewer final
|
||||
class CommonPreviewer final
|
||||
: public AzToolsFramework::AssetBrowser::Previewer
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(MaterialPreviewer, AZ::SystemAllocator, 0);
|
||||
AZ_CLASS_ALLOCATOR(CommonPreviewer, AZ::SystemAllocator, 0);
|
||||
|
||||
explicit MaterialPreviewer(QWidget* parent = nullptr);
|
||||
~MaterialPreviewer();
|
||||
explicit CommonPreviewer(QWidget* parent = nullptr);
|
||||
~CommonPreviewer();
|
||||
|
||||
// AzToolsFramework::AssetBrowser::Previewer overrides...
|
||||
void Clear() const override {}
|
||||
@@ -62,16 +62,11 @@ namespace AZ
|
||||
void resizeEvent(QResizeEvent* event) override;
|
||||
|
||||
private:
|
||||
void DisplayInternal(const AzToolsFramework::AssetBrowser::ProductAssetBrowserEntry* product);
|
||||
void UpdateFileInfo() const;
|
||||
|
||||
// QLabel word wrap does not break long words such as filenames, so manual word wrap needed
|
||||
static QString WordWrap(const QString& string, int maxLength);
|
||||
|
||||
QScopedPointer<Ui::MaterialPreviewerClass> m_ui;
|
||||
Data::AssetId m_assetId;
|
||||
QScopedPointer<Ui::CommonPreviewerClass> m_ui;
|
||||
QString m_fileInfo;
|
||||
QString m_name = "MaterialPreviewer";
|
||||
QString m_name = "CommonPreviewer";
|
||||
};
|
||||
} // namespace LyIntegration
|
||||
} // namespace AZ
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MaterialPreviewerClass</class>
|
||||
<widget class="QWidget" name="MaterialPreviewerClass">
|
||||
<class>CommonPreviewerClass</class>
|
||||
<widget class="QWidget" name="CommonPreviewerClass">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
@@ -27,7 +27,7 @@
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="AzToolsFramework::Thumbnailer::ThumbnailWidget" name="m_materialPreviewWidget" native="true">
|
||||
<widget class="AzToolsFramework::Thumbnailer::ThumbnailWidget" name="m_previewWidget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
|
||||
#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
|
||||
#include <Atom/RPI.Reflect/Model/ModelAsset.h>
|
||||
#include <Source/Thumbnails/Preview/CommonPreviewer.h>
|
||||
#include <Source/Thumbnails/Preview/CommonPreviewerFactory.h>
|
||||
#include <Source/Thumbnails/ThumbnailUtils.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace LyIntegration
|
||||
{
|
||||
AzToolsFramework::AssetBrowser::Previewer* CommonPreviewerFactory::CreatePreviewer(QWidget* parent) const
|
||||
{
|
||||
return new CommonPreviewer(parent);
|
||||
}
|
||||
|
||||
bool CommonPreviewerFactory::IsEntrySupported(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) const
|
||||
{
|
||||
return
|
||||
Thumbnails::GetAssetId(entry->GetThumbnailKey(), RPI::MaterialAsset::RTTI_Type()).IsValid() ||
|
||||
Thumbnails::GetAssetId(entry->GetThumbnailKey(), RPI::ModelAsset::RTTI_Type()).IsValid();
|
||||
}
|
||||
|
||||
const QString& CommonPreviewerFactory::GetName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
} // namespace LyIntegration
|
||||
} // namespace AZ
|
||||
+5
-5
@@ -22,14 +22,14 @@ namespace AZ
|
||||
{
|
||||
namespace LyIntegration
|
||||
{
|
||||
class MaterialPreviewerFactory final
|
||||
class CommonPreviewerFactory final
|
||||
: public AzToolsFramework::AssetBrowser::PreviewerFactory
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(MaterialPreviewerFactory, AZ::SystemAllocator, 0);
|
||||
AZ_CLASS_ALLOCATOR(CommonPreviewerFactory, AZ::SystemAllocator, 0);
|
||||
|
||||
MaterialPreviewerFactory() = default;
|
||||
~MaterialPreviewerFactory() = default;
|
||||
CommonPreviewerFactory() = default;
|
||||
~CommonPreviewerFactory() = default;
|
||||
|
||||
// AzToolsFramework::AssetBrowser::PreviewerFactory overrides...
|
||||
AzToolsFramework::AssetBrowser::Previewer* CreatePreviewer(QWidget* parent = nullptr) const override;
|
||||
@@ -37,7 +37,7 @@ namespace AZ
|
||||
const QString& GetName() const override;
|
||||
|
||||
private:
|
||||
QString m_name = "MaterialPreviewer";
|
||||
QString m_name = "CommonPreviewer";
|
||||
};
|
||||
} // namespace LyIntegration
|
||||
} // namespace AZ
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
|
||||
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.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>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace LyIntegration
|
||||
{
|
||||
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();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
CommonThumbnailRenderer::~CommonThumbnailRenderer()
|
||||
{
|
||||
if (m_currentStep != Step::None)
|
||||
{
|
||||
CommonThumbnailRenderer::SetStep(Step::ReleaseResources);
|
||||
}
|
||||
AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::MultiHandler::BusDisconnect();
|
||||
SystemTickBus::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();
|
||||
}
|
||||
|
||||
AZStd::shared_ptr<ThumbnailRendererData> CommonThumbnailRenderer::GetData() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
void CommonThumbnailRenderer::RenderThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey thumbnailKey, [[maybe_unused]] int thumbnailSize)
|
||||
{
|
||||
m_data->m_thumbnailQueue.push(thumbnailKey);
|
||||
if (m_currentStep == Step::None)
|
||||
{
|
||||
SetStep(Step::Initialize);
|
||||
}
|
||||
}
|
||||
} // namespace Thumbnails
|
||||
} // namespace LyIntegration
|
||||
} // namespace AZ
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzToolsFramework/Thumbnails/Thumbnail.h>
|
||||
#include <AzToolsFramework/Thumbnails/ThumbnailerBus.h>
|
||||
#include <Thumbnails/Rendering/ThumbnailRendererContext.h>
|
||||
#include <Thumbnails/Rendering/ThumbnailRendererData.h>
|
||||
|
||||
// Disables warning messages triggered by the Qt library
|
||||
// 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>
|
||||
AZ_POP_DISABLE_WARNING
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace LyIntegration
|
||||
{
|
||||
namespace Thumbnails
|
||||
{
|
||||
class ThumbnailRendererStep;
|
||||
|
||||
//! Provides custom rendering of material and model thumbnails
|
||||
class CommonThumbnailRenderer
|
||||
: private AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::MultiHandler
|
||||
, private SystemTickBus::Handler
|
||||
, public ThumbnailRendererContext
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(CommonThumbnailRenderer, AZ::SystemAllocator, 0)
|
||||
|
||||
CommonThumbnailRenderer();
|
||||
~CommonThumbnailRenderer();
|
||||
|
||||
//! ThumbnailRendererContext overrides...
|
||||
void SetStep(Step step) override;
|
||||
Step GetStep() const override;
|
||||
AZStd::shared_ptr<ThumbnailRendererData> GetData() const override;
|
||||
|
||||
private:
|
||||
//! ThumbnailerRendererRequestsBus::Handler interface overrides...
|
||||
void RenderThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey thumbnailKey, int thumbnailSize) override;
|
||||
bool Installed() const override;
|
||||
|
||||
//! SystemTickBus::Handler interface overrides...
|
||||
void OnSystemTick() override;
|
||||
|
||||
AZStd::unordered_map<Step, AZStd::shared_ptr<ThumbnailRendererStep>> m_steps;
|
||||
Step m_currentStep = Step::None;
|
||||
AZStd::shared_ptr<ThumbnailRendererData> m_data;
|
||||
};
|
||||
} // namespace Thumbnails
|
||||
} // namespace LyIntegration
|
||||
} // namespace AZ
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#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
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#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/default.lightingpreset.azasset";
|
||||
static constexpr const char* DefaultModelPath = "materialeditor/viewportmodels/quadsphere.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";
|
||||
AzFramework::Scene* m_frameworkScene = nullptr;
|
||||
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;
|
||||
|
||||
double m_simulateTime = 0.0f;
|
||||
float m_deltaTime = 0.0f;
|
||||
|
||||
//! 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
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#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/ThumbnailRendererSteps/CaptureStep.h>
|
||||
#include <AzCore/Math/MatrixUtils.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace LyIntegration
|
||||
{
|
||||
namespace Thumbnails
|
||||
{
|
||||
CaptureStep::CaptureStep(ThumbnailRendererContext* context)
|
||||
: ThumbnailRendererStep(context)
|
||||
{
|
||||
}
|
||||
|
||||
void CaptureStep::Start()
|
||||
{
|
||||
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;
|
||||
TickBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
void CaptureStep::Stop()
|
||||
{
|
||||
m_context->GetData()->m_renderPipeline->RemoveFromRenderTick();
|
||||
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(float deltaTime, ScriptTimePoint time)
|
||||
{
|
||||
m_context->GetData()->m_deltaTime = deltaTime;
|
||||
m_context->GetData()->m_simulateTime = time.GetSeconds();
|
||||
|
||||
if (m_readyToCapture && m_ticksToCapture-- <= 0)
|
||||
{
|
||||
m_context->GetData()->m_renderPipeline->AddToRenderTickOnce();
|
||||
|
||||
RPI::AttachmentReadback::CallbackFunction readbackCallback = [&](const RPI::AttachmentReadback::ReadbackResult& result)
|
||||
{
|
||||
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);
|
||||
// Reset the capture flag if the capture request was successful. Otherwise try capture it again next tick.
|
||||
if (startedCapture)
|
||||
{
|
||||
m_readyToCapture = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CaptureStep::OnCaptureFinished([[maybe_unused]] Render::FrameCaptureResult result, [[maybe_unused]] const AZStd::string& info)
|
||||
{
|
||||
m_context->SetStep(Step::FindThumbnailToRender);
|
||||
}
|
||||
} // namespace Thumbnails
|
||||
} // namespace LyIntegration
|
||||
} // namespace AZ
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Atom/Feature/Utils/FrameCaptureBus.h>
|
||||
#include <AzCore/Component/TickBus.h>
|
||||
#include <Thumbnails/Rendering/ThumbnailRendererSteps/ThumbnailRendererStep.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace LyIntegration
|
||||
{
|
||||
namespace Thumbnails
|
||||
{
|
||||
//! CaptureStep renders a thumbnail to a pixmap and notifies MaterialOrModelThumbnail once finished
|
||||
class CaptureStep
|
||||
: public ThumbnailRendererStep
|
||||
, private TickBus::Handler
|
||||
, private Render::FrameCaptureNotificationBus::Handler
|
||||
{
|
||||
public:
|
||||
CaptureStep(ThumbnailRendererContext* context);
|
||||
|
||||
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;
|
||||
};
|
||||
} // namespace Thumbnails
|
||||
} // namespace LyIntegration
|
||||
} // namespace AZ
|
||||
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#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/ThumbnailRendererSteps/FindThumbnailToRenderStep.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace LyIntegration
|
||||
{
|
||||
namespace Thumbnails
|
||||
{
|
||||
FindThumbnailToRenderStep::FindThumbnailToRenderStep(ThumbnailRendererContext* context)
|
||||
: ThumbnailRendererStep(context)
|
||||
{
|
||||
}
|
||||
|
||||
void FindThumbnailToRenderStep::Start()
|
||||
{
|
||||
TickBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
void FindThumbnailToRenderStep::Stop()
|
||||
{
|
||||
TickBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
} // namespace Thumbnails
|
||||
} // namespace LyIntegration
|
||||
} // namespace AZ
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Thumbnails/Rendering/ThumbnailRendererSteps/ThumbnailRendererStep.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace LyIntegration
|
||||
{
|
||||
namespace Thumbnails
|
||||
{
|
||||
//! FindThumbnailToRenderStep checks whether there are any new thumbnails that need to be rendered every tick
|
||||
class FindThumbnailToRenderStep
|
||||
: public ThumbnailRendererStep
|
||||
, private TickBus::Handler
|
||||
{
|
||||
public:
|
||||
FindThumbnailToRenderStep(ThumbnailRendererContext* context);
|
||||
|
||||
void Start() override;
|
||||
void Stop() override;
|
||||
|
||||
private:
|
||||
|
||||
//! AZ::TickBus::Handler interface overrides...
|
||||
void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
|
||||
|
||||
void PickNextThumbnail();
|
||||
};
|
||||
} // namespace Thumbnails
|
||||
} // namespace LyIntegration
|
||||
} // namespace AZ
|
||||
|
||||
+224
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#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 <AzCore/Math/MatrixUtils.h>
|
||||
#include <AzFramework/Components/TransformComponent.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 minimum required feature processors
|
||||
RPI::SceneDescriptor sceneDesc;
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::TransformServiceFeatureProcessor");
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::MeshFeatureProcessor");
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::PointLightFeatureProcessor");
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::SpotLightFeatureProcessor");
|
||||
// There is currently a bug where having multiple DirectionalLightFeatureProcessors active can result in shadow flickering [ATOM-13568]
|
||||
// as well as continually rebuilding MeshDrawPackets [ATOM-13633]. Lets just disable the directional light FP for now.
|
||||
// Possibly re-enable with [GFX TODO][ATOM-13639]
|
||||
// sceneDesc.m_featureProcessorNames.push_back("AZ::Render::DirectionalLightFeatureProcessor");
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::DiskLightFeatureProcessor");
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::CapsuleLightFeatureProcessor");
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::QuadLightFeatureProcessor");
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::DecalTextureArrayFeatureProcessor");
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::ImageBasedLightFeatureProcessor");
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::PostProcessFeatureProcessor");
|
||||
sceneDesc.m_featureProcessorNames.push_back("AZ::Render::SkyBoxFeatureProcessor");
|
||||
|
||||
data->m_scene = RPI::Scene::CreateScene(sceneDesc);
|
||||
|
||||
// Setup scene srg modification callback (to push per-frame values to the shaders)
|
||||
RPI::ShaderResourceGroupCallback callback = [data](RPI::ShaderResourceGroup* srg)
|
||||
{
|
||||
if (srg == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
bool needCompile = false;
|
||||
RHI::ShaderInputConstantIndex timeIndex = srg->FindShaderInputConstantIndex(Name{ "m_time" });
|
||||
if (timeIndex.IsValid())
|
||||
{
|
||||
srg->SetConstant(timeIndex, aznumeric_cast<float>(data->m_simulateTime));
|
||||
needCompile = true;
|
||||
}
|
||||
RHI::ShaderInputConstantIndex deltaTimeIndex = srg->FindShaderInputConstantIndex(Name{ "m_deltaTime" });
|
||||
if (deltaTimeIndex.IsValid())
|
||||
{
|
||||
srg->SetConstant(deltaTimeIndex, data->m_deltaTime);
|
||||
needCompile = true;
|
||||
}
|
||||
|
||||
if (needCompile)
|
||||
{
|
||||
srg->Compile();
|
||||
}
|
||||
};
|
||||
data->m_scene->SetShaderResourceGroupCallback(callback);
|
||||
|
||||
// Bind m_defaultScene to the GameEntityContext's AzFramework::Scene
|
||||
Outcome<AzFramework::Scene*, AZStd::string> createSceneOutcome;
|
||||
AzFramework::SceneSystemRequestBus::BroadcastResult(
|
||||
createSceneOutcome,
|
||||
&AzFramework::SceneSystemRequests::CreateScene,
|
||||
data->m_sceneName);
|
||||
AZ_Assert(createSceneOutcome, createSceneOutcome.GetError().c_str()); // This should never happen unless scene creation has changed.
|
||||
createSceneOutcome.GetValue()->SetSubsystem(data->m_scene.get());
|
||||
data->m_frameworkScene = createSceneOutcome.GetValue();
|
||||
data->m_frameworkScene->SetSubsystem(data->m_scene.get());
|
||||
|
||||
bool success = false;
|
||||
AzFramework::SceneSystemRequestBus::BroadcastResult(
|
||||
success,
|
||||
&AzFramework::SceneSystemRequests::SetSceneForEntityContextId,
|
||||
data->m_entityContext->GetContextId(),
|
||||
data->m_frameworkScene);
|
||||
AZ_Assert(success, "Unable to set entity context on AzFramework::Scene: %s", data->m_sceneName.c_str());
|
||||
|
||||
// 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 = "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;
|
||||
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>(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);
|
||||
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);
|
||||
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
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#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 const char* LightingPresetPath = "lightingpresets/default.lightingpreset.azasset";
|
||||
static constexpr float AspectRatio = 1.0f;
|
||||
static constexpr float NearDist = 0.1f;
|
||||
static constexpr float FarDist = 100.0f;
|
||||
};
|
||||
} // namespace Thumbnails
|
||||
} // namespace LyIntegration
|
||||
} // namespace AZ
|
||||
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#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/SceneSystemBus.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()
|
||||
{
|
||||
m_context->GetData()->m_defaultMaterialAsset.Release();
|
||||
m_context->GetData()->m_defaultModelAsset.Release();
|
||||
m_context->GetData()->m_materialAsset.Release();
|
||||
m_context->GetData()->m_modelAsset.Release();
|
||||
|
||||
if (m_context->GetData()->m_modelEntity)
|
||||
{
|
||||
AzFramework::EntityContextRequestBus::Event(m_context->GetData()->m_entityContext->GetContextId(),
|
||||
&AzFramework::EntityContextRequestBus::Events::DestroyEntity, m_context->GetData()->m_modelEntity);
|
||||
m_context->GetData()->m_modelEntity = nullptr;
|
||||
}
|
||||
|
||||
m_context->GetData()->m_frameworkScene->UnsetSubsystem<RPI::Scene>();
|
||||
|
||||
m_context->GetData()->m_scene->Deactivate();
|
||||
m_context->GetData()->m_scene->RemoveRenderPipeline(m_context->GetData()->m_renderPipeline->GetId());
|
||||
RPI::RPISystemInterface::Get()->UnregisterScene(m_context->GetData()->m_scene);
|
||||
bool sceneRemovedSuccessfully = false;
|
||||
AzFramework::SceneSystemRequestBus::BroadcastResult(
|
||||
sceneRemovedSuccessfully,
|
||||
&AzFramework::SceneSystemRequests::RemoveScene,
|
||||
m_context->GetData()->m_sceneName);
|
||||
m_context->GetData()->m_scene = nullptr;
|
||||
m_context->GetData()->m_renderPipeline = nullptr;
|
||||
}
|
||||
} // namespace Thumbnails
|
||||
} // namespace LyIntegration
|
||||
} // namespace AZ
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#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
|
||||
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace LyIntegration
|
||||
{
|
||||
namespace Thumbnails
|
||||
{
|
||||
class ThumbnailRendererContext;
|
||||
|
||||
//! ThumbnailRendererStep decouples CommonThumbnailRenderer logic into easy-to-understand and debug pieces
|
||||
class ThumbnailRendererStep
|
||||
{
|
||||
public:
|
||||
explicit ThumbnailRendererStep(ThumbnailRendererContext* context) : m_context(context) {}
|
||||
virtual ~ThumbnailRendererStep() = default;
|
||||
|
||||
//! Start is called when step begins execution
|
||||
virtual void Start() {}
|
||||
//! Stop is called when step ends execution
|
||||
virtual void Stop() {}
|
||||
|
||||
protected:
|
||||
ThumbnailRendererContext* m_context;
|
||||
};
|
||||
} // namespace Thumbnails
|
||||
} // namespace LyIntegration
|
||||
} // namespace AZ
|
||||
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Thumbnails/ThumbnailerBus.h"
|
||||
|
||||
#include <Thumbnails/Rendering/ThumbnailRendererData.h>
|
||||
#include <Thumbnails/Rendering/ThumbnailRendererContext.h>
|
||||
#include <Thumbnails/Rendering/ThumbnailRendererSteps/CaptureStep.h>
|
||||
#include <Thumbnails/Rendering/ThumbnailRendererSteps/WaitForAssetsToLoadStep.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace LyIntegration
|
||||
{
|
||||
namespace Thumbnails
|
||||
{
|
||||
WaitForAssetsToLoadStep::WaitForAssetsToLoadStep(ThumbnailRendererContext* context)
|
||||
: ThumbnailRendererStep(context)
|
||||
{
|
||||
}
|
||||
|
||||
void WaitForAssetsToLoadStep::Start()
|
||||
{
|
||||
LoadNextAsset();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
} // namespace Thumbnails
|
||||
} // namespace LyIntegration
|
||||
} // namespace AZ
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <Thumbnails/Rendering/ThumbnailRendererSteps/ThumbnailRendererStep.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace LyIntegration
|
||||
{
|
||||
namespace Thumbnails
|
||||
{
|
||||
//! 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);
|
||||
|
||||
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;
|
||||
};
|
||||
} // namespace Thumbnails
|
||||
} // namespace LyIntegration
|
||||
} // namespace AZ
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <API/EditorAssetSystemAPI.h>
|
||||
#include <AssetBrowser/Thumbnails/ProductThumbnail.h>
|
||||
#include <AssetBrowser/Thumbnails/SourceThumbnail.h>
|
||||
#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
|
||||
#include <Atom/RPI.Reflect/Model/ModelAsset.h>
|
||||
#include <Thumbnails/ThumbnailUtils.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace LyIntegration
|
||||
{
|
||||
namespace Thumbnails
|
||||
{
|
||||
Data::AssetId GetAssetId(AzToolsFramework::Thumbnailer::SharedThumbnailKey key, const Data::AssetType& assetType)
|
||||
{
|
||||
static const Data::AssetId invalidAssetId;
|
||||
|
||||
// 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;
|
||||
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(foundIt, &AzToolsFramework::AssetSystemRequestBus::Events::GetAssetsProducedBySourceUUID, sourceKey->GetSourceUuid(), productsAssetInfo);
|
||||
if (!foundIt)
|
||||
{
|
||||
return invalidAssetId;
|
||||
}
|
||||
auto assetInfoIt = AZStd::find_if(productsAssetInfo.begin(), productsAssetInfo.end(),
|
||||
[&assetType](const Data::AssetInfo& assetInfo)
|
||||
{
|
||||
return assetInfo.m_assetType == assetType;
|
||||
});
|
||||
if (assetInfoIt == productsAssetInfo.end())
|
||||
{
|
||||
return invalidAssetId;
|
||||
}
|
||||
|
||||
return assetInfoIt->m_assetId;
|
||||
}
|
||||
|
||||
// if it's a product thumbnail key just return its assetId
|
||||
auto productKey = azrtti_cast<const AzToolsFramework::AssetBrowser::ProductThumbnailKey*>(key.data());
|
||||
if (productKey && productKey->GetAssetType() == assetType)
|
||||
{
|
||||
return productKey->GetAssetId();
|
||||
}
|
||||
return invalidAssetId;
|
||||
}
|
||||
|
||||
|
||||
QString WordWrap(const QString& string, int maxLength)
|
||||
{
|
||||
QString result;
|
||||
int length = 0;
|
||||
|
||||
for (const QChar& c : string)
|
||||
{
|
||||
if (c == '\n')
|
||||
{
|
||||
length = 0;
|
||||
}
|
||||
else if (length > maxLength)
|
||||
{
|
||||
result.append('\n');
|
||||
length = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
length++;
|
||||
}
|
||||
result.append(c);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} // namespace Thumbnails
|
||||
} // namespace LyIntegration
|
||||
} // namespace AZ
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzToolsFramework/Thumbnails/Thumbnail.h>
|
||||
#endif
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace LyIntegration
|
||||
{
|
||||
namespace Thumbnails
|
||||
{
|
||||
//! Get assetId by assetType that belongs to either source or product thumbnail key
|
||||
Data::AssetId GetAssetId(AzToolsFramework::Thumbnailer::SharedThumbnailKey key, const Data::AssetType& assetType);
|
||||
|
||||
//! 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);
|
||||
} // namespace Thumbnails
|
||||
} // namespace LyIntegration
|
||||
} // namespace AZ
|
||||
Reference in New Issue
Block a user