From 0ebe6c6079f391b53765a580fa0869585f9adb61 Mon Sep 17 00:00:00 2001 From: igarri Date: Thu, 22 Apr 2021 13:19:39 +0100 Subject: [PATCH 001/116] Setup Table model and Table view --- .../AzToolsFramework/AssetBrowserTableModel.h | 36 ++ .../AssetBrowser/AssetBrowserTableModel.cpp | 37 ++ .../AssetBrowser/AssetBrowserTableModel.h | 36 ++ .../Entries/AssetBrowserEntry.cpp | 5 +- .../AssetBrowser/Entries/AssetBrowserEntry.h | 2 + .../Entries/FolderAssetBrowserEntry.cpp | 1 + .../Entries/RootAssetBrowserEntry.cpp | 3 + .../Views/AssetBrowserTableView.cpp | 65 +++ .../Views/AssetBrowserTableView.h | 56 +++ .../AssetBrowser/Views/EntryDelegate.cpp | 44 +-- .../aztoolsframework_files.cmake | 4 + .../AzAssetBrowser/AzAssetBrowserWindow.cpp | 17 + .../AzAssetBrowser/AzAssetBrowserWindow.h | 3 + .../AzAssetBrowser/AzAssetBrowserWindow.ui | 369 ++++++++++-------- 14 files changed, 492 insertions(+), 186 deletions(-) create mode 100644 Code/Framework/AzToolsFramework/AssetBrowserTableModel.h create mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp create mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h create mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp create mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h diff --git a/Code/Framework/AzToolsFramework/AssetBrowserTableModel.h b/Code/Framework/AzToolsFramework/AssetBrowserTableModel.h new file mode 100644 index 0000000000..4e65b3921c --- /dev/null +++ b/Code/Framework/AzToolsFramework/AssetBrowserTableModel.h @@ -0,0 +1,36 @@ +#pragma once +#if !defined(Q_MOC_RUN) +#include +#include +#include + +#include +#include +#include + +AZ_PUSH_DISABLE_WARNING( + 4251, "-Wunknown-warning-option") // 4251: class '...' needs to have dll-interface to be used by clients of class '...' +#include +#include +#include +#endif +AZ_POP_DISABLE_WARNING +namespace AzToolsFramework +{ + namespace AssetBrowser + { + class AssetBrowserTableModel + : public QSortFilterProxyModel + { + Q_OBJECT + public: + AZ_CLASS_ALLOCATOR(AssetBrowserTableModel, AZ::SystemAllocator, 0); + explicit AssetBrowserTableModel(QObject* parent = nullptr); + + QModelIndex mapToSource(const QModelIndex &proxyIndex) const override; + QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override; + QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + }; + } +} diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp new file mode 100644 index 0000000000..a6e5cde6d8 --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp @@ -0,0 +1,37 @@ +#include "AssetBrowserTableModel.h" +namespace AzToolsFramework +{ + namespace AssetBrowser + { + AssetBrowserTableModel::AssetBrowserTableModel(QObject* parent /* = nullptr */) + : QSortFilterProxyModel(parent) + { + } + QModelIndex AssetBrowserTableModel::mapToSource(const QModelIndex& proxyIndex) const + { + AZ_UNUSED(proxyIndex); + return QModelIndex(); + } + QModelIndex AssetBrowserTableModel::mapFromSource(const QModelIndex& sourceIndex) const + { + AZ_UNUSED(sourceIndex); + return QModelIndex(); + } + QModelIndex AssetBrowserTableModel::index(int row, int column, const QModelIndex& parent) const + { + AZ_UNUSED(row); + AZ_UNUSED(column); + AZ_UNUSED(parent); + + return QModelIndex(); + } + QVariant AssetBrowserTableModel::data(const QModelIndex& index, int role) const + { + AZ_UNUSED(index); + AZ_UNUSED(role); + + return QVariant(); + } + } // namespace AssetBrowser +} // namespace AzToolsFramework +#include "AssetBrowser/moc_AssetBrowserTableModel.cpp" diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h new file mode 100644 index 0000000000..4e65b3921c --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h @@ -0,0 +1,36 @@ +#pragma once +#if !defined(Q_MOC_RUN) +#include +#include +#include + +#include +#include +#include + +AZ_PUSH_DISABLE_WARNING( + 4251, "-Wunknown-warning-option") // 4251: class '...' needs to have dll-interface to be used by clients of class '...' +#include +#include +#include +#endif +AZ_POP_DISABLE_WARNING +namespace AzToolsFramework +{ + namespace AssetBrowser + { + class AssetBrowserTableModel + : public QSortFilterProxyModel + { + Q_OBJECT + public: + AZ_CLASS_ALLOCATOR(AssetBrowserTableModel, AZ::SystemAllocator, 0); + explicit AssetBrowserTableModel(QObject* parent = nullptr); + + QModelIndex mapToSource(const QModelIndex &proxyIndex) const override; + QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override; + QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + }; + } +} diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntry.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntry.cpp index 85d5eaecea..8ee8f44137 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntry.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntry.cpp @@ -46,6 +46,7 @@ namespace AzToolsFramework const char* AssetBrowserEntry::m_columnNames[] = { "Name", + "Path", "Source ID", "Fingerprint", "Guid", @@ -128,6 +129,8 @@ namespace AzToolsFramework return QString::fromUtf8(m_name.c_str()); case Column::DisplayName: return m_displayName; + case Column::Path: + return m_displayPath; default: return QVariant(); } @@ -283,4 +286,4 @@ namespace AzToolsFramework } // namespace AssetBrowser } // namespace AzToolsFramework -#include "AssetBrowser/Entries/moc_AssetBrowserEntry.cpp" \ No newline at end of file +#include "AssetBrowser/Entries/moc_AssetBrowserEntry.cpp" diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntry.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntry.h index 6f0eceeeea..ac5470a136 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntry.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntry.h @@ -68,6 +68,7 @@ namespace AzToolsFramework enum class Column { Name, + Path, SourceID, Fingerprint, Guid, @@ -135,6 +136,7 @@ namespace AzToolsFramework protected: AZStd::string m_name; QString m_displayName; + QString m_displayPath; AZStd::string m_relativePath; AZStd::string m_fullPath; AZStd::vector m_children; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/FolderAssetBrowserEntry.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/FolderAssetBrowserEntry.cpp index 88b26ad5ee..0312edbc51 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/FolderAssetBrowserEntry.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/FolderAssetBrowserEntry.cpp @@ -43,6 +43,7 @@ namespace AzToolsFramework void FolderAssetBrowserEntry::UpdateChildPaths(AssetBrowserEntry* child) const { child->m_relativePath = m_relativePath + AZ_CORRECT_DATABASE_SEPARATOR + child->m_name; + child->m_displayPath = QString::fromUtf8(child->m_relativePath.c_str()); child->m_fullPath = m_fullPath + AZ_CORRECT_DATABASE_SEPARATOR + child->m_name; AssetBrowserEntry::UpdateChildPaths(child); } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/RootAssetBrowserEntry.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/RootAssetBrowserEntry.cpp index ada961711a..2ee71c8719 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/RootAssetBrowserEntry.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/RootAssetBrowserEntry.cpp @@ -292,6 +292,9 @@ namespace AzToolsFramework product->m_assetType = productWithUuidDatabaseEntry.second.m_assetType; product->m_assetType.ToString(product->m_assetTypeString); AZ::Data::AssetCatalogRequestBus::BroadcastResult(product->m_relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, assetId); + QString displayPath = QString::fromUtf8(product->m_relativePath.c_str()); + displayPath.remove(QString("/" + QString::fromUtf8(product->m_name.c_str()))); + product->m_displayPath = displayPath; EntryCache::GetInstance()->m_productAssetIdMap[assetId] = product; if (needsAdd) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp new file mode 100644 index 0000000000..ee86f372db --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp @@ -0,0 +1,65 @@ +#include "AssetBrowserTableView.h" + +#pragma optimize("", off) +namespace AzToolsFramework +{ + namespace AssetBrowser + { + AssetBrowserTableView::AssetBrowserTableView(QWidget* parent) + : QTableView(parent) + { + AssetBrowserViewRequestBus::Handler::BusConnect(); + AssetBrowserComponentNotificationBus::Handler::BusConnect(); + } + AssetBrowserTableView::~AssetBrowserTableView() + { + AssetBrowserViewRequestBus::Handler::BusDisconnect(); + AssetBrowserComponentNotificationBus::Handler::BusDisconnect(); + } + void AssetBrowserTableView::setModel(QAbstractItemModel* model) + { + //m_assetBrowserSortFilterProxyModel = qobject_cast(model); + //AZ_Assert(m_assetBrowserSortFilterProxyModel, "Expecting AssetBrowserTableFilterModel"); + //m_assetBrowserModel = qobject_cast(m_assetBrowserSortFilterProxyModel->sourceModel()); + QTableView::setModel(model); + } + void AssetBrowserTableView::SetName(const QString& name) + { + m_name = name; + bool isAssetBrowserComponentReady = false; + AssetBrowserComponentRequestBus::BroadcastResult(isAssetBrowserComponentReady, &AssetBrowserComponentRequests::AreEntriesReady); + if (isAssetBrowserComponentReady) + { + OnAssetBrowserComponentReady(); + } + } + AZStd::vector AssetBrowserTableView::GetSelectedAssets() const + { + return AZStd::vector(); + } + + void AssetBrowserTableView::SelectProduct(AZ::Data::AssetId assetID) + { + AZ_UNUSED(assetID); + } + + void AssetBrowserTableView::SelectFileAtPath(const AZStd::string& assetPath) + { + AZ_UNUSED(assetPath); + } + + void AssetBrowserTableView::ClearFilter() + { + } + + void AssetBrowserTableView::Update() + { + } + + //void AssetBrowserTableView::OnAssetBrowserComponentReady() + //{ + //} + } // namespace AssetBrowser +} // namespace AzToolsFramework +#pragma optimize("", on) +#include "AssetBrowser/Views/moc_AssetBrowserTableView.cpp" diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h new file mode 100644 index 0000000000..04881aa782 --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h @@ -0,0 +1,56 @@ +#pragma once +#if !defined(Q_MOC_RUN) +#include +#include +#include + +#include +//#include + +#include +#include +#include +#endif + +namespace AzToolsFramework +{ + namespace AssetBrowser + { + class AssetBrowserEntry; + class AssetBrowserModel; + class AssetBrowserFilterModel; + class EntryDelegate; + + class AssetBrowserTableView + : public QTableView + , public AssetBrowserViewRequestBus::Handler + , public AssetBrowserComponentNotificationBus::Handler + { + Q_OBJECT + public: + explicit AssetBrowserTableView(QWidget* parent = nullptr); + ~AssetBrowserTableView() override; + + void setModel(QAbstractItemModel *model) override; + void SetName(const QString& name); + + AZStd::vector GetSelectedAssets() const; + + ////////////////////////////////////////////////////////////////////////// + // AssetBrowserViewRequestBus + virtual void SelectProduct(AZ::Data::AssetId assetID) override; + virtual void SelectFileAtPath(const AZStd::string& assetPath) override; + virtual void ClearFilter() override; + virtual void Update() override; + + ////////////////////////////////////////////////////////////////////////// + // AssetBrowserComponentNotificationBus + //void OnAssetBrowserComponentReady() override; + ////////////////////////////////////////////////////////////////////////// + private: + QString m_name; + + + }; + } // namespace AssetBrowser +} // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp index abc290a406..42e161cf37 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp @@ -74,34 +74,34 @@ namespace AzToolsFramework QPoint iconTopLeft(remainingRect.x(), remainingRect.y() + (remainingRect.height() / 2) - (m_iconSize / 2)); auto sourceEntry = azrtti_cast(entry); - - int thumbX = DrawThumbnail(painter, iconTopLeft, iconSize, entry->GetThumbnailKey()); - QPalette actualPalette(option.palette); - - if (sourceEntry) + if (index.column() == static_cast(AssetBrowserEntry::Column::Name)) { - if (m_showSourceControl) + int thumbX = DrawThumbnail(painter, iconTopLeft, iconSize, entry->GetThumbnailKey()); + if (sourceEntry) { - DrawThumbnail(painter, iconTopLeft, iconSize, sourceEntry->GetSourceControlThumbnailKey()); - } - // sources with no children should be greyed out. - if (sourceEntry->GetChildCount() == 0) - { - isEnabled = false; // draw in disabled style. - actualPalette.setCurrentColorGroup(QPalette::Disabled); + if (m_showSourceControl) + { + DrawThumbnail(painter, iconTopLeft, iconSize, sourceEntry->GetSourceControlThumbnailKey()); + } + // sources with no children should be greyed out. + if (sourceEntry->GetChildCount() == 0) + { + isEnabled = false; // draw in disabled style. + actualPalette.setCurrentColorGroup(QPalette::Disabled); + } } + + remainingRect.adjust(thumbX, 0, 0, 0); // bump it to the right by the size of the thumbnail + remainingRect.adjust(ENTRY_SPACING_LEFT_PIXELS, 0, 0, 0); // bump it to the right by the spacing. } + QString displayString = qvariant_cast(index.data(index.column())); - remainingRect.adjust(thumbX, 0, 0, 0); // bump it to the right by the size of the thumbnail - remainingRect.adjust(ENTRY_SPACING_LEFT_PIXELS, 0, 0, 0); // bump it to the right by the spacing. - - style->drawItemText(painter, - remainingRect, - option.displayAlignment, - actualPalette, - isEnabled, - entry->GetDisplayName(), + style->drawItemText( + painter, remainingRect, option.displayAlignment, actualPalette, isEnabled, + index.column() == static_cast(AssetBrowserEntry::Column::Name) + ? qvariant_cast(entry->data(static_cast(AssetBrowserEntry::Column::Name))) + : qvariant_cast(entry->data(static_cast(AssetBrowserEntry::Column::Path))), isSelected ? QPalette::HighlightedText : QPalette::Text); } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake index 2939bb44ad..51ca1a3fdb 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake @@ -545,6 +545,8 @@ set(FILES AssetBrowser/AssetBrowserEntry.h AssetBrowser/AssetBrowserFilterModel.cpp AssetBrowser/AssetBrowserFilterModel.h + AssetBrowser/AssetBrowserTableModel.cpp + AssetBrowser/AssetBrowserTableModel.h AssetBrowser/AssetBrowserModel.cpp AssetBrowser/AssetBrowserModel.h AssetBrowser/AssetEntryChange.h @@ -555,6 +557,8 @@ set(FILES AssetBrowser/EBusFindAssetTypeByName.h AssetBrowser/Views/AssetBrowserTreeView.cpp AssetBrowser/Views/AssetBrowserTreeView.h + AssetBrowser/Views/AssetBrowserTableView.cpp + AssetBrowser/Views/AssetBrowserTableView.h AssetBrowser/Views/EntryDelegate.cpp AssetBrowser/Views/EntryDelegate.h AssetBrowser/Views/AssetBrowserFolderWidget.cpp diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp index 0b23739bb8..733044746e 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include // AzQtComponents @@ -66,6 +67,7 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) : QWidget(parent) , m_ui(new Ui::AzAssetBrowserWindowClass()) , m_filterModel(new AzToolsFramework::AssetBrowser::AssetBrowserFilterModel(parent)) + , m_tableModel(new AzToolsFramework::AssetBrowser::AssetBrowserTableModel(parent)) { m_ui->setupUi(this); m_ui->m_searchWidget->Setup(true, true); @@ -76,7 +78,12 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) m_filterModel->setSourceModel(m_assetBrowserModel); m_filterModel->SetFilter(m_ui->m_searchWidget->GetFilter()); + m_tableModel->setSourceModel(m_filterModel.data()); + m_ui->m_assetBrowserTreeViewWidget->setModel(m_filterModel.data()); + m_ui->m_assetBrowserTableViewWidget->setModel(m_tableModel.data()); + + m_ui->m_assetBrowserTableViewWidget->setVisible(false); connect(m_ui->m_searchWidget->GetFilter().data(), &AssetBrowserEntryFilter::updatedSignal, m_filterModel.data(), &AssetBrowserFilterModel::filterUpdatedSlot); @@ -92,7 +99,11 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::ClearStringFilter, m_ui->m_searchWidget, &SearchWidget::ClearStringFilter); connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::ClearTypeFilter, m_ui->m_searchWidget, &SearchWidget::ClearTypeFilter); + m_ui->m_assetBrowserTreeViewWidget->SetName("AssetBrowserTreeView_main"); + m_ui->m_assetBrowserTableViewWidget->SetName("AssetBrowserTableView_main"); + + connect(m_ui->m_viewSwitcherCheckBox, &QCheckBox::stateChanged, this, &AzAssetBrowserWindow::SwitchDisplayView); } AzAssetBrowserWindow::~AzAssetBrowserWindow() @@ -220,4 +231,10 @@ void AzAssetBrowserWindow::DoubleClickedItem([[maybe_unused]] const QModelIndex& } +void AzAssetBrowserWindow::SwitchDisplayView(const int state) +{ + m_ui->m_assetBrowserTableViewWidget->setVisible(state); + m_ui->m_assetBrowserTreeViewWidget->setVisible(!state); +} + #include diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.h b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.h index 263712dfe2..1a5604b98f 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.h +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.h @@ -29,6 +29,7 @@ namespace AzToolsFramework namespace AssetBrowser { class AssetBrowserFilterModel; + class AssetBrowserTableModel; class AssetBrowserModel; } } @@ -53,6 +54,7 @@ private: QScopedPointer m_ui; QScopedPointer m_filterModel; + QScopedPointer m_tableModel; AzToolsFramework::AssetBrowser::AssetBrowserModel* m_assetBrowserModel; void UpdatePreview() const; @@ -60,6 +62,7 @@ private: private Q_SLOTS: void SelectionChangedSlot(const QItemSelection& selected, const QItemSelection& deselected) const; void DoubleClickedItem(const QModelIndex& element); + void SwitchDisplayView(const int state); }; extern const char* AZ_ASSET_BROWSER_PREVIEW_NAME; diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.ui b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.ui index d6a6b4b8df..d9e42ef906 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.ui +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.ui @@ -1,168 +1,211 @@ - AzAssetBrowserWindowClass - - - - 0 - 0 - 691 - 554 - - - - Asset Browser - - - - 0 - - - - - - 1 - 1 - - - - true - - - - - 0 - 0 - 671 - 534 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - 0 - 0 - - - - + AzAssetBrowserWindowClass + + + + 0 + 0 + 691 + 554 + + + + Asset Browser + + + + 0 + + + + + + 1 + 1 + + + + true + + + + + 0 + 0 + 671 + 534 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + 0 + 0 + + + + + + + + Switch View + + + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + false + + + + + 0 + 0 + + + + vertical-align: top + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed + + + QAbstractItemView::DropOnly + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + QAbstractItemView::ScrollPerPixel + + + false + + + true + + + + + + + + 1 + 0 + + + + QAbstractItemView::DragOnly + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + + + - - - - - - 0 - 0 - - - - Qt::Horizontal - - - false - - - - - 0 - 0 - - - - vertical-align: top - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 1 - 0 - - - - QAbstractItemView::DragOnly - - - - - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - - - - - - - - AzToolsFramework::AssetBrowser::SearchWidget - QWidget -
AzToolsFramework/AssetBrowser/Search/SearchWidget.h
- 1 -
- - AzToolsFramework::AssetBrowser::AssetBrowserTreeView - QTreeView -
AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.h
-
- - AzToolsFramework::AssetBrowser::PreviewerFrame - QFrame -
AzToolsFramework/AssetBrowser/Previewer/PreviewerFrame.h
- 1 -
-
- - + + + AzToolsFramework::AssetBrowser::SearchWidget + QWidget +
AzToolsFramework/AssetBrowser/Search/SearchWidget.h
+ 1 +
+ + AzToolsFramework::AssetBrowser::AssetBrowserTreeView + QTreeView +
AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.h
+
+ + AzToolsFramework::AssetBrowser::PreviewerFrame + QFrame +
AzToolsFramework/AssetBrowser/Previewer/PreviewerFrame.h
+ 1 +
+ + AzToolsFramework::AssetBrowser::AssetBrowserTableView + QTableView +
AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h
+
+
+ +
From b7c2495911484fa0e22a57e77534c3fffdb678d0 Mon Sep 17 00:00:00 2001 From: igarri Date: Wed, 28 Apr 2021 09:38:43 +0100 Subject: [PATCH 002/116] Working base --- .../AssetBrowser/AssetBrowserFilterModel.cpp | 2 + .../AssetBrowser/AssetBrowserFilterModel.h | 1 + .../AssetBrowser/AssetBrowserTableModel.cpp | 94 ++++++++++++++++--- .../AssetBrowser/AssetBrowserTableModel.h | 18 +++- .../Views/AssetBrowserTableView.cpp | 74 +++++++++++++-- .../Views/AssetBrowserTableView.h | 17 +++- .../AzAssetBrowser/AzAssetBrowserWindow.cpp | 4 + 7 files changed, 184 insertions(+), 26 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp index 9c60b6cd35..42498eb76e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp @@ -62,6 +62,7 @@ namespace AzToolsFramework invalidateFilter(); m_invalidateFilter = false; } + Q_EMIT entriesUpdated(); } bool AssetBrowserFilterModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const @@ -162,6 +163,7 @@ namespace AzToolsFramework { m_alreadyRecomputingFilters = false; FilterUpdatedSlotImmediate(); + //beginInsertRows() } ); } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h index f9423b2534..6aa1a08e45 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h @@ -53,6 +53,7 @@ namespace AzToolsFramework Q_SIGNALS: void filterChanged(); + void entriesUpdated(); ////////////////////////////////////////////////////////////////////////// //QSortFilterProxyModel diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp index a6e5cde6d8..e7a49b2d99 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp @@ -6,31 +6,97 @@ namespace AzToolsFramework AssetBrowserTableModel::AssetBrowserTableModel(QObject* parent /* = nullptr */) : QSortFilterProxyModel(parent) { + m_showColumn.insert(static_cast(AssetBrowserEntry::Column::DisplayName)); + m_showColumn.insert(static_cast(AssetBrowserEntry::Column::Path)); } QModelIndex AssetBrowserTableModel::mapToSource(const QModelIndex& proxyIndex) const { - AZ_UNUSED(proxyIndex); - return QModelIndex(); + Q_ASSERT(!proxyIndex.isValid() || proxyIndex.model() == this); + if (!proxyIndex.isValid()) + { + return QModelIndex(); + } + return m_indexMap[proxyIndex.row()]; } QModelIndex AssetBrowserTableModel::mapFromSource(const QModelIndex& sourceIndex) const { - AZ_UNUSED(sourceIndex); - return QModelIndex(); + Q_ASSERT(!sourceIndex.isValid() || sourceIndex.model() == sourceModel()); + if (!sourceIndex.isValid()) + { + return QModelIndex(); + } + return createIndex(m_rowMap[sourceIndex], sourceIndex.column(), sourceIndex.internalPointer()); } - QModelIndex AssetBrowserTableModel::index(int row, int column, const QModelIndex& parent) const - { - AZ_UNUSED(row); - AZ_UNUSED(column); - AZ_UNUSED(parent); + //QModelIndex AssetBrowserTableModel::index(int row, int column, const QModelIndex& parent) const + //{ - return QModelIndex(); - } + // //return parent.isValid() ? QModelIndex() : createIndex(row, column , m_indexMap[row].internalPointer()); + // if (!parent.isValid()) + // { + // QModelIndex(); + // } + // return createIndex(row, column, m_indexMap[row].internalPointer()); + //} QVariant AssetBrowserTableModel::data(const QModelIndex& index, int role) const { - AZ_UNUSED(index); - AZ_UNUSED(role); + //AZ_UNUSED(role); + auto sourceIndex = mapToSource(index); + if (!sourceIndex.isValid()) + return QVariant(); - return QVariant(); + AssetBrowserEntry* entry = GetAssetEntry(sourceIndex); // static_cast(sourceIndex.internalPointer()); + if (entry == nullptr) + { + AZ_Assert(false, "ERROR - index internal pointer not pointing to an AssetEntry. Tree provided by the AssetBrowser invalid?"); + return Qt::PartiallyChecked; + } + + return sourceIndex.data(role); //return entry->data(index.column()); + //return QVariant::fromValue(entry); + + } + bool AssetBrowserTableModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const + { + AZ_UNUSED(source_row); + AZ_UNUSED(source_parent); + return true; + } + bool AssetBrowserTableModel::filterAcceptsColumn(int source_column, const QModelIndex&) const + { + return m_showColumn.find(source_column) != m_showColumn.end(); + } + int AssetBrowserTableModel::BuildMap(const QAbstractItemModel* model, const QModelIndex& parent, int row) + { + int rows = model ? model->rowCount(parent) : 0; + for (int i = 0; i < rows; ++i) + { + auto index = model->index(i, 0, parent); + + m_rowMap[index] = row; + m_indexMap[row] = index; + row = row + 1; + if (model->hasChildren(index)) + { + row = BuildMap(model, index, row); + } + } + return row; + } + AssetBrowserEntry* AssetBrowserTableModel::GetAssetEntry(QModelIndex index) const + { + if (index.isValid()) + { + return static_cast(index.internalPointer()); + } + else + { + AZ_Error("AssetBrowser", false, "Invalid Source Index provided to GetAssetEntry."); + return nullptr; + } + } + void AssetBrowserTableModel::UpdateMap() + { + BuildMap(sourceModel()); } } // namespace AssetBrowser } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h index 4e65b3921c..ef87ad8512 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h @@ -29,8 +29,24 @@ namespace AzToolsFramework QModelIndex mapToSource(const QModelIndex &proxyIndex) const override; QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override; - QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; + //QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + + public Q_SLOTS: + void UpdateMap(); + + protected: + bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override; + bool filterAcceptsColumn(int source_column, const QModelIndex& /*source_parent*/) const override; + + private: + int BuildMap(const QAbstractItemModel* model, const QModelIndex& parent = QModelIndex(), int row = 0); + AssetBrowserEntry* GetAssetEntry(QModelIndex index) const; + + private: + AZStd::fixed_unordered_set(AssetBrowserEntry::Column::Count)> m_showColumn; + QMap m_indexMap; + QMap m_rowMap; }; } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp index ee86f372db..927deb0039 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp @@ -1,5 +1,34 @@ -#include "AssetBrowserTableView.h" +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +AZ_PUSH_DISABLE_WARNING( + 4244 4251 4800, "-Wunknown-warning-option") // conversion from 'int' to 'float', possible loss of data, needs to have dll-interface to + // be used by clients of class 'QFlags::Int': forcing value to bool + // 'true' or 'false' (performance warning) +#include +#include +#include +#include +#include +#include +#include +AZ_POP_DISABLE_WARNING #pragma optimize("", off) namespace AzToolsFramework { @@ -7,7 +36,19 @@ namespace AzToolsFramework { AssetBrowserTableView::AssetBrowserTableView(QWidget* parent) : QTableView(parent) + , m_delegate(new EntryDelegate(this)) + { + setSortingEnabled(true); + setItemDelegate(m_delegate); + // header()->hide(); + setContextMenuPolicy(Qt::CustomContextMenu); + + setMouseTracking(true); + + connect(this, &QTableView::customContextMenuRequested, this, &AssetBrowserTableView::OnContextMenu); + //connect(m_scTimer, &QTimer::timeout, this, &AssetBrowserTreeView::OnUpdateSCThumbnailsList); + AssetBrowserViewRequestBus::Handler::BusConnect(); AssetBrowserComponentNotificationBus::Handler::BusConnect(); } @@ -18,9 +59,9 @@ namespace AzToolsFramework } void AssetBrowserTableView::setModel(QAbstractItemModel* model) { - //m_assetBrowserSortFilterProxyModel = qobject_cast(model); - //AZ_Assert(m_assetBrowserSortFilterProxyModel, "Expecting AssetBrowserTableFilterModel"); - //m_assetBrowserModel = qobject_cast(m_assetBrowserSortFilterProxyModel->sourceModel()); + m_sourceModel = qobject_cast(model); + AZ_Assert(m_sourceModel, "Expecting AssetBrowserTableModel"); + m_sourceFilterModel = qobject_cast(m_sourceModel->sourceModel()); QTableView::setModel(model); } void AssetBrowserTableView::SetName(const QString& name) @@ -54,11 +95,30 @@ namespace AzToolsFramework void AssetBrowserTableView::Update() { + update(); } - //void AssetBrowserTableView::OnAssetBrowserComponentReady() - //{ - //} + void AssetBrowserTableView::OnAssetBrowserComponentReady() + { + } + + void AssetBrowserTableView::OnContextMenu(const QPoint& point) + { + AZ_UNUSED(point); + + auto selectedAssets = GetSelectedAssets(); + if (selectedAssets.size() != 1) + { + return; + } + + QMenu menu(this); + AssetBrowserInteractionNotificationBus::Broadcast(&AssetBrowserInteractionNotificationBus::Events::AddContextMenuActions, this, &menu, selectedAssets); + if (!menu.isEmpty()) + { + menu.exec(QCursor::pos()); + } + } } // namespace AssetBrowser } // namespace AzToolsFramework #pragma optimize("", on) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h index 04881aa782..bec24cca9b 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h @@ -5,7 +5,7 @@ #include #include -//#include +#include #include #include @@ -17,7 +17,7 @@ namespace AzToolsFramework namespace AssetBrowser { class AssetBrowserEntry; - class AssetBrowserModel; + class AssetBrowserTableModel; class AssetBrowserFilterModel; class EntryDelegate; @@ -45,11 +45,20 @@ namespace AzToolsFramework ////////////////////////////////////////////////////////////////////////// // AssetBrowserComponentNotificationBus - //void OnAssetBrowserComponentReady() override; + void OnAssetBrowserComponentReady() override; ////////////////////////////////////////////////////////////////////////// + + private Q_SLOTS: + void OnContextMenu(const QPoint& point); + + //! Get all visible source entries and place them in a queue to update their source control status + //void OnUpdateSCThumbnailsList(); + private: QString m_name; - + QPointer m_sourceFilterModel = nullptr; + QPointer m_sourceModel = nullptr; + EntryDelegate* m_delegate = nullptr; }; } // namespace AssetBrowser diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp index 733044746e..d67ee0d0ca 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp @@ -78,13 +78,17 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) m_filterModel->setSourceModel(m_assetBrowserModel); m_filterModel->SetFilter(m_ui->m_searchWidget->GetFilter()); + m_tableModel->setFilterRole(Qt::DisplayRole); m_tableModel->setSourceModel(m_filterModel.data()); + //m_tableModel->setSourceModel(m_assetBrowserModel); m_ui->m_assetBrowserTreeViewWidget->setModel(m_filterModel.data()); m_ui->m_assetBrowserTableViewWidget->setModel(m_tableModel.data()); m_ui->m_assetBrowserTableViewWidget->setVisible(false); + connect(m_filterModel.data(), &AssetBrowserFilterModel::entriesUpdated, m_tableModel.data(), &AssetBrowserTableModel::UpdateMap); + connect(m_ui->m_searchWidget->GetFilter().data(), &AssetBrowserEntryFilter::updatedSignal, m_filterModel.data(), &AssetBrowserFilterModel::filterUpdatedSlot); connect(m_filterModel.data(), &AssetBrowserFilterModel::filterChanged, this, [this]() From 65550d3f1c3ec5d011485a8d9fdbe973b6789710 Mon Sep 17 00:00:00 2001 From: igarri Date: Mon, 10 May 2021 10:39:01 +0100 Subject: [PATCH 003/116] Entries updating on the table view --- .../AssetBrowser/AssetBrowserFilterModel.cpp | 4 +- .../AssetBrowser/AssetBrowserModel.cpp | 3 +- .../AssetBrowser/AssetBrowserTableModel.cpp | 264 ++++++++++++++++-- .../AssetBrowser/AssetBrowserTableModel.h | 79 +++++- .../Views/AssetBrowserTableView.cpp | 48 +++- .../Views/AssetBrowserTableView.h | 22 +- .../AzAssetBrowser/AzAssetBrowserWindow.cpp | 27 +- .../AzAssetBrowser/AzAssetBrowserWindow.h | 2 + 8 files changed, 395 insertions(+), 54 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp index 42498eb76e..5e9203cc29 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp @@ -31,7 +31,8 @@ namespace AzToolsFramework AssetBrowserFilterModel::AssetBrowserFilterModel(QObject* parent) : QSortFilterProxyModel(parent) { - m_showColumn.insert(AssetBrowserModel::m_column); + m_showColumn.insert(static_cast(AssetBrowserEntry::Column::DisplayName)); + m_showColumn.insert(static_cast(AssetBrowserEntry::Column::Path)); m_collator.setNumericMode(true); AssetBrowserComponentNotificationBus::Handler::BusConnect(); } @@ -163,7 +164,6 @@ namespace AzToolsFramework { m_alreadyRecomputingFilters = false; FilterUpdatedSlotImmediate(); - //beginInsertRows() } ); } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.cpp index d7c0164435..1101e11f3a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.cpp @@ -144,7 +144,8 @@ namespace AzToolsFramework if (parent.isValid()) { if ((parent.column() != static_cast(AssetBrowserEntry::Column::DisplayName)) && - (parent.column() != static_cast(AssetBrowserEntry::Column::Name))) + (parent.column() != static_cast(AssetBrowserEntry::Column::Name)) && + (parent.column() != static_cast(AssetBrowserEntry::Column::Path))) { return 0; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp index e7a49b2d99..7480d17d47 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp @@ -1,4 +1,16 @@ -#include "AssetBrowserTableModel.h" +#include +#include +#include +#include +AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") + +#include +#include + +#include +#include +#include +AZ_POP_DISABLE_WARNING namespace AzToolsFramework { namespace AssetBrowser @@ -6,9 +18,24 @@ namespace AzToolsFramework AssetBrowserTableModel::AssetBrowserTableModel(QObject* parent /* = nullptr */) : QSortFilterProxyModel(parent) { - m_showColumn.insert(static_cast(AssetBrowserEntry::Column::DisplayName)); - m_showColumn.insert(static_cast(AssetBrowserEntry::Column::Path)); + sort(0); + setDynamicSortFilter(false); + setRecursiveFilteringEnabled(true); + AssetBrowserComponentNotificationBus::Handler::BusConnect(); } + AssetBrowserTableModel::~AssetBrowserTableModel() + { + AssetBrowserComponentNotificationBus::Handler::BusDisconnect(); + } + void AssetBrowserTableModel::OnAssetBrowserComponentReady() + { + BuildMap(sourceModel()); + } + void AssetBrowserTableModel::setSourceModel(QAbstractItemModel* sourceModel) + { + QSortFilterProxyModel::setSourceModel(sourceModel); + } + QModelIndex AssetBrowserTableModel::mapToSource(const QModelIndex& proxyIndex) const { Q_ASSERT(!proxyIndex.isValid() || proxyIndex.model() == this); @@ -18,6 +45,11 @@ namespace AzToolsFramework } return m_indexMap[proxyIndex.row()]; } + QModelIndex AssetBrowserTableModel::parent(const QModelIndex& child) const + { + AZ_UNUSED(child); + return QModelIndex(); + } QModelIndex AssetBrowserTableModel::mapFromSource(const QModelIndex& sourceIndex) const { Q_ASSERT(!sourceIndex.isValid() || sourceIndex.model() == sourceModel()); @@ -27,16 +59,14 @@ namespace AzToolsFramework } return createIndex(m_rowMap[sourceIndex], sourceIndex.column(), sourceIndex.internalPointer()); } - //QModelIndex AssetBrowserTableModel::index(int row, int column, const QModelIndex& parent) const - //{ - // //return parent.isValid() ? QModelIndex() : createIndex(row, column , m_indexMap[row].internalPointer()); - // if (!parent.isValid()) - // { - // QModelIndex(); - // } - // return createIndex(row, column, m_indexMap[row].internalPointer()); - //} + QModelIndex AssetBrowserTableModel::index(int row, int column, const QModelIndex& parent) const + { + /*AZ_UNUSED(row); + AZ_UNUSED(column);*/ + return parent.isValid() ? QModelIndex() : createIndex(row, column, m_indexMap[row].internalPointer()); + } + QVariant AssetBrowserTableModel::data(const QModelIndex& index, int role) const { //AZ_UNUSED(role); @@ -47,34 +77,67 @@ namespace AzToolsFramework AssetBrowserEntry* entry = GetAssetEntry(sourceIndex); // static_cast(sourceIndex.internalPointer()); if (entry == nullptr) { - AZ_Assert(false, "ERROR - index internal pointer not pointing to an AssetEntry. Tree provided by the AssetBrowser invalid?"); + AZ_Assert( + false, "ERROR - index internal pointer not pointing to an AssetEntry. Tree provided by the AssetBrowser invalid?"); return Qt::PartiallyChecked; } - return sourceIndex.data(role); //return entry->data(index.column()); + return sourceIndex.data(role); // return entry->data(index.column()); //return QVariant::fromValue(entry); + //AZ_UNUSED(role); + //if (index.isValid()) + //{ + // ////if (role == AssetBrowserModel::EntryRole) + // //{ + // QModelIndex modelIndex = mapFromSource(index); + // auto assetEntry = static_cast(index.internalPointer()); + // return QVariant::fromValue(assetEntry); + //} + //return QVariant(); // AzToolsFramework::AssetBrowser::AssetBrowserModel::data(index, role); } - bool AssetBrowserTableModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const + + + int AssetBrowserTableModel::rowCount(const QModelIndex& parent) const { - AZ_UNUSED(source_row); - AZ_UNUSED(source_parent); - return true; - } - bool AssetBrowserTableModel::filterAcceptsColumn(int source_column, const QModelIndex&) const - { - return m_showColumn.find(source_column) != m_showColumn.end(); + return !parent.isValid() ? m_rowMap.size() : 0; } + int AssetBrowserTableModel::BuildMap(const QAbstractItemModel* model, const QModelIndex& parent, int row) { + //int rows = model ? model->rowCount(parent) : 0; + //for (int i = 0; i < rows; ++i) + //{ + // auto index = model->index(i, 0, parent); + // //if (!model->hasChildren(index)) + // //{ + // beginInsertRows(parent, row, row); + // m_rowMap[index] = row; + // m_indexMap[row] = index; + // endInsertRows(); + // Q_EMIT dataChanged(parent, parent); + // row = row + 1; + // //} + // if (model->hasChildren(index)) + // { + // row = BuildMap(model, index, row); + // } + //} + //return row; int rows = model ? model->rowCount(parent) : 0; for (int i = 0; i < rows; ++i) { auto index = model->index(i, 0, parent); + if (model->hasChildren(index) == false) + { + beginInsertRows(parent, row, row); + m_rowMap[index] = row; + m_indexMap[row] = index; + endInsertRows(); + Q_EMIT dataChanged(parent, parent); + row = row + 1; + } - m_rowMap[index] = row; - m_indexMap[row] = index; - row = row + 1; if (model->hasChildren(index)) { row = BuildMap(model, index, row); @@ -96,8 +159,159 @@ namespace AzToolsFramework } void AssetBrowserTableModel::UpdateMap() { + m_indexMap.clear(); + m_rowMap.clear(); BuildMap(sourceModel()); } + + //---------------------------------------AssetBrowserTableFilterModel-------------------------------------------- + AssetBrowserTableFilterModel::AssetBrowserTableFilterModel(QObject* parent) + : QSortFilterProxyModel(parent) + { + m_showColumn.insert(static_cast(AssetBrowserEntry::Column::DisplayName)); + m_showColumn.insert(static_cast(AssetBrowserEntry::Column::Path)); + AssetBrowserComponentNotificationBus::Handler::BusConnect(); + } + + AssetBrowserTableFilterModel::~AssetBrowserTableFilterModel() + { + AssetBrowserComponentNotificationBus::Handler::BusDisconnect(); + } + + void AssetBrowserTableFilterModel::setSourceModel(QAbstractItemModel* sourceModel) + { + QSortFilterProxyModel::setSourceModel(sourceModel); + } + + void AssetBrowserTableFilterModel::SetFilter(FilterConstType filter) + { + connect(filter.data(), &AssetBrowserEntryFilter::updatedSignal, this, &AssetBrowserTableFilterModel::filterUpdatedSlot); + m_filter = filter; + m_invalidateFilter = true; + // asset browser entries are not guaranteed to have populated when the filter is set, delay filtering until they are + bool isAssetBrowserComponentReady = false; + AssetBrowserComponentRequestBus::BroadcastResult(isAssetBrowserComponentReady, &AssetBrowserComponentRequests::AreEntriesReady); + if (isAssetBrowserComponentReady) + { + OnAssetBrowserComponentReady(); + } + } + + void AssetBrowserTableFilterModel::FilterUpdatedSlotImmediate() + { + auto compFilter = qobject_cast>(m_filter); + if (compFilter) + { + auto& subFilters = compFilter->GetSubFilters(); + auto it = AZStd::find_if(subFilters.begin(), subFilters.end(), [subFilters](FilterConstType filter) -> bool { + auto assetTypeFilter = qobject_cast>(filter); + return !assetTypeFilter.isNull(); + }); + if (it != subFilters.end()) + { + m_assetTypeFilter = qobject_cast>(*it); + } + it = AZStd::find_if(subFilters.begin(), subFilters.end(), [subFilters](FilterConstType filter) -> bool { + auto stringFilter = qobject_cast>(filter); + return !stringFilter.isNull(); + }); + if (it != subFilters.end()) + { + m_stringFilter = qobject_cast>(*it); + } + } + invalidateFilter(); + Q_EMIT filterChanged(); + } + + void AssetBrowserTableFilterModel::OnAssetBrowserComponentReady() + { + if (m_invalidateFilter) + { + invalidateFilter(); + m_invalidateFilter = false; + } + Q_EMIT entriesUpdated(); + } + + bool AssetBrowserTableFilterModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const + { + AZ_UNUSED(source_row); + AZ_UNUSED(source_parent); + QModelIndex idx = sourceModel()->index(source_row, 0, source_parent); + if (!idx.isValid()) + { + return false; + } + // no filter present, every entry is visible + if (!m_filter) + { + return true; + } + + //// the entry is the internal pointer of the index + //auto entry = static_cast(idx.internalPointer()); + + //if (entry) + //{ + // // root should return true even if its not displayed in the treeview + // if (entry && entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Root) + // { + // return true; + // } + // return m_filter->Match(entry); + //} + return true; + } + + bool AssetBrowserTableFilterModel::filterAcceptsColumn(int source_column, const QModelIndex&) const + { + return m_showColumn.find(source_column) != m_showColumn.end(); + } + + bool AssetBrowserTableFilterModel::lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const + { + if (source_left.column() == source_right.column()) + { + QVariant leftData = sourceModel()->data(source_left, AssetBrowserModel::Roles::EntryRole); + QVariant rightData = sourceModel()->data(source_right, AssetBrowserModel::Roles::EntryRole); + if (leftData.canConvert() && rightData.canConvert()) + { + auto leftEntry = qvariant_cast(leftData); + auto rightEntry = qvariant_cast(rightData); + + // folders should always come first + if (azrtti_istypeof(leftEntry) && + azrtti_istypeof(rightEntry)) + { + return false; + } + if (azrtti_istypeof(leftEntry) && + azrtti_istypeof(rightEntry)) + { + return true; + } + + // if both entries are of same type, sort alphabetically + return m_collator.compare(leftEntry->GetDisplayName(), rightEntry->GetDisplayName()) > 0; + } + } + return QSortFilterProxyModel::lessThan(source_left, source_right); + } + + void AssetBrowserTableFilterModel::filterUpdatedSlot() + { + if (!m_alreadyRecomputingFilters) + { + m_alreadyRecomputingFilters = true; + // de-bounce it, since we may get many filter updates all at once. + QTimer::singleShot(0, this, [this]() { + m_alreadyRecomputingFilters = false; + FilterUpdatedSlotImmediate(); + }); + } + } + } // namespace AssetBrowser } // namespace AzToolsFramework #include "AssetBrowser/moc_AssetBrowserTableModel.cpp" diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h index ef87ad8512..8ffd1a469e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h @@ -21,32 +21,87 @@ namespace AzToolsFramework { class AssetBrowserTableModel : public QSortFilterProxyModel + , public AssetBrowserComponentNotificationBus::Handler { Q_OBJECT + public: AZ_CLASS_ALLOCATOR(AssetBrowserTableModel, AZ::SystemAllocator, 0); explicit AssetBrowserTableModel(QObject* parent = nullptr); - - QModelIndex mapToSource(const QModelIndex &proxyIndex) const override; - QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override; - //QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; + ~AssetBrowserTableModel(); + //////////////////////////////////////////////////////////////////// + // AssetBrowserComponentNotificationBus + //////////////////////////////////////////////////////////////////// + void OnAssetBrowserComponentReady() override; + void setSourceModel(QAbstractItemModel* sourceModel) override; + //////////////////////////////////////////////////////////////////// + // QSortFilterProxyModel + QModelIndex mapToSource(const QModelIndex& proxyIndex) const override; + QModelIndex mapFromSource(const QModelIndex& sourceIndex) const override; + QModelIndex parent(const QModelIndex& child) const override; + QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; public Q_SLOTS: void UpdateMap(); - protected: - bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override; - bool filterAcceptsColumn(int source_column, const QModelIndex& /*source_parent*/) const override; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + //QVariant headerData(int section, Qt::Orientation orientation, int role /* = Qt::DisplayRole */) const override; + //////////////////////////////////////////////////////////////////// private: - int BuildMap(const QAbstractItemModel* model, const QModelIndex& parent = QModelIndex(), int row = 0); AssetBrowserEntry* GetAssetEntry(QModelIndex index) const; - + int BuildMap(const QAbstractItemModel* model, const QModelIndex& parent = QModelIndex(), int row = 0); private: - AZStd::fixed_unordered_set(AssetBrowserEntry::Column::Count)> m_showColumn; QMap m_indexMap; QMap m_rowMap; }; - } -} + + class AssetBrowserTableFilterModel + : public QSortFilterProxyModel + , public AssetBrowserComponentNotificationBus::Handler + { + Q_OBJECT + public: + explicit AssetBrowserTableFilterModel(QObject* parent = nullptr); + ~AssetBrowserTableFilterModel(); + + void setSourceModel(QAbstractItemModel* sourceModel) override; + // asset type filtering + void SetFilter(FilterConstType filter); + void FilterUpdatedSlotImmediate(); + + ////////////////////////////////////////////////////////////////////////// + // AssetBrowserComponentNotificationBus + ////////////////////////////////////////////////////////////////////////// + void OnAssetBrowserComponentReady() override; + + Q_SIGNALS: + void filterChanged(); + void entriesUpdated(); + + ////////////////////////////////////////////////////////////////////////// + // QSortFilterProxyModel + protected: + bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override; + bool filterAcceptsColumn(int source_column, const QModelIndex& /*source_parent*/) const override; + bool lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const override; + ////////////////////////////////////////////////////////////////////////// + + public Q_SLOTS: + void filterUpdatedSlot(); + + private: + AZStd::fixed_unordered_set(AssetBrowserEntry::Column::Count)> m_showColumn; + bool m_alreadyRecomputingFilters = false; + // asset source name match filter + FilterConstType m_filter; + AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // 4251: class '...' needs to have dll-interface to be used by clients of class '...' + QWeakPointer m_stringFilter; + QWeakPointer m_assetTypeFilter; + QCollator m_collator; // cache the collator as its somewhat expensive to constantly create and destroy one. + AZ_POP_DISABLE_WARNING + bool m_invalidateFilter = false; + }; + } // namespace AssetBrowser +} // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp index 927deb0039..aa35d99894 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp @@ -41,13 +41,13 @@ namespace AzToolsFramework { setSortingEnabled(true); setItemDelegate(m_delegate); - // header()->hide(); + //header()->hide(); setContextMenuPolicy(Qt::CustomContextMenu); setMouseTracking(true); connect(this, &QTableView::customContextMenuRequested, this, &AssetBrowserTableView::OnContextMenu); - //connect(m_scTimer, &QTimer::timeout, this, &AssetBrowserTreeView::OnUpdateSCThumbnailsList); + connect(m_scTimer, &QTimer::timeout, this, &AssetBrowserTableView::OnUpdateSCThumbnailsList); AssetBrowserViewRequestBus::Handler::BusConnect(); AssetBrowserComponentNotificationBus::Handler::BusConnect(); @@ -59,9 +59,9 @@ namespace AzToolsFramework } void AssetBrowserTableView::setModel(QAbstractItemModel* model) { - m_sourceModel = qobject_cast(model); - AZ_Assert(m_sourceModel, "Expecting AssetBrowserTableModel"); - m_sourceFilterModel = qobject_cast(m_sourceModel->sourceModel()); + m_filterModel = qobject_cast(model); + AZ_Assert(m_filterModel, "Expecting AssetBrowserTableModel"); + m_sourceModel = qobject_cast(m_filterModel->sourceModel()); QTableView::setModel(model); } void AssetBrowserTableView::SetName(const QString& name) @@ -76,9 +76,40 @@ namespace AzToolsFramework } AZStd::vector AssetBrowserTableView::GetSelectedAssets() const { - return AZStd::vector(); - } + QModelIndexList sourceIndexes{}; + //for (const auto& index : selectedIndexes()) + //{ + // sourceIndexes.push_back(m_sourceModel->mapToSource(index)); + //} + AZStd::vector entries; + //AssetBrowserModel::SourceIndexesToAssetDatabaseEntries(sourceIndexes, entries); + return entries; + } + void AssetBrowserTableView::selectionChanged(const QItemSelection& selected, const QItemSelection& deselected) + { + AZ_UNUSED(selected); + AZ_UNUSED(deselected); + } + void AssetBrowserTableView::rowsAboutToBeRemoved(const QModelIndex& parent, int start, int end) + { + // if selected entry is being removed, clear selection so not to select (and attempt to preview) other entries potentially + // marked for deletion + if (selectionModel() && selectionModel()->selectedIndexes().size() == 1) + { + QModelIndex selectedIndex = selectionModel()->selectedIndexes().first(); + QModelIndex parentSelectedIndex = selectedIndex.parent(); + if (parentSelectedIndex == parent && selectedIndex.row() >= start && selectedIndex.row() <= end) + { + selectionModel()->clear(); + } + } + QTableView::rowsAboutToBeRemoved(parent, start, end); + } + void AssetBrowserTableView::OnUpdateSCThumbnailsList() + { + + } void AssetBrowserTableView::SelectProduct(AZ::Data::AssetId assetID) { AZ_UNUSED(assetID); @@ -91,6 +122,9 @@ namespace AzToolsFramework void AssetBrowserTableView::ClearFilter() { + emit ClearStringFilter(); + emit ClearTypeFilter(); + m_sourceModel->FilterUpdatedSlotImmediate(); } void AssetBrowserTableView::Update() diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h index bec24cca9b..aef7353334 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h @@ -48,18 +48,32 @@ namespace AzToolsFramework void OnAssetBrowserComponentReady() override; ////////////////////////////////////////////////////////////////////////// - private Q_SLOTS: - void OnContextMenu(const QPoint& point); + + Q_SIGNALS: + void selectionChangedSignal(const QItemSelection& selected, const QItemSelection& deselected); + void ClearStringFilter(); + void ClearTypeFilter(); + + protected Q_SLOTS: + void selectionChanged(const QItemSelection& selected, const QItemSelection& deselected) override; + void rowsAboutToBeRemoved(const QModelIndex& parent, int start, int end) override; //! Get all visible source entries and place them in a queue to update their source control status //void OnUpdateSCThumbnailsList(); private: QString m_name; - QPointer m_sourceFilterModel = nullptr; - QPointer m_sourceModel = nullptr; + QPointer m_filterModel = nullptr; + QPointer m_sourceModel = nullptr; EntryDelegate* m_delegate = nullptr; + QTimer* m_scTimer = nullptr; + const int m_scUpdateInterval = 100; + + private Q_SLOTS: + void OnContextMenu(const QPoint& point); + //! Get all visible source entries and place them in a queue to update their source control status + void OnUpdateSCThumbnailsList(); }; } // namespace AssetBrowser } // namespace AzToolsFramework diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp index d67ee0d0ca..fb850f4f26 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp @@ -68,6 +68,7 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) , m_ui(new Ui::AzAssetBrowserWindowClass()) , m_filterModel(new AzToolsFramework::AssetBrowser::AssetBrowserFilterModel(parent)) , m_tableModel(new AzToolsFramework::AssetBrowser::AssetBrowserTableModel(parent)) + , m_tableFilterModel(new AzToolsFramework::AssetBrowser::AssetBrowserTableFilterModel(parent)) { m_ui->setupUi(this); m_ui->m_searchWidget->Setup(true, true); @@ -82,12 +83,18 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) m_tableModel->setSourceModel(m_filterModel.data()); //m_tableModel->setSourceModel(m_assetBrowserModel); - m_ui->m_assetBrowserTreeViewWidget->setModel(m_filterModel.data()); - m_ui->m_assetBrowserTableViewWidget->setModel(m_tableModel.data()); + m_tableFilterModel->setSourceModel(m_tableModel.data()); + m_tableFilterModel->SetFilter(m_ui->m_searchWidget->GetFilter()); + + m_ui->m_assetBrowserTreeViewWidget->setModel(m_filterModel.data()); + m_ui->m_assetBrowserTreeViewWidget->hideColumn(static_cast(AssetBrowserEntry::Column::Path)); + + //m_ui->m_assetBrowserTableViewWidget->setModel(m_tableFilterModel.data()); + m_ui->m_assetBrowserTableViewWidget->setModel(m_tableModel.data()); m_ui->m_assetBrowserTableViewWidget->setVisible(false); - connect(m_filterModel.data(), &AssetBrowserFilterModel::entriesUpdated, m_tableModel.data(), &AssetBrowserTableModel::UpdateMap); + //connect(m_filterModel.data(), &AssetBrowserFilterModel::entriesUpdated, m_tableModel.data(), &AssetBrowserTableModel::UpdateMap); connect(m_ui->m_searchWidget->GetFilter().data(), &AssetBrowserEntryFilter::updatedSignal, m_filterModel.data(), &AssetBrowserFilterModel::filterUpdatedSlot); @@ -97,6 +104,17 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) const bool selectFirstFilteredIndex = false; m_ui->m_assetBrowserTreeViewWidget->UpdateAfterFilter(hasFilter, selectFirstFilteredIndex); }); + + //connect( m_ui->m_searchWidget->GetFilter().data(), &AssetBrowserEntryFilter::updatedSignal, m_tableFilterModel.data(), + // &AssetBrowserTableFilterModel::filterUpdatedSlot); + //connect(m_tableFilterModel.data(), &AssetBrowserTableFilterModel::filterChanged, this, [this]() { + // const bool hasFilter = !m_ui->m_searchWidget->GetFilterString().isEmpty(); + // const bool selectFirstFilteredIndex = false; + // m_ui->m_assetBrowserTableViewWidget->UpdateAfterFilter(hasFilter, selectFirstFilteredIndex); + //}); + + connect(m_filterModel.data(), &AssetBrowserFilterModel::filterChanged, m_tableModel.data(), &AssetBrowserTableModel::UpdateMap); + connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::selectionChangedSignal, this, &AzAssetBrowserWindow::SelectionChangedSlot); connect(m_ui->m_assetBrowserTreeViewWidget, &QAbstractItemView::doubleClicked, this, &AzAssetBrowserWindow::DoubleClickedItem); @@ -104,6 +122,9 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::ClearStringFilter, m_ui->m_searchWidget, &SearchWidget::ClearStringFilter); connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::ClearTypeFilter, m_ui->m_searchWidget, &SearchWidget::ClearTypeFilter); + connect(m_ui->m_assetBrowserTableViewWidget, &AssetBrowserTableView::ClearStringFilter, m_ui->m_searchWidget, &SearchWidget::ClearStringFilter); + connect(m_ui->m_assetBrowserTableViewWidget, &AssetBrowserTableView::ClearTypeFilter, m_ui->m_searchWidget, &SearchWidget::ClearTypeFilter); + m_ui->m_assetBrowserTreeViewWidget->SetName("AssetBrowserTreeView_main"); m_ui->m_assetBrowserTableViewWidget->SetName("AssetBrowserTableView_main"); diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.h b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.h index 1a5604b98f..a8a8474ef8 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.h +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.h @@ -31,6 +31,7 @@ namespace AzToolsFramework class AssetBrowserFilterModel; class AssetBrowserTableModel; class AssetBrowserModel; + class AssetBrowserTableFilterModel; } } @@ -55,6 +56,7 @@ private: QScopedPointer m_ui; QScopedPointer m_filterModel; QScopedPointer m_tableModel; + QScopedPointer m_tableFilterModel; AzToolsFramework::AssetBrowser::AssetBrowserModel* m_assetBrowserModel; void UpdatePreview() const; From 6e15e87e41d610391facaeb210bc0d5b484c1d1c Mon Sep 17 00:00:00 2001 From: igarri Date: Mon, 10 May 2021 15:52:35 +0100 Subject: [PATCH 004/116] Asset Browser Table view filtering --- .../AssetBrowser/AssetBrowserFilterModel.h | 2 +- .../AssetBrowser/AssetBrowserTableModel.cpp | 302 ++++++++++-------- .../AssetBrowser/AssetBrowserTableModel.h | 87 ++--- .../AzAssetBrowser/AzAssetBrowserWindow.cpp | 6 +- .../AzAssetBrowser/AzAssetBrowserWindow.h | 2 +- 5 files changed, 217 insertions(+), 182 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h index 6aa1a08e45..3fff43859f 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h @@ -45,7 +45,7 @@ namespace AzToolsFramework //asset type filtering void SetFilter(FilterConstType filter); void FilterUpdatedSlotImmediate(); - + const FilterConstType& GetFilter() const { return m_filter; } ////////////////////////////////////////////////////////////////////////// // AssetBrowserComponentNotificationBus ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp index 7480d17d47..b75d3e9400 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp @@ -5,7 +5,7 @@ AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") #include -#include +#include #include #include @@ -29,10 +29,12 @@ namespace AzToolsFramework } void AssetBrowserTableModel::OnAssetBrowserComponentReady() { - BuildMap(sourceModel()); + //BuildMap(sourceModel()); } void AssetBrowserTableModel::setSourceModel(QAbstractItemModel* sourceModel) { + m_filterModel = qobject_cast(sourceModel); + AZ_Assert(m_filterModel, "Expecting AssetBrowserFilterModel"); QSortFilterProxyModel::setSourceModel(sourceModel); } @@ -60,6 +62,18 @@ namespace AzToolsFramework return createIndex(m_rowMap[sourceIndex], sourceIndex.column(), sourceIndex.internalPointer()); } + bool AssetBrowserTableModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const + { + AZ_UNUSED(source_row); + AZ_UNUSED(source_parent); + // no filter present, every entry is not visible + if (!m_filterModel->GetFilter()) + { + return false; + } + return true; + } + QModelIndex AssetBrowserTableModel::index(int row, int column, const QModelIndex& parent) const { /*AZ_UNUSED(row); @@ -159,158 +173,172 @@ namespace AzToolsFramework } void AssetBrowserTableModel::UpdateMap() { - m_indexMap.clear(); - m_rowMap.clear(); + //m_indexMap.clear(); + //m_rowMap.clear(); + + if (m_indexMap.size() > 0) + { + //beginRemoveRows(m_indexMap.first().parent(), m_indexMap.first().row(), m_indexMap.last().row()); + for (const auto& key : m_indexMap.keys()) + { + beginRemoveRows(m_indexMap[key], m_indexMap[key].row(), m_indexMap[key].row()); + m_rowMap.remove(m_indexMap[key]); + m_indexMap.remove(key); + endRemoveRows(); + } + //endRemoveRows(); + } + BuildMap(sourceModel()); } //---------------------------------------AssetBrowserTableFilterModel-------------------------------------------- - AssetBrowserTableFilterModel::AssetBrowserTableFilterModel(QObject* parent) - : QSortFilterProxyModel(parent) - { - m_showColumn.insert(static_cast(AssetBrowserEntry::Column::DisplayName)); - m_showColumn.insert(static_cast(AssetBrowserEntry::Column::Path)); - AssetBrowserComponentNotificationBus::Handler::BusConnect(); - } + //AssetBrowserTableFilterModel::AssetBrowserTableFilterModel(QObject* parent) + // : QSortFilterProxyModel(parent) + //{ + // m_showColumn.insert(static_cast(AssetBrowserEntry::Column::DisplayName)); + // m_showColumn.insert(static_cast(AssetBrowserEntry::Column::Path)); + // AssetBrowserComponentNotificationBus::Handler::BusConnect(); + //} - AssetBrowserTableFilterModel::~AssetBrowserTableFilterModel() - { - AssetBrowserComponentNotificationBus::Handler::BusDisconnect(); - } + //AssetBrowserTableFilterModel::~AssetBrowserTableFilterModel() + //{ + // AssetBrowserComponentNotificationBus::Handler::BusDisconnect(); + //} - void AssetBrowserTableFilterModel::setSourceModel(QAbstractItemModel* sourceModel) - { - QSortFilterProxyModel::setSourceModel(sourceModel); - } + //void AssetBrowserTableFilterModel::setSourceModel(QAbstractItemModel* sourceModel) + //{ + // QSortFilterProxyModel::setSourceModel(sourceModel); + //} - void AssetBrowserTableFilterModel::SetFilter(FilterConstType filter) - { - connect(filter.data(), &AssetBrowserEntryFilter::updatedSignal, this, &AssetBrowserTableFilterModel::filterUpdatedSlot); - m_filter = filter; - m_invalidateFilter = true; - // asset browser entries are not guaranteed to have populated when the filter is set, delay filtering until they are - bool isAssetBrowserComponentReady = false; - AssetBrowserComponentRequestBus::BroadcastResult(isAssetBrowserComponentReady, &AssetBrowserComponentRequests::AreEntriesReady); - if (isAssetBrowserComponentReady) - { - OnAssetBrowserComponentReady(); - } - } + //void AssetBrowserTableFilterModel::SetFilter(FilterConstType filter) + //{ + // connect(filter.data(), &AssetBrowserEntryFilter::updatedSignal, this, &AssetBrowserTableFilterModel::filterUpdatedSlot); + // m_filter = filter; + // m_invalidateFilter = true; + // // asset browser entries are not guaranteed to have populated when the filter is set, delay filtering until they are + // bool isAssetBrowserComponentReady = false; + // AssetBrowserComponentRequestBus::BroadcastResult(isAssetBrowserComponentReady, &AssetBrowserComponentRequests::AreEntriesReady); + // if (isAssetBrowserComponentReady) + // { + // OnAssetBrowserComponentReady(); + // } + //} - void AssetBrowserTableFilterModel::FilterUpdatedSlotImmediate() - { - auto compFilter = qobject_cast>(m_filter); - if (compFilter) - { - auto& subFilters = compFilter->GetSubFilters(); - auto it = AZStd::find_if(subFilters.begin(), subFilters.end(), [subFilters](FilterConstType filter) -> bool { - auto assetTypeFilter = qobject_cast>(filter); - return !assetTypeFilter.isNull(); - }); - if (it != subFilters.end()) - { - m_assetTypeFilter = qobject_cast>(*it); - } - it = AZStd::find_if(subFilters.begin(), subFilters.end(), [subFilters](FilterConstType filter) -> bool { - auto stringFilter = qobject_cast>(filter); - return !stringFilter.isNull(); - }); - if (it != subFilters.end()) - { - m_stringFilter = qobject_cast>(*it); - } - } - invalidateFilter(); - Q_EMIT filterChanged(); - } + //void AssetBrowserTableFilterModel::FilterUpdatedSlotImmediate() + //{ + // auto compFilter = qobject_cast>(m_filter); + // if (compFilter) + // { + // auto& subFilters = compFilter->GetSubFilters(); + // auto it = AZStd::find_if(subFilters.begin(), subFilters.end(), [subFilters](FilterConstType filter) -> bool { + // auto assetTypeFilter = qobject_cast>(filter); + // return !assetTypeFilter.isNull(); + // }); + // if (it != subFilters.end()) + // { + // m_assetTypeFilter = qobject_cast>(*it); + // } + // it = AZStd::find_if(subFilters.begin(), subFilters.end(), [subFilters](FilterConstType filter) -> bool { + // auto stringFilter = qobject_cast>(filter); + // return !stringFilter.isNull(); + // }); + // if (it != subFilters.end()) + // { + // m_stringFilter = qobject_cast>(*it); + // } + // } + // invalidateFilter(); + // Q_EMIT filterChanged(); + //} - void AssetBrowserTableFilterModel::OnAssetBrowserComponentReady() - { - if (m_invalidateFilter) - { - invalidateFilter(); - m_invalidateFilter = false; - } - Q_EMIT entriesUpdated(); - } + //void AssetBrowserTableFilterModel::OnAssetBrowserComponentReady() + //{ + // if (m_invalidateFilter) + // { + // invalidateFilter(); + // m_invalidateFilter = false; + // } + // Q_EMIT entriesUpdated(); + //} - bool AssetBrowserTableFilterModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const - { - AZ_UNUSED(source_row); - AZ_UNUSED(source_parent); - QModelIndex idx = sourceModel()->index(source_row, 0, source_parent); - if (!idx.isValid()) - { - return false; - } - // no filter present, every entry is visible - if (!m_filter) - { - return true; - } + //bool AssetBrowserTableFilterModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const + //{ + // AZ_UNUSED(source_row); + // AZ_UNUSED(source_parent); + // QModelIndex idx = sourceModel()->index(source_row, 0, source_parent); + // if (!idx.isValid()) + // { + // return false; + // } + // // no filter present, every entry is visible + // if (!m_filter) + // { + // return true; + // } - //// the entry is the internal pointer of the index - //auto entry = static_cast(idx.internalPointer()); + // //// the entry is the internal pointer of the index + // //auto entry = static_cast(idx.internalPointer()); - //if (entry) - //{ - // // root should return true even if its not displayed in the treeview - // if (entry && entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Root) - // { - // return true; - // } - // return m_filter->Match(entry); - //} - return true; - } + // //if (entry) + // //{ + // // // root should return true even if its not displayed in the treeview + // // if (entry && entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Root) + // // { + // // return true; + // // } + // // return m_filter->Match(entry); + // //} + // return true; + //} - bool AssetBrowserTableFilterModel::filterAcceptsColumn(int source_column, const QModelIndex&) const - { - return m_showColumn.find(source_column) != m_showColumn.end(); - } + //bool AssetBrowserTableFilterModel::filterAcceptsColumn(int source_column, const QModelIndex&) const + //{ + // return m_showColumn.find(source_column) != m_showColumn.end(); + //} - bool AssetBrowserTableFilterModel::lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const - { - if (source_left.column() == source_right.column()) - { - QVariant leftData = sourceModel()->data(source_left, AssetBrowserModel::Roles::EntryRole); - QVariant rightData = sourceModel()->data(source_right, AssetBrowserModel::Roles::EntryRole); - if (leftData.canConvert() && rightData.canConvert()) - { - auto leftEntry = qvariant_cast(leftData); - auto rightEntry = qvariant_cast(rightData); + //bool AssetBrowserTableFilterModel::lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const + //{ + // if (source_left.column() == source_right.column()) + // { + // QVariant leftData = sourceModel()->data(source_left, AssetBrowserModel::Roles::EntryRole); + // QVariant rightData = sourceModel()->data(source_right, AssetBrowserModel::Roles::EntryRole); + // if (leftData.canConvert() && rightData.canConvert()) + // { + // auto leftEntry = qvariant_cast(leftData); + // auto rightEntry = qvariant_cast(rightData); - // folders should always come first - if (azrtti_istypeof(leftEntry) && - azrtti_istypeof(rightEntry)) - { - return false; - } - if (azrtti_istypeof(leftEntry) && - azrtti_istypeof(rightEntry)) - { - return true; - } + // // folders should always come first + // if (azrtti_istypeof(leftEntry) && + // azrtti_istypeof(rightEntry)) + // { + // return false; + // } + // if (azrtti_istypeof(leftEntry) && + // azrtti_istypeof(rightEntry)) + // { + // return true; + // } - // if both entries are of same type, sort alphabetically - return m_collator.compare(leftEntry->GetDisplayName(), rightEntry->GetDisplayName()) > 0; - } - } - return QSortFilterProxyModel::lessThan(source_left, source_right); - } + // // if both entries are of same type, sort alphabetically + // return m_collator.compare(leftEntry->GetDisplayName(), rightEntry->GetDisplayName()) > 0; + // } + // } + // return QSortFilterProxyModel::lessThan(source_left, source_right); + //} - void AssetBrowserTableFilterModel::filterUpdatedSlot() - { - if (!m_alreadyRecomputingFilters) - { - m_alreadyRecomputingFilters = true; - // de-bounce it, since we may get many filter updates all at once. - QTimer::singleShot(0, this, [this]() { - m_alreadyRecomputingFilters = false; - FilterUpdatedSlotImmediate(); - }); - } - } + //void AssetBrowserTableFilterModel::filterUpdatedSlot() + //{ + // if (!m_alreadyRecomputingFilters) + // { + // m_alreadyRecomputingFilters = true; + // // de-bounce it, since we may get many filter updates all at once. + // QTimer::singleShot(0, this, [this]() { + // m_alreadyRecomputingFilters = false; + // FilterUpdatedSlotImmediate(); + // }); + // } + //} } // namespace AssetBrowser } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h index 8ffd1a469e..34cf8432ff 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h @@ -7,6 +7,8 @@ #include #include #include +//#include +#include AZ_PUSH_DISABLE_WARNING( 4251, "-Wunknown-warning-option") // 4251: class '...' needs to have dll-interface to be used by clients of class '...' @@ -19,6 +21,9 @@ namespace AzToolsFramework { namespace AssetBrowser { + class AssetBrowserFilterModel; + + class AssetBrowserTableModel : public QSortFilterProxyModel , public AssetBrowserComponentNotificationBus::Handler @@ -38,6 +43,7 @@ namespace AzToolsFramework // QSortFilterProxyModel QModelIndex mapToSource(const QModelIndex& proxyIndex) const override; QModelIndex mapFromSource(const QModelIndex& sourceIndex) const override; + bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override; QModelIndex parent(const QModelIndex& child) const override; QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; @@ -53,55 +59,56 @@ namespace AzToolsFramework AssetBrowserEntry* GetAssetEntry(QModelIndex index) const; int BuildMap(const QAbstractItemModel* model, const QModelIndex& parent = QModelIndex(), int row = 0); private: + QPointer m_filterModel; QMap m_indexMap; QMap m_rowMap; }; - class AssetBrowserTableFilterModel - : public QSortFilterProxyModel - , public AssetBrowserComponentNotificationBus::Handler - { - Q_OBJECT - public: - explicit AssetBrowserTableFilterModel(QObject* parent = nullptr); - ~AssetBrowserTableFilterModel(); + //class AssetBrowserTableFilterModel + // : public QSortFilterProxyModel + // , public AssetBrowserComponentNotificationBus::Handler + //{ + // Q_OBJECT + //public: + // explicit AssetBrowserTableFilterModel(QObject* parent = nullptr); + // ~AssetBrowserTableFilterModel(); - void setSourceModel(QAbstractItemModel* sourceModel) override; - // asset type filtering - void SetFilter(FilterConstType filter); - void FilterUpdatedSlotImmediate(); + // void setSourceModel(QAbstractItemModel* sourceModel) override; + // // asset type filtering + // void SetFilter(FilterConstType filter); + // void FilterUpdatedSlotImmediate(); - ////////////////////////////////////////////////////////////////////////// - // AssetBrowserComponentNotificationBus - ////////////////////////////////////////////////////////////////////////// - void OnAssetBrowserComponentReady() override; + // ////////////////////////////////////////////////////////////////////////// + // // AssetBrowserComponentNotificationBus + // ////////////////////////////////////////////////////////////////////////// + // void OnAssetBrowserComponentReady() override; - Q_SIGNALS: - void filterChanged(); - void entriesUpdated(); + //Q_SIGNALS: + // void filterChanged(); + // void entriesUpdated(); - ////////////////////////////////////////////////////////////////////////// - // QSortFilterProxyModel - protected: - bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override; - bool filterAcceptsColumn(int source_column, const QModelIndex& /*source_parent*/) const override; - bool lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const override; - ////////////////////////////////////////////////////////////////////////// + // ////////////////////////////////////////////////////////////////////////// + // // QSortFilterProxyModel + //protected: + // bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override; + // bool filterAcceptsColumn(int source_column, const QModelIndex& /*source_parent*/) const override; + // bool lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const override; + // ////////////////////////////////////////////////////////////////////////// - public Q_SLOTS: - void filterUpdatedSlot(); + //public Q_SLOTS: + // void filterUpdatedSlot(); - private: - AZStd::fixed_unordered_set(AssetBrowserEntry::Column::Count)> m_showColumn; - bool m_alreadyRecomputingFilters = false; - // asset source name match filter - FilterConstType m_filter; - AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // 4251: class '...' needs to have dll-interface to be used by clients of class '...' - QWeakPointer m_stringFilter; - QWeakPointer m_assetTypeFilter; - QCollator m_collator; // cache the collator as its somewhat expensive to constantly create and destroy one. - AZ_POP_DISABLE_WARNING - bool m_invalidateFilter = false; - }; + //private: + // AZStd::fixed_unordered_set(AssetBrowserEntry::Column::Count)> m_showColumn; + // bool m_alreadyRecomputingFilters = false; + // // asset source name match filter + // FilterConstType m_filter; + // AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // 4251: class '...' needs to have dll-interface to be used by clients of class '...' + // QWeakPointer m_stringFilter; + // QWeakPointer m_assetTypeFilter; + // QCollator m_collator; // cache the collator as its somewhat expensive to constantly create and destroy one. + // AZ_POP_DISABLE_WARNING + // bool m_invalidateFilter = false; + //}; } // namespace AssetBrowser } // namespace AzToolsFramework diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp index fb850f4f26..dd4b3b0cad 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp @@ -68,7 +68,7 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) , m_ui(new Ui::AzAssetBrowserWindowClass()) , m_filterModel(new AzToolsFramework::AssetBrowser::AssetBrowserFilterModel(parent)) , m_tableModel(new AzToolsFramework::AssetBrowser::AssetBrowserTableModel(parent)) - , m_tableFilterModel(new AzToolsFramework::AssetBrowser::AssetBrowserTableFilterModel(parent)) + /*, m_tableFilterModel(new AzToolsFramework::AssetBrowser::AssetBrowserTableFilterModel(parent))*/ { m_ui->setupUi(this); m_ui->m_searchWidget->Setup(true, true); @@ -83,8 +83,8 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) m_tableModel->setSourceModel(m_filterModel.data()); //m_tableModel->setSourceModel(m_assetBrowserModel); - m_tableFilterModel->setSourceModel(m_tableModel.data()); - m_tableFilterModel->SetFilter(m_ui->m_searchWidget->GetFilter()); + //m_tableFilterModel->setSourceModel(m_tableModel.data()); + //m_tableFilterModel->SetFilter(m_ui->m_searchWidget->GetFilter()); m_ui->m_assetBrowserTreeViewWidget->setModel(m_filterModel.data()); diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.h b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.h index a8a8474ef8..801af3e2a8 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.h +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.h @@ -56,7 +56,7 @@ private: QScopedPointer m_ui; QScopedPointer m_filterModel; QScopedPointer m_tableModel; - QScopedPointer m_tableFilterModel; + //QScopedPointer m_tableFilterModel; AzToolsFramework::AssetBrowser::AssetBrowserModel* m_assetBrowserModel; void UpdatePreview() const; From 1c990b2ef6b206c254e810d0301365c0a411ab88 Mon Sep 17 00:00:00 2001 From: igarri Date: Wed, 12 May 2021 11:03:02 +0100 Subject: [PATCH 005/116] Filter Sorting Working --- .../AssetBrowser/AssetBrowserFilterModel.cpp | 3 +- .../AssetBrowser/AssetBrowserFilterModel.h | 1 - .../AssetBrowser/AssetBrowserTableModel.cpp | 234 ++---------------- .../AssetBrowser/AssetBrowserTableModel.h | 60 +---- .../AzAssetBrowser/AzAssetBrowserWindow.cpp | 20 +- 5 files changed, 33 insertions(+), 285 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp index 5e9203cc29..34f8b97b5a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp @@ -32,7 +32,7 @@ namespace AzToolsFramework : QSortFilterProxyModel(parent) { m_showColumn.insert(static_cast(AssetBrowserEntry::Column::DisplayName)); - m_showColumn.insert(static_cast(AssetBrowserEntry::Column::Path)); + //m_showColumn.insert(static_cast(AssetBrowserEntry::Column::Path)); m_collator.setNumericMode(true); AssetBrowserComponentNotificationBus::Handler::BusConnect(); } @@ -63,7 +63,6 @@ namespace AzToolsFramework invalidateFilter(); m_invalidateFilter = false; } - Q_EMIT entriesUpdated(); } bool AssetBrowserFilterModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h index 3fff43859f..6cccc53eb6 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h @@ -53,7 +53,6 @@ namespace AzToolsFramework Q_SIGNALS: void filterChanged(); - void entriesUpdated(); ////////////////////////////////////////////////////////////////////////// //QSortFilterProxyModel diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp index b75d3e9400..ce9e97520a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp @@ -7,9 +7,7 @@ AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") #include #include -#include #include -#include AZ_POP_DISABLE_WARNING namespace AzToolsFramework { @@ -18,18 +16,7 @@ namespace AzToolsFramework AssetBrowserTableModel::AssetBrowserTableModel(QObject* parent /* = nullptr */) : QSortFilterProxyModel(parent) { - sort(0); setDynamicSortFilter(false); - setRecursiveFilteringEnabled(true); - AssetBrowserComponentNotificationBus::Handler::BusConnect(); - } - AssetBrowserTableModel::~AssetBrowserTableModel() - { - AssetBrowserComponentNotificationBus::Handler::BusDisconnect(); - } - void AssetBrowserTableModel::OnAssetBrowserComponentReady() - { - //BuildMap(sourceModel()); } void AssetBrowserTableModel::setSourceModel(QAbstractItemModel* sourceModel) { @@ -69,86 +56,68 @@ namespace AzToolsFramework // no filter present, every entry is not visible if (!m_filterModel->GetFilter()) { - return false; + return true; } return true; } QModelIndex AssetBrowserTableModel::index(int row, int column, const QModelIndex& parent) const { - /*AZ_UNUSED(row); - AZ_UNUSED(column);*/ return parent.isValid() ? QModelIndex() : createIndex(row, column, m_indexMap[row].internalPointer()); } QVariant AssetBrowserTableModel::data(const QModelIndex& index, int role) const { - //AZ_UNUSED(role); auto sourceIndex = mapToSource(index); if (!sourceIndex.isValid()) return QVariant(); - AssetBrowserEntry* entry = GetAssetEntry(sourceIndex); // static_cast(sourceIndex.internalPointer()); + AssetBrowserEntry* entry = GetAssetEntry(sourceIndex); if (entry == nullptr) { - AZ_Assert( - false, "ERROR - index internal pointer not pointing to an AssetEntry. Tree provided by the AssetBrowser invalid?"); + AZ_Assert(false, "ERROR - index internal pointer not pointing to an AssetEntry. Tree provided by the AssetBrowser invalid?"); return Qt::PartiallyChecked; } - return sourceIndex.data(role); // return entry->data(index.column()); - //return QVariant::fromValue(entry); - //AZ_UNUSED(role); - //if (index.isValid()) - //{ - // ////if (role == AssetBrowserModel::EntryRole) - // //{ - // QModelIndex modelIndex = mapFromSource(index); - // auto assetEntry = static_cast(index.internalPointer()); - // return QVariant::fromValue(assetEntry); - //} - //return QVariant(); // AzToolsFramework::AssetBrowser::AssetBrowserModel::data(index, role); - + return sourceIndex.data(role); } - int AssetBrowserTableModel::rowCount(const QModelIndex& parent) const { return !parent.isValid() ? m_rowMap.size() : 0; } + QVariant AssetBrowserTableModel::headerData(int section, Qt::Orientation orientation, int role) const + { + if (role == Qt::DisplayRole && orientation == Qt::Horizontal) + { + switch (section) + { + case static_cast(AssetBrowserEntry::Column::Name): + return QString("Name"); + case static_cast(AssetBrowserEntry::Column::Path): + return QString("Path"); + default: + return QString::number(section); + } + } + return QSortFilterProxyModel::headerData(section, orientation, role); // QVariant(); + } + int AssetBrowserTableModel::BuildMap(const QAbstractItemModel* model, const QModelIndex& parent, int row) { - //int rows = model ? model->rowCount(parent) : 0; - //for (int i = 0; i < rows; ++i) - //{ - // auto index = model->index(i, 0, parent); - // //if (!model->hasChildren(index)) - // //{ - // beginInsertRows(parent, row, row); - // m_rowMap[index] = row; - // m_indexMap[row] = index; - // endInsertRows(); - // Q_EMIT dataChanged(parent, parent); - // row = row + 1; - // //} - // if (model->hasChildren(index)) - // { - // row = BuildMap(model, index, row); - // } - //} - //return row; int rows = model ? model->rowCount(parent) : 0; for (int i = 0; i < rows; ++i) { - auto index = model->index(i, 0, parent); + QModelIndex index = model->index(i, 0, parent); if (model->hasChildren(index) == false) { beginInsertRows(parent, row, row); m_rowMap[index] = row; m_indexMap[row] = index; endInsertRows(); - Q_EMIT dataChanged(parent, parent); + + Q_EMIT dataChanged(index, index); row = row + 1; } @@ -173,12 +142,12 @@ namespace AzToolsFramework } void AssetBrowserTableModel::UpdateMap() { + //Not properly clears the indexes. //m_indexMap.clear(); //m_rowMap.clear(); - + emit layoutAboutToBeChanged(); if (m_indexMap.size() > 0) { - //beginRemoveRows(m_indexMap.first().parent(), m_indexMap.first().row(), m_indexMap.last().row()); for (const auto& key : m_indexMap.keys()) { beginRemoveRows(m_indexMap[key], m_indexMap[key].row(), m_indexMap[key].row()); @@ -186,160 +155,11 @@ namespace AzToolsFramework m_indexMap.remove(key); endRemoveRows(); } - //endRemoveRows(); } BuildMap(sourceModel()); + sort(0); } - - //---------------------------------------AssetBrowserTableFilterModel-------------------------------------------- - //AssetBrowserTableFilterModel::AssetBrowserTableFilterModel(QObject* parent) - // : QSortFilterProxyModel(parent) - //{ - // m_showColumn.insert(static_cast(AssetBrowserEntry::Column::DisplayName)); - // m_showColumn.insert(static_cast(AssetBrowserEntry::Column::Path)); - // AssetBrowserComponentNotificationBus::Handler::BusConnect(); - //} - - //AssetBrowserTableFilterModel::~AssetBrowserTableFilterModel() - //{ - // AssetBrowserComponentNotificationBus::Handler::BusDisconnect(); - //} - - //void AssetBrowserTableFilterModel::setSourceModel(QAbstractItemModel* sourceModel) - //{ - // QSortFilterProxyModel::setSourceModel(sourceModel); - //} - - //void AssetBrowserTableFilterModel::SetFilter(FilterConstType filter) - //{ - // connect(filter.data(), &AssetBrowserEntryFilter::updatedSignal, this, &AssetBrowserTableFilterModel::filterUpdatedSlot); - // m_filter = filter; - // m_invalidateFilter = true; - // // asset browser entries are not guaranteed to have populated when the filter is set, delay filtering until they are - // bool isAssetBrowserComponentReady = false; - // AssetBrowserComponentRequestBus::BroadcastResult(isAssetBrowserComponentReady, &AssetBrowserComponentRequests::AreEntriesReady); - // if (isAssetBrowserComponentReady) - // { - // OnAssetBrowserComponentReady(); - // } - //} - - //void AssetBrowserTableFilterModel::FilterUpdatedSlotImmediate() - //{ - // auto compFilter = qobject_cast>(m_filter); - // if (compFilter) - // { - // auto& subFilters = compFilter->GetSubFilters(); - // auto it = AZStd::find_if(subFilters.begin(), subFilters.end(), [subFilters](FilterConstType filter) -> bool { - // auto assetTypeFilter = qobject_cast>(filter); - // return !assetTypeFilter.isNull(); - // }); - // if (it != subFilters.end()) - // { - // m_assetTypeFilter = qobject_cast>(*it); - // } - // it = AZStd::find_if(subFilters.begin(), subFilters.end(), [subFilters](FilterConstType filter) -> bool { - // auto stringFilter = qobject_cast>(filter); - // return !stringFilter.isNull(); - // }); - // if (it != subFilters.end()) - // { - // m_stringFilter = qobject_cast>(*it); - // } - // } - // invalidateFilter(); - // Q_EMIT filterChanged(); - //} - - //void AssetBrowserTableFilterModel::OnAssetBrowserComponentReady() - //{ - // if (m_invalidateFilter) - // { - // invalidateFilter(); - // m_invalidateFilter = false; - // } - // Q_EMIT entriesUpdated(); - //} - - //bool AssetBrowserTableFilterModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const - //{ - // AZ_UNUSED(source_row); - // AZ_UNUSED(source_parent); - // QModelIndex idx = sourceModel()->index(source_row, 0, source_parent); - // if (!idx.isValid()) - // { - // return false; - // } - // // no filter present, every entry is visible - // if (!m_filter) - // { - // return true; - // } - - // //// the entry is the internal pointer of the index - // //auto entry = static_cast(idx.internalPointer()); - - // //if (entry) - // //{ - // // // root should return true even if its not displayed in the treeview - // // if (entry && entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Root) - // // { - // // return true; - // // } - // // return m_filter->Match(entry); - // //} - // return true; - //} - - //bool AssetBrowserTableFilterModel::filterAcceptsColumn(int source_column, const QModelIndex&) const - //{ - // return m_showColumn.find(source_column) != m_showColumn.end(); - //} - - //bool AssetBrowserTableFilterModel::lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const - //{ - // if (source_left.column() == source_right.column()) - // { - // QVariant leftData = sourceModel()->data(source_left, AssetBrowserModel::Roles::EntryRole); - // QVariant rightData = sourceModel()->data(source_right, AssetBrowserModel::Roles::EntryRole); - // if (leftData.canConvert() && rightData.canConvert()) - // { - // auto leftEntry = qvariant_cast(leftData); - // auto rightEntry = qvariant_cast(rightData); - - // // folders should always come first - // if (azrtti_istypeof(leftEntry) && - // azrtti_istypeof(rightEntry)) - // { - // return false; - // } - // if (azrtti_istypeof(leftEntry) && - // azrtti_istypeof(rightEntry)) - // { - // return true; - // } - - // // if both entries are of same type, sort alphabetically - // return m_collator.compare(leftEntry->GetDisplayName(), rightEntry->GetDisplayName()) > 0; - // } - // } - // return QSortFilterProxyModel::lessThan(source_left, source_right); - //} - - //void AssetBrowserTableFilterModel::filterUpdatedSlot() - //{ - // if (!m_alreadyRecomputingFilters) - // { - // m_alreadyRecomputingFilters = true; - // // de-bounce it, since we may get many filter updates all at once. - // QTimer::singleShot(0, this, [this]() { - // m_alreadyRecomputingFilters = false; - // FilterUpdatedSlotImmediate(); - // }); - // } - //} - } // namespace AssetBrowser } // namespace AzToolsFramework #include "AssetBrowser/moc_AssetBrowserTableModel.cpp" diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h index 34cf8432ff..69b8ead7c5 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h @@ -1,9 +1,6 @@ #pragma once #if !defined(Q_MOC_RUN) -#include #include -#include - #include #include #include @@ -26,21 +23,15 @@ namespace AzToolsFramework class AssetBrowserTableModel : public QSortFilterProxyModel - , public AssetBrowserComponentNotificationBus::Handler { Q_OBJECT public: AZ_CLASS_ALLOCATOR(AssetBrowserTableModel, AZ::SystemAllocator, 0); explicit AssetBrowserTableModel(QObject* parent = nullptr); - ~AssetBrowserTableModel(); - //////////////////////////////////////////////////////////////////// - // AssetBrowserComponentNotificationBus - //////////////////////////////////////////////////////////////////// - void OnAssetBrowserComponentReady() override; - void setSourceModel(QAbstractItemModel* sourceModel) override; //////////////////////////////////////////////////////////////////// // QSortFilterProxyModel + void setSourceModel(QAbstractItemModel* sourceModel) override; QModelIndex mapToSource(const QModelIndex& proxyIndex) const override; QModelIndex mapFromSource(const QModelIndex& sourceIndex) const override; bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override; @@ -52,7 +43,7 @@ namespace AzToolsFramework void UpdateMap(); protected: int rowCount(const QModelIndex& parent = QModelIndex()) const override; - //QVariant headerData(int section, Qt::Orientation orientation, int role /* = Qt::DisplayRole */) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role /* = Qt::DisplayRole */) const override; //////////////////////////////////////////////////////////////////// private: @@ -63,52 +54,5 @@ namespace AzToolsFramework QMap m_indexMap; QMap m_rowMap; }; - - //class AssetBrowserTableFilterModel - // : public QSortFilterProxyModel - // , public AssetBrowserComponentNotificationBus::Handler - //{ - // Q_OBJECT - //public: - // explicit AssetBrowserTableFilterModel(QObject* parent = nullptr); - // ~AssetBrowserTableFilterModel(); - - // void setSourceModel(QAbstractItemModel* sourceModel) override; - // // asset type filtering - // void SetFilter(FilterConstType filter); - // void FilterUpdatedSlotImmediate(); - - // ////////////////////////////////////////////////////////////////////////// - // // AssetBrowserComponentNotificationBus - // ////////////////////////////////////////////////////////////////////////// - // void OnAssetBrowserComponentReady() override; - - //Q_SIGNALS: - // void filterChanged(); - // void entriesUpdated(); - - // ////////////////////////////////////////////////////////////////////////// - // // QSortFilterProxyModel - //protected: - // bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override; - // bool filterAcceptsColumn(int source_column, const QModelIndex& /*source_parent*/) const override; - // bool lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const override; - // ////////////////////////////////////////////////////////////////////////// - - //public Q_SLOTS: - // void filterUpdatedSlot(); - - //private: - // AZStd::fixed_unordered_set(AssetBrowserEntry::Column::Count)> m_showColumn; - // bool m_alreadyRecomputingFilters = false; - // // asset source name match filter - // FilterConstType m_filter; - // AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // 4251: class '...' needs to have dll-interface to be used by clients of class '...' - // QWeakPointer m_stringFilter; - // QWeakPointer m_assetTypeFilter; - // QCollator m_collator; // cache the collator as its somewhat expensive to constantly create and destroy one. - // AZ_POP_DISABLE_WARNING - // bool m_invalidateFilter = false; - //}; } // namespace AssetBrowser } // namespace AzToolsFramework diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp index dd4b3b0cad..554c62a251 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp @@ -68,7 +68,6 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) , m_ui(new Ui::AzAssetBrowserWindowClass()) , m_filterModel(new AzToolsFramework::AssetBrowser::AssetBrowserFilterModel(parent)) , m_tableModel(new AzToolsFramework::AssetBrowser::AssetBrowserTableModel(parent)) - /*, m_tableFilterModel(new AzToolsFramework::AssetBrowser::AssetBrowserTableFilterModel(parent))*/ { m_ui->setupUi(this); m_ui->m_searchWidget->Setup(true, true); @@ -81,21 +80,13 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) m_tableModel->setFilterRole(Qt::DisplayRole); m_tableModel->setSourceModel(m_filterModel.data()); - //m_tableModel->setSourceModel(m_assetBrowserModel); - - //m_tableFilterModel->setSourceModel(m_tableModel.data()); - //m_tableFilterModel->SetFilter(m_ui->m_searchWidget->GetFilter()); - m_ui->m_assetBrowserTreeViewWidget->setModel(m_filterModel.data()); m_ui->m_assetBrowserTreeViewWidget->hideColumn(static_cast(AssetBrowserEntry::Column::Path)); - //m_ui->m_assetBrowserTableViewWidget->setModel(m_tableFilterModel.data()); m_ui->m_assetBrowserTableViewWidget->setModel(m_tableModel.data()); m_ui->m_assetBrowserTableViewWidget->setVisible(false); - //connect(m_filterModel.data(), &AssetBrowserFilterModel::entriesUpdated, m_tableModel.data(), &AssetBrowserTableModel::UpdateMap); - connect(m_ui->m_searchWidget->GetFilter().data(), &AssetBrowserEntryFilter::updatedSignal, m_filterModel.data(), &AssetBrowserFilterModel::filterUpdatedSlot); connect(m_filterModel.data(), &AssetBrowserFilterModel::filterChanged, this, [this]() @@ -105,20 +96,15 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) m_ui->m_assetBrowserTreeViewWidget->UpdateAfterFilter(hasFilter, selectFirstFilteredIndex); }); - //connect( m_ui->m_searchWidget->GetFilter().data(), &AssetBrowserEntryFilter::updatedSignal, m_tableFilterModel.data(), - // &AssetBrowserTableFilterModel::filterUpdatedSlot); - //connect(m_tableFilterModel.data(), &AssetBrowserTableFilterModel::filterChanged, this, [this]() { - // const bool hasFilter = !m_ui->m_searchWidget->GetFilterString().isEmpty(); - // const bool selectFirstFilteredIndex = false; - // m_ui->m_assetBrowserTableViewWidget->UpdateAfterFilter(hasFilter, selectFirstFilteredIndex); - //}); - connect(m_filterModel.data(), &AssetBrowserFilterModel::filterChanged, m_tableModel.data(), &AssetBrowserTableModel::UpdateMap); connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::selectionChangedSignal, this, &AzAssetBrowserWindow::SelectionChangedSlot); connect(m_ui->m_assetBrowserTreeViewWidget, &QAbstractItemView::doubleClicked, this, &AzAssetBrowserWindow::DoubleClickedItem); + connect(m_ui->m_assetBrowserTableViewWidget, &QAbstractItemView::doubleClicked, this, &AzAssetBrowserWindow::DoubleClickedItem); + + connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::ClearStringFilter, m_ui->m_searchWidget, &SearchWidget::ClearStringFilter); connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::ClearTypeFilter, m_ui->m_searchWidget, &SearchWidget::ClearTypeFilter); From 80684b383b66b762dbc3e4537afb536c033a2caa Mon Sep 17 00:00:00 2001 From: igarri Date: Wed, 12 May 2021 11:42:39 +0100 Subject: [PATCH 006/116] Code cleanup --- .../AssetBrowser/AssetBrowserTableModel.cpp | 121 ++++++++---------- .../AssetBrowser/AssetBrowserTableModel.h | 22 +--- .../AzAssetBrowser/AzAssetBrowserWindow.cpp | 2 +- 3 files changed, 61 insertions(+), 84 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp index ce9e97520a..724e7a54d9 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp @@ -1,14 +1,8 @@ -#include -#include -#include -#include -AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") #include #include +#include -#include -AZ_POP_DISABLE_WARNING namespace AzToolsFramework { namespace AssetBrowser @@ -34,11 +28,6 @@ namespace AzToolsFramework } return m_indexMap[proxyIndex.row()]; } - QModelIndex AssetBrowserTableModel::parent(const QModelIndex& child) const - { - AZ_UNUSED(child); - return QModelIndex(); - } QModelIndex AssetBrowserTableModel::mapFromSource(const QModelIndex& sourceIndex) const { Q_ASSERT(!sourceIndex.isValid() || sourceIndex.model() == sourceModel()); @@ -49,44 +38,6 @@ namespace AzToolsFramework return createIndex(m_rowMap[sourceIndex], sourceIndex.column(), sourceIndex.internalPointer()); } - bool AssetBrowserTableModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const - { - AZ_UNUSED(source_row); - AZ_UNUSED(source_parent); - // no filter present, every entry is not visible - if (!m_filterModel->GetFilter()) - { - return true; - } - return true; - } - - QModelIndex AssetBrowserTableModel::index(int row, int column, const QModelIndex& parent) const - { - return parent.isValid() ? QModelIndex() : createIndex(row, column, m_indexMap[row].internalPointer()); - } - - QVariant AssetBrowserTableModel::data(const QModelIndex& index, int role) const - { - auto sourceIndex = mapToSource(index); - if (!sourceIndex.isValid()) - return QVariant(); - - AssetBrowserEntry* entry = GetAssetEntry(sourceIndex); - if (entry == nullptr) - { - AZ_Assert(false, "ERROR - index internal pointer not pointing to an AssetEntry. Tree provided by the AssetBrowser invalid?"); - return Qt::PartiallyChecked; - } - - return sourceIndex.data(role); - } - - int AssetBrowserTableModel::rowCount(const QModelIndex& parent) const - { - return !parent.isValid() ? m_rowMap.size() : 0; - } - QVariant AssetBrowserTableModel::headerData(int section, Qt::Orientation orientation, int role) const { if (role == Qt::DisplayRole && orientation == Qt::Horizontal) @@ -104,7 +55,50 @@ namespace AzToolsFramework return QSortFilterProxyModel::headerData(section, orientation, role); // QVariant(); } - int AssetBrowserTableModel::BuildMap(const QAbstractItemModel* model, const QModelIndex& parent, int row) + QVariant AssetBrowserTableModel::data(const QModelIndex& index, int role) const + { + auto sourceIndex = mapToSource(index); + if (!sourceIndex.isValid()) + return QVariant(); + + AssetBrowserEntry* entry = GetAssetEntry(sourceIndex); + if (entry == nullptr) + { + AZ_Assert(false, "ERROR - index internal pointer not pointing to an AssetEntry. Tree provided by the AssetBrowser invalid?"); + return Qt::PartiallyChecked; + } + + return sourceIndex.data(role); + } + + QModelIndex AssetBrowserTableModel::index(int row, int column, const QModelIndex& parent) const + { + return parent.isValid() ? QModelIndex() : createIndex(row, column, m_indexMap[row].internalPointer()); + } + + QModelIndex AssetBrowserTableModel::parent(const QModelIndex& child) const + { + AZ_UNUSED(child); + return QModelIndex(); + } + bool AssetBrowserTableModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const + { + AZ_UNUSED(source_row); + AZ_UNUSED(source_parent); + // no filter present, every entry is not visible + if (!m_filterModel->GetFilter()) + { + return true; + } + return true; + } + + int AssetBrowserTableModel::rowCount(const QModelIndex& parent) const + { + return !parent.isValid() ? m_rowMap.size() : 0; + } + + int AssetBrowserTableModel::BuildTableModelMap(const QAbstractItemModel* model, const QModelIndex& parent /*= QModelIndex()*/, int row /*= 0*/) { int rows = model ? model->rowCount(parent) : 0; for (int i = 0; i < rows; ++i) @@ -123,7 +117,7 @@ namespace AzToolsFramework if (model->hasChildren(index)) { - row = BuildMap(model, index, row); + row = BuildTableModelMap(model, index, row); } } return row; @@ -140,25 +134,18 @@ namespace AzToolsFramework return nullptr; } } - void AssetBrowserTableModel::UpdateMap() - { - //Not properly clears the indexes. - //m_indexMap.clear(); - //m_rowMap.clear(); + void AssetBrowserTableModel::UpdateTableModelMaps() +{ emit layoutAboutToBeChanged(); if (m_indexMap.size() > 0) { - for (const auto& key : m_indexMap.keys()) - { - beginRemoveRows(m_indexMap[key], m_indexMap[key].row(), m_indexMap[key].row()); - m_rowMap.remove(m_indexMap[key]); - m_indexMap.remove(key); - endRemoveRows(); - } + beginRemoveRows(m_indexMap.first(), m_indexMap.first().row(), m_indexMap.last().row()); + m_rowMap.clear(); + m_indexMap.clear(); + endRemoveRows(); } - - BuildMap(sourceModel()); - sort(0); + BuildTableModelMap(sourceModel()); + emit layoutChanged(); } } // namespace AssetBrowser } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h index 69b8ead7c5..51976c3482 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h @@ -1,25 +1,16 @@ #pragma once #if !defined(Q_MOC_RUN) -#include #include -#include -#include -//#include -#include - -AZ_PUSH_DISABLE_WARNING( - 4251, "-Wunknown-warning-option") // 4251: class '...' needs to have dll-interface to be used by clients of class '...' -#include -#include #include +#include #endif -AZ_POP_DISABLE_WARNING + namespace AzToolsFramework { namespace AssetBrowser { class AssetBrowserFilterModel; - + class AssetBrowserEntry; class AssetBrowserTableModel : public QSortFilterProxyModel @@ -34,21 +25,20 @@ namespace AzToolsFramework void setSourceModel(QAbstractItemModel* sourceModel) override; QModelIndex mapToSource(const QModelIndex& proxyIndex) const override; QModelIndex mapFromSource(const QModelIndex& sourceIndex) const override; - bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override; QModelIndex parent(const QModelIndex& child) const override; QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - public Q_SLOTS: - void UpdateMap(); + void UpdateTableModelMaps(); protected: + bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override; int rowCount(const QModelIndex& parent = QModelIndex()) const override; QVariant headerData(int section, Qt::Orientation orientation, int role /* = Qt::DisplayRole */) const override; //////////////////////////////////////////////////////////////////// private: AssetBrowserEntry* GetAssetEntry(QModelIndex index) const; - int BuildMap(const QAbstractItemModel* model, const QModelIndex& parent = QModelIndex(), int row = 0); + int BuildTableModelMap(const QAbstractItemModel* model, const QModelIndex& parent = QModelIndex(), int row = 0); private: QPointer m_filterModel; QMap m_indexMap; diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp index 554c62a251..f415e0a135 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp @@ -96,7 +96,7 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) m_ui->m_assetBrowserTreeViewWidget->UpdateAfterFilter(hasFilter, selectFirstFilteredIndex); }); - connect(m_filterModel.data(), &AssetBrowserFilterModel::filterChanged, m_tableModel.data(), &AssetBrowserTableModel::UpdateMap); + connect(m_filterModel.data(), &AssetBrowserFilterModel::filterChanged, m_tableModel.data(), &AssetBrowserTableModel::UpdateTableModelMaps); connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::selectionChangedSignal, this, &AzAssetBrowserWindow::SelectionChangedSlot); From c1e21185b43e7892973dc1055ae19d1b9099b5e1 Mon Sep 17 00:00:00 2001 From: igarri Date: Wed, 12 May 2021 12:20:23 +0100 Subject: [PATCH 007/116] Selecting correct indexes from Asset Browser Model --- .../Views/AssetBrowserTableView.cpp | 22 +++++------ .../Views/AssetBrowserTableView.h | 7 +--- .../AzAssetBrowser/AzAssetBrowserWindow.cpp | 39 ++++++++++++++++++- .../AzAssetBrowser/AzAssetBrowserWindow.h | 2 +- 4 files changed, 52 insertions(+), 18 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp index aa35d99894..0a6aeed374 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp @@ -47,7 +47,7 @@ namespace AzToolsFramework setMouseTracking(true); connect(this, &QTableView::customContextMenuRequested, this, &AssetBrowserTableView::OnContextMenu); - connect(m_scTimer, &QTimer::timeout, this, &AssetBrowserTableView::OnUpdateSCThumbnailsList); + //connect(m_scTimer, &QTimer::timeout, this, &AssetBrowserTableView::OnUpdateSCThumbnailsList); AssetBrowserViewRequestBus::Handler::BusConnect(); AssetBrowserComponentNotificationBus::Handler::BusConnect(); @@ -59,9 +59,9 @@ namespace AzToolsFramework } void AssetBrowserTableView::setModel(QAbstractItemModel* model) { - m_filterModel = qobject_cast(model); - AZ_Assert(m_filterModel, "Expecting AssetBrowserTableModel"); - m_sourceModel = qobject_cast(m_filterModel->sourceModel()); + m_tableModel = qobject_cast(model); + AZ_Assert(m_tableModel, "Expecting AssetBrowserTableModel"); + m_sourceFilterModel = qobject_cast(m_tableModel->sourceModel()); QTableView::setModel(model); } void AssetBrowserTableView::SetName(const QString& name) @@ -76,14 +76,14 @@ namespace AzToolsFramework } AZStd::vector AssetBrowserTableView::GetSelectedAssets() const { - QModelIndexList sourceIndexes{}; - //for (const auto& index : selectedIndexes()) - //{ - // sourceIndexes.push_back(m_sourceModel->mapToSource(index)); - //} + QModelIndexList sourceIndexes; + for (const auto& index : selectedIndexes()) + { + sourceIndexes.push_back(m_sourceFilterModel->mapToSource(m_tableModel->mapToSource(index))); + } AZStd::vector entries; - //AssetBrowserModel::SourceIndexesToAssetDatabaseEntries(sourceIndexes, entries); + AssetBrowserModel::SourceIndexesToAssetDatabaseEntries(sourceIndexes, entries); return entries; } void AssetBrowserTableView::selectionChanged(const QItemSelection& selected, const QItemSelection& deselected) @@ -124,7 +124,7 @@ namespace AzToolsFramework { emit ClearStringFilter(); emit ClearTypeFilter(); - m_sourceModel->FilterUpdatedSlotImmediate(); + m_sourceFilterModel->FilterUpdatedSlotImmediate(); } void AssetBrowserTableView::Update() diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h index aef7353334..d1bab70104 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h @@ -63,13 +63,10 @@ namespace AzToolsFramework private: QString m_name; - QPointer m_filterModel = nullptr; - QPointer m_sourceModel = nullptr; + QPointer m_tableModel = nullptr; + QPointer m_sourceFilterModel = nullptr; EntryDelegate* m_delegate = nullptr; - QTimer* m_scTimer = nullptr; - const int m_scUpdateInterval = 100; - private Q_SLOTS: void OnContextMenu(const QPoint& point); //! Get all visible source entries and place them in a queue to update their source control status diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp index f415e0a135..b59190d9a9 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp @@ -102,7 +102,7 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) this, &AzAssetBrowserWindow::SelectionChangedSlot); connect(m_ui->m_assetBrowserTreeViewWidget, &QAbstractItemView::doubleClicked, this, &AzAssetBrowserWindow::DoubleClickedItem); - connect(m_ui->m_assetBrowserTableViewWidget, &QAbstractItemView::doubleClicked, this, &AzAssetBrowserWindow::DoubleClickedItem); + connect(m_ui->m_assetBrowserTableViewWidget, &QAbstractItemView::doubleClicked, this, &AzAssetBrowserWindow::DoubleClickedItemTableModel); connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::ClearStringFilter, m_ui->m_searchWidget, &SearchWidget::ClearStringFilter); @@ -242,6 +242,43 @@ void AzAssetBrowserWindow::DoubleClickedItem([[maybe_unused]] const QModelIndex& } +void AzAssetBrowserWindow::DoubleClickedItemTableModel([[maybe_unused]] const QModelIndex& element) +{ + using namespace AzToolsFramework; + using namespace AzToolsFramework::AssetBrowser; + // assumption: Double clicking an item selects it before telling us we double clicked it. + auto selectedAssets = m_ui->m_assetBrowserTableViewWidget->GetSelectedAssets(); + for (const AssetBrowserEntry* entry : selectedAssets) + { + AZ::Data::AssetId assetIdToOpen; + AZStd::string fullFilePath; + + if (const ProductAssetBrowserEntry* productEntry = azrtti_cast(entry)) + { + assetIdToOpen = productEntry->GetAssetId(); + fullFilePath = entry->GetFullPath(); + } + else if (const SourceAssetBrowserEntry* sourceEntry = azrtti_cast(entry)) + { + // manufacture an empty AssetID with the source's UUID + assetIdToOpen = AZ::Data::AssetId(sourceEntry->GetSourceUuid(), 0); + fullFilePath = entry->GetFullPath(); + } + + bool handledBySomeone = false; + if (assetIdToOpen.IsValid()) + { + AssetBrowserInteractionNotificationBus::Broadcast( + &AssetBrowserInteractionNotifications::OpenAssetInAssociatedEditor, assetIdToOpen, handledBySomeone); + } + + if (!handledBySomeone && !fullFilePath.empty()) + { + AzAssetBrowserRequestHandler::OpenWithOS(fullFilePath); + } + } +} + void AzAssetBrowserWindow::SwitchDisplayView(const int state) { m_ui->m_assetBrowserTableViewWidget->setVisible(state); diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.h b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.h index 801af3e2a8..86d81ad873 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.h +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.h @@ -56,7 +56,6 @@ private: QScopedPointer m_ui; QScopedPointer m_filterModel; QScopedPointer m_tableModel; - //QScopedPointer m_tableFilterModel; AzToolsFramework::AssetBrowser::AssetBrowserModel* m_assetBrowserModel; void UpdatePreview() const; @@ -64,6 +63,7 @@ private: private Q_SLOTS: void SelectionChangedSlot(const QItemSelection& selected, const QItemSelection& deselected) const; void DoubleClickedItem(const QModelIndex& element); + void DoubleClickedItemTableModel(const QModelIndex& element); void SwitchDisplayView(const int state); }; From d6868df735033804d51c52949bfcc87d1d6cbeb6 Mon Sep 17 00:00:00 2001 From: igarri Date: Thu, 13 May 2021 12:29:16 +0100 Subject: [PATCH 008/116] Expanding TableView Columns --- .../AssetBrowser/AssetBrowserFilterModel.cpp | 2 +- .../AssetBrowser/AssetBrowserTableModel.cpp | 1 - .../AssetBrowser/Views/AssetBrowserTableView.cpp | 15 ++++----------- .../AssetBrowser/Views/AssetBrowserTableView.h | 5 ----- 4 files changed, 5 insertions(+), 18 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp index 34f8b97b5a..ee3aa04e27 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp @@ -32,7 +32,7 @@ namespace AzToolsFramework : QSortFilterProxyModel(parent) { m_showColumn.insert(static_cast(AssetBrowserEntry::Column::DisplayName)); - //m_showColumn.insert(static_cast(AssetBrowserEntry::Column::Path)); + m_showColumn.insert(static_cast(AssetBrowserEntry::Column::Path)); m_collator.setNumericMode(true); AssetBrowserComponentNotificationBus::Handler::BusConnect(); } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp index 724e7a54d9..13b298cdec 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp @@ -1,4 +1,3 @@ - #include #include #include diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp index 0a6aeed374..40e0b9db5e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp @@ -1,7 +1,5 @@ #include -#include -#include #include #include @@ -14,8 +12,6 @@ #include #include #include -#include -#include AZ_PUSH_DISABLE_WARNING( 4244 4251 4800, "-Wunknown-warning-option") // conversion from 'int' to 'float', possible loss of data, needs to have dll-interface to @@ -37,17 +33,16 @@ namespace AzToolsFramework AssetBrowserTableView::AssetBrowserTableView(QWidget* parent) : QTableView(parent) , m_delegate(new EntryDelegate(this)) - { setSortingEnabled(true); setItemDelegate(m_delegate); - //header()->hide(); + verticalHeader()->hide(); setContextMenuPolicy(Qt::CustomContextMenu); setMouseTracking(true); + setSortingEnabled(false); connect(this, &QTableView::customContextMenuRequested, this, &AssetBrowserTableView::OnContextMenu); - //connect(m_scTimer, &QTimer::timeout, this, &AssetBrowserTableView::OnUpdateSCThumbnailsList); AssetBrowserViewRequestBus::Handler::BusConnect(); AssetBrowserComponentNotificationBus::Handler::BusConnect(); @@ -63,6 +58,8 @@ namespace AzToolsFramework AZ_Assert(m_tableModel, "Expecting AssetBrowserTableModel"); m_sourceFilterModel = qobject_cast(m_tableModel->sourceModel()); QTableView::setModel(model); + horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeMode::Stretch); + horizontalHeader()->setSectionResizeMode(1,QHeaderView::ResizeMode::Stretch); } void AssetBrowserTableView::SetName(const QString& name) { @@ -105,10 +102,6 @@ namespace AzToolsFramework } } QTableView::rowsAboutToBeRemoved(parent, start, end); - } - void AssetBrowserTableView::OnUpdateSCThumbnailsList() - { - } void AssetBrowserTableView::SelectProduct(AZ::Data::AssetId assetID) { diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h index d1bab70104..531e962297 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h @@ -58,9 +58,6 @@ namespace AzToolsFramework void selectionChanged(const QItemSelection& selected, const QItemSelection& deselected) override; void rowsAboutToBeRemoved(const QModelIndex& parent, int start, int end) override; - //! Get all visible source entries and place them in a queue to update their source control status - //void OnUpdateSCThumbnailsList(); - private: QString m_name; QPointer m_tableModel = nullptr; @@ -69,8 +66,6 @@ namespace AzToolsFramework private Q_SLOTS: void OnContextMenu(const QPoint& point); - //! Get all visible source entries and place them in a queue to update their source control status - void OnUpdateSCThumbnailsList(); }; } // namespace AssetBrowser } // namespace AzToolsFramework From d7ca3f273bb656f0b162eeeede07ba87cafca22f Mon Sep 17 00:00:00 2001 From: igarri Date: Thu, 13 May 2021 13:25:03 +0100 Subject: [PATCH 009/116] croll to top on view when the filter updates --- .../AssetBrowser/AssetBrowserTableModel.cpp | 1 + .../AssetBrowser/Views/AssetBrowserTableView.cpp | 9 +++++++++ .../AssetBrowser/Views/AssetBrowserTableView.h | 1 + 3 files changed, 11 insertions(+) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp index 13b298cdec..7991eb35d8 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp @@ -145,6 +145,7 @@ namespace AzToolsFramework } BuildTableModelMap(sourceModel()); emit layoutChanged(); + } } // namespace AssetBrowser } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp index 40e0b9db5e..83a0f2ce9f 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp @@ -58,6 +58,8 @@ namespace AzToolsFramework AZ_Assert(m_tableModel, "Expecting AssetBrowserTableModel"); m_sourceFilterModel = qobject_cast(m_tableModel->sourceModel()); QTableView::setModel(model); + connect(m_tableModel, &AssetBrowserTableModel::layoutChanged, this, &AssetBrowserTableView::layoutChangedSlot); + horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeMode::Stretch); horizontalHeader()->setSectionResizeMode(1,QHeaderView::ResizeMode::Stretch); } @@ -103,6 +105,13 @@ namespace AzToolsFramework } QTableView::rowsAboutToBeRemoved(parent, start, end); } + void AssetBrowserTableView::layoutChangedSlot(const QList& parents, QAbstractItemModel::LayoutChangeHint hint) + { + AZ_UNUSED(parents); + AZ_UNUSED(hint); + + scrollToTop(); + } void AssetBrowserTableView::SelectProduct(AZ::Data::AssetId assetID) { AZ_UNUSED(assetID); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h index 531e962297..b39d48c391 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h @@ -57,6 +57,7 @@ namespace AzToolsFramework protected Q_SLOTS: void selectionChanged(const QItemSelection& selected, const QItemSelection& deselected) override; void rowsAboutToBeRemoved(const QModelIndex& parent, int start, int end) override; + void layoutChangedSlot(const QList &parents = QList(), QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint); private: QString m_name; From 33240c9f90fad3cf4c4e30ef1fcda909a0acad7b Mon Sep 17 00:00:00 2001 From: igarri Date: Thu, 13 May 2021 16:08:14 +0100 Subject: [PATCH 010/116] Selecting assets from tableview --- .../AssetBrowser/AssetBrowserTableModel.cpp | 13 +------------ .../AssetBrowser/AssetBrowserTableModel.h | 2 -- .../AssetBrowser/Views/AssetBrowserTableView.cpp | 12 ++++++++---- .../AssetBrowser/Views/AssetBrowserTreeView.cpp | 5 ++++- 4 files changed, 13 insertions(+), 19 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp index 7991eb35d8..bebdf44c9a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp @@ -27,15 +27,6 @@ namespace AzToolsFramework } return m_indexMap[proxyIndex.row()]; } - QModelIndex AssetBrowserTableModel::mapFromSource(const QModelIndex& sourceIndex) const - { - Q_ASSERT(!sourceIndex.isValid() || sourceIndex.model() == sourceModel()); - if (!sourceIndex.isValid()) - { - return QModelIndex(); - } - return createIndex(m_rowMap[sourceIndex], sourceIndex.column(), sourceIndex.internalPointer()); - } QVariant AssetBrowserTableModel::headerData(int section, Qt::Orientation orientation, int role) const { @@ -94,7 +85,7 @@ namespace AzToolsFramework int AssetBrowserTableModel::rowCount(const QModelIndex& parent) const { - return !parent.isValid() ? m_rowMap.size() : 0; + return !parent.isValid() ? m_indexMap.size() : 0; } int AssetBrowserTableModel::BuildTableModelMap(const QAbstractItemModel* model, const QModelIndex& parent /*= QModelIndex()*/, int row /*= 0*/) @@ -106,7 +97,6 @@ namespace AzToolsFramework if (model->hasChildren(index) == false) { beginInsertRows(parent, row, row); - m_rowMap[index] = row; m_indexMap[row] = index; endInsertRows(); @@ -139,7 +129,6 @@ namespace AzToolsFramework if (m_indexMap.size() > 0) { beginRemoveRows(m_indexMap.first(), m_indexMap.first().row(), m_indexMap.last().row()); - m_rowMap.clear(); m_indexMap.clear(); endRemoveRows(); } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h index 51976c3482..432300194b 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h @@ -24,7 +24,6 @@ namespace AzToolsFramework // QSortFilterProxyModel void setSourceModel(QAbstractItemModel* sourceModel) override; QModelIndex mapToSource(const QModelIndex& proxyIndex) const override; - QModelIndex mapFromSource(const QModelIndex& sourceIndex) const override; QModelIndex parent(const QModelIndex& child) const override; QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; @@ -42,7 +41,6 @@ namespace AzToolsFramework private: QPointer m_filterModel; QMap m_indexMap; - QMap m_rowMap; }; } // namespace AssetBrowser } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp index 83a0f2ce9f..cb4a989043 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp @@ -41,6 +41,7 @@ namespace AzToolsFramework setMouseTracking(true); setSortingEnabled(false); + setSelectionMode(QAbstractItemView::SingleSelection); connect(this, &QTableView::customContextMenuRequested, this, &AssetBrowserTableView::OnContextMenu); @@ -61,7 +62,7 @@ namespace AzToolsFramework connect(m_tableModel, &AssetBrowserTableModel::layoutChanged, this, &AssetBrowserTableView::layoutChangedSlot); horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeMode::Stretch); - horizontalHeader()->setSectionResizeMode(1,QHeaderView::ResizeMode::Stretch); + horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeMode::Stretch); } void AssetBrowserTableView::SetName(const QString& name) { @@ -78,7 +79,10 @@ namespace AzToolsFramework QModelIndexList sourceIndexes; for (const auto& index : selectedIndexes()) { - sourceIndexes.push_back(m_sourceFilterModel->mapToSource(m_tableModel->mapToSource(index))); + if (index.column() == 0) + { + sourceIndexes.push_back(m_sourceFilterModel->mapToSource(m_tableModel->mapToSource(index))); + } } AZStd::vector entries; @@ -87,8 +91,8 @@ namespace AzToolsFramework } void AssetBrowserTableView::selectionChanged(const QItemSelection& selected, const QItemSelection& deselected) { - AZ_UNUSED(selected); - AZ_UNUSED(deselected); + QTableView::selectionChanged(selected, deselected); + Q_EMIT selectionChangedSignal(selected, deselected); } void AssetBrowserTableView::rowsAboutToBeRemoved(const QModelIndex& parent, int start, int end) { diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.cpp index eeee433835..f2a5cc1a3a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.cpp @@ -101,7 +101,10 @@ namespace AzToolsFramework QModelIndexList sourceIndexes; for (const auto& index : selectedIndexes()) { - sourceIndexes.push_back(m_assetBrowserSortFilterProxyModel->mapToSource(index)); + if (index.column() == 0) + { + sourceIndexes.push_back(m_assetBrowserSortFilterProxyModel->mapToSource(index)); + } } AZStd::vector entries; From cff9fea535c91a08ce4d444c2a79823d53f2f75c Mon Sep 17 00:00:00 2001 From: igarri Date: Fri, 14 May 2021 13:09:14 +0100 Subject: [PATCH 011/116] Switching views with filters --- .../AssetBrowser/AssetBrowserFilterModel.cpp | 6 ++++++ .../AssetBrowser/AssetBrowserFilterModel.h | 2 +- .../AzToolsFramework/AssetBrowser/Search/Filter.cpp | 5 +++++ .../AzToolsFramework/AssetBrowser/Search/Filter.h | 2 +- .../AssetBrowser/Views/AssetBrowserTreeView.cpp | 2 ++ .../Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp | 9 +++++++-- .../Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.h | 2 +- 7 files changed, 23 insertions(+), 5 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp index ee3aa04e27..b4728633d3 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp @@ -130,6 +130,9 @@ namespace AzToolsFramework if (compFilter) { auto& subFilters = compFilter->GetSubFilters(); + //bool bNoFilters = false; + + auto it = AZStd::find_if(subFilters.begin(), subFilters.end(), [subFilters](FilterConstType filter) -> bool { auto assetTypeFilter = qobject_cast >(filter); @@ -147,8 +150,11 @@ namespace AzToolsFramework if (it != subFilters.end()) { m_stringFilter = qobject_cast >(*it); + emit switchFilterView(m_stringFilter.toStrongRef()->IsEmpty()); } } + + invalidateFilter(); Q_EMIT filterChanged(); } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h index 6cccc53eb6..71689354d1 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h @@ -52,8 +52,8 @@ namespace AzToolsFramework void OnAssetBrowserComponentReady() override; Q_SIGNALS: + void switchFilterView(int); void filterChanged(); - ////////////////////////////////////////////////////////////////////////// //QSortFilterProxyModel protected: diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.cpp index ceda5f8e19..86315613ad 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.cpp @@ -233,6 +233,11 @@ namespace AzToolsFramework Q_EMIT updatedSignal(); } + bool StringFilter::IsEmpty() const + { + return m_filterString.isEmpty(); + } + QString StringFilter::GetNameInternal() const { return m_filterString; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.h index b67b699862..6d19fb3b47 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.h @@ -110,7 +110,7 @@ namespace AzToolsFramework ~StringFilter() override = default; void SetFilterString(const QString& filterString); - + bool IsEmpty() const; protected: QString GetNameInternal() const override; bool MatchInternal(const AssetBrowserEntry* entry) const override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.cpp index f2a5cc1a3a..e29607698d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.cpp @@ -52,6 +52,7 @@ namespace AzToolsFramework setSortingEnabled(true); setItemDelegate(m_delegate); header()->hide(); + setContextMenuPolicy(Qt::CustomContextMenu); setMouseTracking(true); @@ -174,6 +175,7 @@ namespace AzToolsFramework void AssetBrowserTreeView::OnAssetBrowserComponentReady() { + hideColumn(static_cast(AssetBrowserEntry::Column::Path)); if (!m_name.isEmpty()) { auto crc = AZ::Crc32(m_name.toUtf8().data()); diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp index b59190d9a9..d1bbbb1f9d 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp @@ -82,7 +82,7 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) m_tableModel->setSourceModel(m_filterModel.data()); m_ui->m_assetBrowserTreeViewWidget->setModel(m_filterModel.data()); - m_ui->m_assetBrowserTreeViewWidget->hideColumn(static_cast(AssetBrowserEntry::Column::Path)); + //m_ui->m_assetBrowserTreeViewWidget->hideColumn(static_cast(AssetBrowserEntry::Column::Path)); m_ui->m_assetBrowserTableViewWidget->setModel(m_tableModel.data()); m_ui->m_assetBrowserTableViewWidget->setVisible(false); @@ -97,9 +97,14 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) }); connect(m_filterModel.data(), &AssetBrowserFilterModel::filterChanged, m_tableModel.data(), &AssetBrowserTableModel::UpdateTableModelMaps); + connect(m_filterModel.data(), &AssetBrowserFilterModel::switchFilterView, this, &AzAssetBrowserWindow::SwitchDisplayView); connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::selectionChangedSignal, this, &AzAssetBrowserWindow::SelectionChangedSlot); + + connect(m_ui->m_assetBrowserTableViewWidget, &AssetBrowserTableView::selectionChangedSignal, + this, &AzAssetBrowserWindow::SelectionChangedSlot); + connect(m_ui->m_assetBrowserTreeViewWidget, &QAbstractItemView::doubleClicked, this, &AzAssetBrowserWindow::DoubleClickedItem); connect(m_ui->m_assetBrowserTableViewWidget, &QAbstractItemView::doubleClicked, this, &AzAssetBrowserWindow::DoubleClickedItemTableModel); @@ -279,7 +284,7 @@ void AzAssetBrowserWindow::DoubleClickedItemTableModel([[maybe_unused]] const QM } } -void AzAssetBrowserWindow::SwitchDisplayView(const int state) +void AzAssetBrowserWindow::SwitchDisplayView(bool state) { m_ui->m_assetBrowserTableViewWidget->setVisible(state); m_ui->m_assetBrowserTreeViewWidget->setVisible(!state); diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.h b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.h index 86d81ad873..8c32a913ba 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.h +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.h @@ -64,7 +64,7 @@ private Q_SLOTS: void SelectionChangedSlot(const QItemSelection& selected, const QItemSelection& deselected) const; void DoubleClickedItem(const QModelIndex& element); void DoubleClickedItemTableModel(const QModelIndex& element); - void SwitchDisplayView(const int state); + void SwitchDisplayView(bool state); }; extern const char* AZ_ASSET_BROWSER_PREVIEW_NAME; From b9c9811d3566a008feb330ef79d82b501bcd2ac3 Mon Sep 17 00:00:00 2001 From: igarri Date: Mon, 17 May 2021 14:06:01 +0100 Subject: [PATCH 012/116] Fixing qobject_cast to the StringFilter --- .../AssetBrowser/AssetBrowserFilterModel.cpp | 33 ++++++++++++++----- .../AssetBrowser/AssetBrowserFilterModel.h | 2 +- .../AzAssetBrowser/AzAssetBrowserWindow.cpp | 2 +- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp index b4728633d3..9ee00a96ae 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp @@ -130,9 +130,7 @@ namespace AzToolsFramework if (compFilter) { auto& subFilters = compFilter->GetSubFilters(); - //bool bNoFilters = false; - auto it = AZStd::find_if(subFilters.begin(), subFilters.end(), [subFilters](FilterConstType filter) -> bool { auto assetTypeFilter = qobject_cast >(filter); @@ -142,21 +140,38 @@ namespace AzToolsFramework { m_assetTypeFilter = qobject_cast >(*it); } - it = AZStd::find_if(subFilters.begin(), subFilters.end(), [subFilters](FilterConstType filter) -> bool + + it = AZStd::find_if(subFilters.begin(), subFilters.end(), [](FilterConstType filter) -> bool { - auto stringFilter = qobject_cast >(filter); - return !stringFilter.isNull(); + auto stringCompositeFilter = qobject_cast >(filter); + bool isStringFilter = false; + if (stringCompositeFilter) + { + auto& subFilters = stringCompositeFilter->GetSubFilters(); + auto it = AZStd::find_if(subFilters.begin(), subFilters.end(), [](FilterConstType filt) -> bool + { + auto strFilter = qobject_cast>(filt); + return !strFilter.isNull(); + }); + if (it != subFilters.end()) + { + isStringFilter = true; + } + } + + return isStringFilter; }); if (it != subFilters.end()) { - m_stringFilter = qobject_cast >(*it); - emit switchFilterView(m_stringFilter.toStrongRef()->IsEmpty()); + auto compStringFilter = qobject_cast>(*it); + m_stringFilter = qobject_cast>(compStringFilter->GetSubFilters()[0]); } + } - - invalidateFilter(); Q_EMIT filterChanged(); + emit stringFilterPopulated(!m_stringFilter.isNull()); + } void AssetBrowserFilterModel::filterUpdatedSlot() diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h index 71689354d1..7a6faf9f18 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h @@ -52,7 +52,7 @@ namespace AzToolsFramework void OnAssetBrowserComponentReady() override; Q_SIGNALS: - void switchFilterView(int); + void stringFilterPopulated(bool); void filterChanged(); ////////////////////////////////////////////////////////////////////////// //QSortFilterProxyModel diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp index d1bbbb1f9d..047d4d4dc2 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp @@ -97,7 +97,6 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) }); connect(m_filterModel.data(), &AssetBrowserFilterModel::filterChanged, m_tableModel.data(), &AssetBrowserTableModel::UpdateTableModelMaps); - connect(m_filterModel.data(), &AssetBrowserFilterModel::switchFilterView, this, &AzAssetBrowserWindow::SwitchDisplayView); connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::selectionChangedSignal, this, &AzAssetBrowserWindow::SelectionChangedSlot); @@ -119,6 +118,7 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) m_ui->m_assetBrowserTreeViewWidget->SetName("AssetBrowserTreeView_main"); m_ui->m_assetBrowserTableViewWidget->SetName("AssetBrowserTableView_main"); + connect(m_filterModel.data(), &AssetBrowserFilterModel::stringFilterPopulated, this, &AzAssetBrowserWindow::SwitchDisplayView); connect(m_ui->m_viewSwitcherCheckBox, &QCheckBox::stateChanged, this, &AzAssetBrowserWindow::SwitchDisplayView); } From 10ca002ced59314ac7e4bc01365a2fb7f4682ebe Mon Sep 17 00:00:00 2001 From: igarri Date: Mon, 17 May 2021 14:25:43 +0100 Subject: [PATCH 013/116] Checkbox to select view --- .../Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp | 13 ++++++++++++- .../Editor/AzAssetBrowser/AzAssetBrowserWindow.h | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp index 047d4d4dc2..8c01f6841c 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp @@ -119,7 +119,7 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) m_ui->m_assetBrowserTableViewWidget->SetName("AssetBrowserTableView_main"); connect(m_filterModel.data(), &AssetBrowserFilterModel::stringFilterPopulated, this, &AzAssetBrowserWindow::SwitchDisplayView); - connect(m_ui->m_viewSwitcherCheckBox, &QCheckBox::stateChanged, this, &AzAssetBrowserWindow::SwitchDisplayView); + connect(m_ui->m_viewSwitcherCheckBox, &QCheckBox::stateChanged, this, &AzAssetBrowserWindow::LockToDefaultView); } AzAssetBrowserWindow::~AzAssetBrowserWindow() @@ -290,4 +290,15 @@ void AzAssetBrowserWindow::SwitchDisplayView(bool state) m_ui->m_assetBrowserTreeViewWidget->setVisible(!state); } +void AzAssetBrowserWindow::LockToDefaultView(bool state) +{ + using namespace AzToolsFramework; + using namespace AzToolsFramework::AssetBrowser; + SwitchDisplayView(!state); + if (state == true) + disconnect(m_filterModel.data(), &AssetBrowserFilterModel::stringFilterPopulated, this, &AzAssetBrowserWindow::SwitchDisplayView); + else + connect(m_filterModel.data(), &AssetBrowserFilterModel::stringFilterPopulated, this, &AzAssetBrowserWindow::SwitchDisplayView); +} + #include diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.h b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.h index 8c32a913ba..1174335995 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.h +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.h @@ -65,6 +65,7 @@ private Q_SLOTS: void DoubleClickedItem(const QModelIndex& element); void DoubleClickedItemTableModel(const QModelIndex& element); void SwitchDisplayView(bool state); + void LockToDefaultView(bool state); }; extern const char* AZ_ASSET_BROWSER_PREVIEW_NAME; From 61ac423ebdc0c9865a95710d94f7f21c1c9ce463 Mon Sep 17 00:00:00 2001 From: igarri Date: Mon, 17 May 2021 16:04:43 +0100 Subject: [PATCH 014/116] Deleted unused files --- .../AzToolsFramework/AssetBrowserTableModel.h | 36 ------------------- 1 file changed, 36 deletions(-) delete mode 100644 Code/Framework/AzToolsFramework/AssetBrowserTableModel.h diff --git a/Code/Framework/AzToolsFramework/AssetBrowserTableModel.h b/Code/Framework/AzToolsFramework/AssetBrowserTableModel.h deleted file mode 100644 index 4e65b3921c..0000000000 --- a/Code/Framework/AzToolsFramework/AssetBrowserTableModel.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once -#if !defined(Q_MOC_RUN) -#include -#include -#include - -#include -#include -#include - -AZ_PUSH_DISABLE_WARNING( - 4251, "-Wunknown-warning-option") // 4251: class '...' needs to have dll-interface to be used by clients of class '...' -#include -#include -#include -#endif -AZ_POP_DISABLE_WARNING -namespace AzToolsFramework -{ - namespace AssetBrowser - { - class AssetBrowserTableModel - : public QSortFilterProxyModel - { - Q_OBJECT - public: - AZ_CLASS_ALLOCATOR(AssetBrowserTableModel, AZ::SystemAllocator, 0); - explicit AssetBrowserTableModel(QObject* parent = nullptr); - - QModelIndex mapToSource(const QModelIndex &proxyIndex) const override; - QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override; - QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - }; - } -} From 1c2b8f91118f744314dc4f34ed33fc66245eea7c Mon Sep 17 00:00:00 2001 From: igarri Date: Tue, 18 May 2021 13:33:21 +0100 Subject: [PATCH 015/116] Adding AZ_CVAR for the new feature --- .../AssetBrowser/AssetBrowserFilterModel.cpp | 10 +++- .../AssetBrowser/Search/Filter.cpp | 5 -- .../AssetBrowser/Search/Filter.h | 1 - .../AzAssetBrowser/AzAssetBrowserWindow.cpp | 51 ++++++++++++------- 4 files changed, 43 insertions(+), 24 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp index 9ee00a96ae..5b820c4d06 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp @@ -12,6 +12,7 @@ #include #include #include +#include AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") #include @@ -22,6 +23,10 @@ AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") #include AZ_POP_DISABLE_WARNING +AZ_CVAR( + bool, ed_useNewAssetBrowserTableView, false, nullptr, AZ::ConsoleFunctorFlags::Null, + "Use the new AssetBrowser TableView for searching assets."); + namespace AzToolsFramework { namespace AssetBrowser @@ -32,7 +37,10 @@ namespace AzToolsFramework : QSortFilterProxyModel(parent) { m_showColumn.insert(static_cast(AssetBrowserEntry::Column::DisplayName)); - m_showColumn.insert(static_cast(AssetBrowserEntry::Column::Path)); + if (ed_useNewAssetBrowserTableView) + { + m_showColumn.insert(static_cast(AssetBrowserEntry::Column::Path)); + } m_collator.setNumericMode(true); AssetBrowserComponentNotificationBus::Handler::BusConnect(); } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.cpp index 86315613ad..ceda5f8e19 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.cpp @@ -233,11 +233,6 @@ namespace AzToolsFramework Q_EMIT updatedSignal(); } - bool StringFilter::IsEmpty() const - { - return m_filterString.isEmpty(); - } - QString StringFilter::GetNameInternal() const { return m_filterString; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.h index 6d19fb3b47..135dd00925 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.h @@ -110,7 +110,6 @@ namespace AzToolsFramework ~StringFilter() override = default; void SetFilterString(const QString& filterString); - bool IsEmpty() const; protected: QString GetNameInternal() const override; bool MatchInternal(const AssetBrowserEntry* entry) const override; diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp index 8c01f6841c..c4a79a9394 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp @@ -20,6 +20,7 @@ #include #include #include +#include // AzQtComponents #include @@ -32,6 +33,9 @@ AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING #include AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING +AZ_CVAR( + bool, ed_useNewAssetBrowserTableView, false, nullptr, AZ::ConsoleFunctorFlags::Null, + "Use the new AssetBrowser TableView for searching assets."); class ListenerForShowAssetEditorEvent : public QObject @@ -78,15 +82,40 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) m_filterModel->setSourceModel(m_assetBrowserModel); m_filterModel->SetFilter(m_ui->m_searchWidget->GetFilter()); - m_tableModel->setFilterRole(Qt::DisplayRole); - m_tableModel->setSourceModel(m_filterModel.data()); + m_ui->m_viewSwitcherCheckBox->setVisible(false); + m_ui->m_assetBrowserTableViewWidget->setVisible(false); + if (ed_useNewAssetBrowserTableView) + { + m_ui->m_viewSwitcherCheckBox->setVisible(true); + m_tableModel->setFilterRole(Qt::DisplayRole); + m_tableModel->setSourceModel(m_filterModel.data()); + m_ui->m_assetBrowserTableViewWidget->setModel(m_tableModel.data()); + connect( + m_filterModel.data(), &AssetBrowserFilterModel::filterChanged, m_tableModel.data(), + &AssetBrowserTableModel::UpdateTableModelMaps); + connect( + m_ui->m_assetBrowserTableViewWidget, &AssetBrowserTableView::selectionChangedSignal, this, + &AzAssetBrowserWindow::SelectionChangedSlot); + connect( + m_ui->m_assetBrowserTableViewWidget, &QAbstractItemView::doubleClicked, this, + &AzAssetBrowserWindow::DoubleClickedItemTableModel); + connect( + m_ui->m_assetBrowserTableViewWidget, &AssetBrowserTableView::ClearStringFilter, m_ui->m_searchWidget, + &SearchWidget::ClearStringFilter); + connect( + m_ui->m_assetBrowserTableViewWidget, &AssetBrowserTableView::ClearTypeFilter, m_ui->m_searchWidget, + &SearchWidget::ClearTypeFilter); + + m_ui->m_assetBrowserTableViewWidget->SetName("AssetBrowserTableView_main"); + + connect(m_filterModel.data(), &AssetBrowserFilterModel::stringFilterPopulated, this, &AzAssetBrowserWindow::SwitchDisplayView); + connect(m_ui->m_viewSwitcherCheckBox, &QCheckBox::stateChanged, this, &AzAssetBrowserWindow::LockToDefaultView); + + } m_ui->m_assetBrowserTreeViewWidget->setModel(m_filterModel.data()); //m_ui->m_assetBrowserTreeViewWidget->hideColumn(static_cast(AssetBrowserEntry::Column::Path)); - m_ui->m_assetBrowserTableViewWidget->setModel(m_tableModel.data()); - m_ui->m_assetBrowserTableViewWidget->setVisible(false); - connect(m_ui->m_searchWidget->GetFilter().data(), &AssetBrowserEntryFilter::updatedSignal, m_filterModel.data(), &AssetBrowserFilterModel::filterUpdatedSlot); connect(m_filterModel.data(), &AssetBrowserFilterModel::filterChanged, this, [this]() @@ -96,30 +125,18 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) m_ui->m_assetBrowserTreeViewWidget->UpdateAfterFilter(hasFilter, selectFirstFilteredIndex); }); - connect(m_filterModel.data(), &AssetBrowserFilterModel::filterChanged, m_tableModel.data(), &AssetBrowserTableModel::UpdateTableModelMaps); connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::selectionChangedSignal, this, &AzAssetBrowserWindow::SelectionChangedSlot); - connect(m_ui->m_assetBrowserTableViewWidget, &AssetBrowserTableView::selectionChangedSignal, - this, &AzAssetBrowserWindow::SelectionChangedSlot); - connect(m_ui->m_assetBrowserTreeViewWidget, &QAbstractItemView::doubleClicked, this, &AzAssetBrowserWindow::DoubleClickedItem); - connect(m_ui->m_assetBrowserTableViewWidget, &QAbstractItemView::doubleClicked, this, &AzAssetBrowserWindow::DoubleClickedItemTableModel); - connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::ClearStringFilter, m_ui->m_searchWidget, &SearchWidget::ClearStringFilter); connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::ClearTypeFilter, m_ui->m_searchWidget, &SearchWidget::ClearTypeFilter); - connect(m_ui->m_assetBrowserTableViewWidget, &AssetBrowserTableView::ClearStringFilter, m_ui->m_searchWidget, &SearchWidget::ClearStringFilter); - connect(m_ui->m_assetBrowserTableViewWidget, &AssetBrowserTableView::ClearTypeFilter, m_ui->m_searchWidget, &SearchWidget::ClearTypeFilter); m_ui->m_assetBrowserTreeViewWidget->SetName("AssetBrowserTreeView_main"); - m_ui->m_assetBrowserTableViewWidget->SetName("AssetBrowserTableView_main"); - - connect(m_filterModel.data(), &AssetBrowserFilterModel::stringFilterPopulated, this, &AzAssetBrowserWindow::SwitchDisplayView); - connect(m_ui->m_viewSwitcherCheckBox, &QCheckBox::stateChanged, this, &AzAssetBrowserWindow::LockToDefaultView); } AzAssetBrowserWindow::~AzAssetBrowserWindow() From f49e4b33337b47b6939f1df90c99696fd0e5efd5 Mon Sep 17 00:00:00 2001 From: igarri Date: Tue, 18 May 2021 15:26:05 +0100 Subject: [PATCH 016/116] modified code from feedback --- .../AssetBrowser/AssetBrowserFilterModel.cpp | 33 +++++++++++-------- .../AssetBrowser/AssetBrowserModel.cpp | 10 +++--- .../AssetBrowser/AssetBrowserModel.h | 2 -- .../Views/AssetBrowserTreeView.cpp | 1 + .../AzAssetBrowser/AzAssetBrowserWindow.cpp | 5 ++- 5 files changed, 26 insertions(+), 25 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp index 5b820c4d06..77e5523ee3 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp @@ -23,9 +23,7 @@ AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") #include AZ_POP_DISABLE_WARNING -AZ_CVAR( - bool, ed_useNewAssetBrowserTableView, false, nullptr, AZ::ConsoleFunctorFlags::Null, - "Use the new AssetBrowser TableView for searching assets."); +AZ_CVAR_EXTERNED(bool, ed_useNewAssetBrowserTableView); namespace AzToolsFramework { @@ -36,10 +34,10 @@ namespace AzToolsFramework AssetBrowserFilterModel::AssetBrowserFilterModel(QObject* parent) : QSortFilterProxyModel(parent) { - m_showColumn.insert(static_cast(AssetBrowserEntry::Column::DisplayName)); + m_showColumn.insert(aznumeric_cast(AssetBrowserEntry::Column::DisplayName)); if (ed_useNewAssetBrowserTableView) { - m_showColumn.insert(static_cast(AssetBrowserEntry::Column::Path)); + m_showColumn.insert(aznumeric_cast(AssetBrowserEntry::Column::Path)); } m_collator.setNumericMode(true); AssetBrowserComponentNotificationBus::Handler::BusConnect(); @@ -149,19 +147,23 @@ namespace AzToolsFramework m_assetTypeFilter = qobject_cast >(*it); } - it = AZStd::find_if(subFilters.begin(), subFilters.end(), [](FilterConstType filter) -> bool + auto compStringFilterIter = AZStd::find_if(subFilters.begin(), subFilters.end(), [](FilterConstType filter) -> bool { + //The real StringFilter is really a CompositeFilter with just one StringFilter in its subfilter list + //To know if it is actually a StringFilter we have to get that subfilter and check if it is a Stringfilter. auto stringCompositeFilter = qobject_cast >(filter); bool isStringFilter = false; if (stringCompositeFilter) { - auto& subFilters = stringCompositeFilter->GetSubFilters(); - auto it = AZStd::find_if(subFilters.begin(), subFilters.end(), [](FilterConstType filt) -> bool - { + const auto& stringSubfilters = stringCompositeFilter->GetSubFilters(); + auto canBeCasted = [](FilterConstType filt) -> bool { auto strFilter = qobject_cast>(filt); return !strFilter.isNull(); - }); - if (it != subFilters.end()) + }; + auto stringSubfliterConstIter = AZStd::find_if(stringSubfilters.begin(), stringSubfilters.end(), canBeCasted); + + //A Composite StringFilter will only have just one subfilter and nothing more. + if (stringSubfliterConstIter != stringSubfilters.end() && stringSubfilters.size() == 1) { isStringFilter = true; } @@ -169,10 +171,13 @@ namespace AzToolsFramework return isStringFilter; }); - if (it != subFilters.end()) + if (compStringFilterIter != subFilters.end()) { - auto compStringFilter = qobject_cast>(*it); - m_stringFilter = qobject_cast>(compStringFilter->GetSubFilters()[0]); + auto compStringFilter = qobject_cast>(*compStringFilterIter); + if (compStringFilter->GetSubFilters().size() > 0 && compStringFilter->GetSubFilters()[0]) + { + m_stringFilter = qobject_cast>(compStringFilter->GetSubFilters()[0]); + } } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.cpp index 1101e11f3a..a5cfad09ba 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.cpp @@ -27,8 +27,6 @@ namespace AzToolsFramework { namespace AssetBrowser { - const int AssetBrowserModel::m_column = static_cast(AssetBrowserEntry::Column::DisplayName); - AssetBrowserModel::AssetBrowserModel(QObject* parent) : QAbstractItemModel(parent) , m_rootEntry(nullptr) @@ -143,9 +141,9 @@ namespace AzToolsFramework if (parent.isValid()) { - if ((parent.column() != static_cast(AssetBrowserEntry::Column::DisplayName)) && - (parent.column() != static_cast(AssetBrowserEntry::Column::Name)) && - (parent.column() != static_cast(AssetBrowserEntry::Column::Path))) + if ((parent.column() != aznumeric_cast(AssetBrowserEntry::Column::DisplayName)) && + (parent.column() != aznumeric_cast(AssetBrowserEntry::Column::Name)) && + (parent.column() != aznumeric_cast(AssetBrowserEntry::Column::Path))) { return 0; } @@ -394,7 +392,7 @@ namespace AzToolsFramework } int row = entry->row(); - index = createIndex(row, m_column, entry); + index = createIndex(row, aznumeric_cast(AssetBrowserEntry::Column::DisplayName), entry); return true; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.h index 9e60c44dae..3c4cae5588 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.h @@ -91,8 +91,6 @@ namespace AzToolsFramework static void SourceIndexesToAssetIds(const QModelIndexList& indexes, AZStd::vector& assetIds); static void SourceIndexesToAssetDatabaseEntries(const QModelIndexList& indexes, AZStd::vector& entries); - const static int m_column; - private: AZStd::shared_ptr m_rootEntry; bool m_loaded; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.cpp index e29607698d..660c04ccd4 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.cpp @@ -102,6 +102,7 @@ namespace AzToolsFramework QModelIndexList sourceIndexes; for (const auto& index : selectedIndexes()) { + //If we check for more than one column then the model will try to select the same entry several times. if (index.column() == 0) { sourceIndexes.push_back(m_assetBrowserSortFilterProxyModel->mapToSource(index)); diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp index c4a79a9394..412dc61465 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp @@ -114,7 +114,6 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) } m_ui->m_assetBrowserTreeViewWidget->setModel(m_filterModel.data()); - //m_ui->m_assetBrowserTreeViewWidget->hideColumn(static_cast(AssetBrowserEntry::Column::Path)); connect(m_ui->m_searchWidget->GetFilter().data(), &AssetBrowserEntryFilter::updatedSignal, m_filterModel.data(), &AssetBrowserFilterModel::filterUpdatedSlot); @@ -232,7 +231,7 @@ void AzAssetBrowserWindow::DoubleClickedItem([[maybe_unused]] const QModelIndex& using namespace AzToolsFramework; using namespace AzToolsFramework::AssetBrowser; // assumption: Double clicking an item selects it before telling us we double clicked it. - auto selectedAssets = m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets(); + const auto& selectedAssets = m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets(); for (const AssetBrowserEntry* entry : selectedAssets) { AZ::Data::AssetId assetIdToOpen; @@ -269,7 +268,7 @@ void AzAssetBrowserWindow::DoubleClickedItemTableModel([[maybe_unused]] const QM using namespace AzToolsFramework; using namespace AzToolsFramework::AssetBrowser; // assumption: Double clicking an item selects it before telling us we double clicked it. - auto selectedAssets = m_ui->m_assetBrowserTableViewWidget->GetSelectedAssets(); + const auto& selectedAssets = m_ui->m_assetBrowserTableViewWidget->GetSelectedAssets(); for (const AssetBrowserEntry* entry : selectedAssets) { AZ::Data::AssetId assetIdToOpen; From ec784b005ffdd39288097ed17f44612cf00b32a4 Mon Sep 17 00:00:00 2001 From: igarri Date: Tue, 18 May 2021 15:49:35 +0100 Subject: [PATCH 017/116] More Corrections --- .../AssetBrowser/AssetBrowserFilterModel.cpp | 2 +- .../AssetBrowser/AssetBrowserTableModel.cpp | 44 ++++++++++--------- .../AssetBrowser/AssetBrowserTableModel.h | 13 +++++- .../Views/AssetBrowserTableView.cpp | 28 +++++++----- .../Views/AssetBrowserTableView.h | 11 +++++ 5 files changed, 64 insertions(+), 34 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp index 77e5523ee3..12b0256c5d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp @@ -174,7 +174,7 @@ namespace AzToolsFramework if (compStringFilterIter != subFilters.end()) { auto compStringFilter = qobject_cast>(*compStringFilterIter); - if (compStringFilter->GetSubFilters().size() > 0 && compStringFilter->GetSubFilters()[0]) + if (!compStringFilter->GetSubFilters().isEmpty() && compStringFilter->GetSubFilters()[0]) { m_stringFilter = qobject_cast>(compStringFilter->GetSubFilters()[0]); } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp index bebdf44c9a..b9bfe1bea6 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp @@ -1,3 +1,14 @@ +/* + * 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 #include #include @@ -32,24 +43,27 @@ namespace AzToolsFramework { if (role == Qt::DisplayRole && orientation == Qt::Horizontal) { - switch (section) + auto columnRole = aznumeric_cast(role); + switch (columnRole) { - case static_cast(AssetBrowserEntry::Column::Name): + case AssetBrowserEntry::Column::Name: return QString("Name"); - case static_cast(AssetBrowserEntry::Column::Path): + case AssetBrowserEntry::Column::Path: return QString("Path"); default: return QString::number(section); } } - return QSortFilterProxyModel::headerData(section, orientation, role); // QVariant(); + return QSortFilterProxyModel::headerData(section, orientation, role); } QVariant AssetBrowserTableModel::data(const QModelIndex& index, int role) const { auto sourceIndex = mapToSource(index); if (!sourceIndex.isValid()) + { return QVariant(); + } AssetBrowserEntry* entry = GetAssetEntry(sourceIndex); if (entry == nullptr) @@ -66,22 +80,10 @@ namespace AzToolsFramework return parent.isValid() ? QModelIndex() : createIndex(row, column, m_indexMap[row].internalPointer()); } - QModelIndex AssetBrowserTableModel::parent(const QModelIndex& child) const + QModelIndex AssetBrowserTableModel::parent([[maybe_unused]] const QModelIndex& child) const { - AZ_UNUSED(child); return QModelIndex(); } - bool AssetBrowserTableModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const - { - AZ_UNUSED(source_row); - AZ_UNUSED(source_parent); - // no filter present, every entry is not visible - if (!m_filterModel->GetFilter()) - { - return true; - } - return true; - } int AssetBrowserTableModel::rowCount(const QModelIndex& parent) const { @@ -94,14 +96,14 @@ namespace AzToolsFramework for (int i = 0; i < rows; ++i) { QModelIndex index = model->index(i, 0, parent); - if (model->hasChildren(index) == false) + if (!model->hasChildren(index)) { beginInsertRows(parent, row, row); m_indexMap[row] = index; endInsertRows(); Q_EMIT dataChanged(index, index); - row = row + 1; + ++row; } if (model->hasChildren(index)) @@ -124,9 +126,9 @@ namespace AzToolsFramework } } void AssetBrowserTableModel::UpdateTableModelMaps() -{ + { emit layoutAboutToBeChanged(); - if (m_indexMap.size() > 0) + if (!m_indexMap.isEmpty()) { beginRemoveRows(m_indexMap.first(), m_indexMap.first().row(), m_indexMap.last().row()); m_indexMap.clear(); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h index 432300194b..b0497213a0 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h @@ -1,4 +1,16 @@ +/* + * 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 #include @@ -30,7 +42,6 @@ namespace AzToolsFramework public Q_SLOTS: void UpdateTableModelMaps(); protected: - bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override; int rowCount(const QModelIndex& parent = QModelIndex()) const override; QVariant headerData(int section, Qt::Orientation orientation, int role /* = Qt::DisplayRole */) const override; //////////////////////////////////////////////////////////////////// diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp index cb4a989043..df3b0b8644 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp @@ -1,3 +1,15 @@ +/* + * 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 #include @@ -109,21 +121,16 @@ namespace AzToolsFramework } QTableView::rowsAboutToBeRemoved(parent, start, end); } - void AssetBrowserTableView::layoutChangedSlot(const QList& parents, QAbstractItemModel::LayoutChangeHint hint) + void AssetBrowserTableView::layoutChangedSlot([[maybe_unused]] const QList& parents,[[maybe_unused]] QAbstractItemModel::LayoutChangeHint hint) { - AZ_UNUSED(parents); - AZ_UNUSED(hint); - scrollToTop(); } - void AssetBrowserTableView::SelectProduct(AZ::Data::AssetId assetID) + void AssetBrowserTableView::SelectProduct([[maybe_unused]] AZ::Data::AssetId assetID) { - AZ_UNUSED(assetID); } - void AssetBrowserTableView::SelectFileAtPath(const AZStd::string& assetPath) + void AssetBrowserTableView::SelectFileAtPath([[maybe_unused]] const AZStd::string& assetPath) { - AZ_UNUSED(assetPath); } void AssetBrowserTableView::ClearFilter() @@ -142,11 +149,10 @@ namespace AzToolsFramework { } - void AssetBrowserTableView::OnContextMenu(const QPoint& point) + void AssetBrowserTableView::OnContextMenu([[maybe_unused]] const QPoint& point) { - AZ_UNUSED(point); - auto selectedAssets = GetSelectedAssets(); + const auto& selectedAssets = GetSelectedAssets(); if (selectedAssets.size() != 1) { return; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h index b39d48c391..482a072373 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h @@ -1,3 +1,14 @@ +/* + * 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 From 0b50b6cc63842c7537ff43609a039e39295f1a5d Mon Sep 17 00:00:00 2001 From: igarri Date: Wed, 19 May 2021 12:04:40 +0100 Subject: [PATCH 018/116] Fixed code Style and minor issues from feedback --- .../AssetBrowser/AssetBrowserFilterModel.cpp | 1 - .../AssetBrowser/AssetBrowserTableModel.cpp | 13 ++++++++----- .../AssetBrowser/Views/AssetBrowserTableView.cpp | 8 ++++++++ .../AssetBrowser/Views/EntryDelegate.cpp | 6 +++--- .../Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp | 4 ++++ 5 files changed, 23 insertions(+), 9 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp index 12b0256c5d..c5723832c7 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp @@ -184,7 +184,6 @@ namespace AzToolsFramework invalidateFilter(); Q_EMIT filterChanged(); emit stringFilterPopulated(!m_stringFilter.isNull()); - } void AssetBrowserFilterModel::filterUpdatedSlot() diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp index b9bfe1bea6..6d9803dfd4 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp @@ -22,10 +22,11 @@ namespace AzToolsFramework { setDynamicSortFilter(false); } + void AssetBrowserTableModel::setSourceModel(QAbstractItemModel* sourceModel) { m_filterModel = qobject_cast(sourceModel); - AZ_Assert(m_filterModel, "Expecting AssetBrowserFilterModel"); + AZ_Assert(m_filterModel, "Error in AssetBrowserTableModel initialization, class expects source model to be an AssetBrowserFilterModel."); QSortFilterProxyModel::setSourceModel(sourceModel); } @@ -47,9 +48,9 @@ namespace AzToolsFramework switch (columnRole) { case AssetBrowserEntry::Column::Name: - return QString("Name"); + return tr("Name"); case AssetBrowserEntry::Column::Path: - return QString("Path"); + return tr("Path"); default: return QString::number(section); } @@ -68,8 +69,8 @@ namespace AzToolsFramework AssetBrowserEntry* entry = GetAssetEntry(sourceIndex); if (entry == nullptr) { - AZ_Assert(false, "ERROR - index internal pointer not pointing to an AssetEntry. Tree provided by the AssetBrowser invalid?"); - return Qt::PartiallyChecked; + AZ_Assert(false, "AssetBrowserTableModel - QModelIndex does not reference an AssetEntry. Source model is not valid."); + return QVariant(); } return sourceIndex.data(role); @@ -113,6 +114,7 @@ namespace AzToolsFramework } return row; } + AssetBrowserEntry* AssetBrowserTableModel::GetAssetEntry(QModelIndex index) const { if (index.isValid()) @@ -125,6 +127,7 @@ namespace AzToolsFramework return nullptr; } } + void AssetBrowserTableModel::UpdateTableModelMaps() { emit layoutAboutToBeChanged(); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp index df3b0b8644..f7128cb504 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp @@ -60,11 +60,13 @@ namespace AzToolsFramework AssetBrowserViewRequestBus::Handler::BusConnect(); AssetBrowserComponentNotificationBus::Handler::BusConnect(); } + AssetBrowserTableView::~AssetBrowserTableView() { AssetBrowserViewRequestBus::Handler::BusDisconnect(); AssetBrowserComponentNotificationBus::Handler::BusDisconnect(); } + void AssetBrowserTableView::setModel(QAbstractItemModel* model) { m_tableModel = qobject_cast(model); @@ -76,6 +78,7 @@ namespace AzToolsFramework horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeMode::Stretch); horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeMode::Stretch); } + void AssetBrowserTableView::SetName(const QString& name) { m_name = name; @@ -86,6 +89,7 @@ namespace AzToolsFramework OnAssetBrowserComponentReady(); } } + AZStd::vector AssetBrowserTableView::GetSelectedAssets() const { QModelIndexList sourceIndexes; @@ -101,11 +105,13 @@ namespace AzToolsFramework AssetBrowserModel::SourceIndexesToAssetDatabaseEntries(sourceIndexes, entries); return entries; } + void AssetBrowserTableView::selectionChanged(const QItemSelection& selected, const QItemSelection& deselected) { QTableView::selectionChanged(selected, deselected); Q_EMIT selectionChangedSignal(selected, deselected); } + void AssetBrowserTableView::rowsAboutToBeRemoved(const QModelIndex& parent, int start, int end) { // if selected entry is being removed, clear selection so not to select (and attempt to preview) other entries potentially @@ -121,10 +127,12 @@ namespace AzToolsFramework } QTableView::rowsAboutToBeRemoved(parent, start, end); } + void AssetBrowserTableView::layoutChangedSlot([[maybe_unused]] const QList& parents,[[maybe_unused]] QAbstractItemModel::LayoutChangeHint hint) { scrollToTop(); } + void AssetBrowserTableView::SelectProduct([[maybe_unused]] AZ::Data::AssetId assetID) { } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp index b968f0480a..dff8a170c7 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp @@ -99,9 +99,9 @@ namespace AzToolsFramework style->drawItemText( painter, remainingRect, option.displayAlignment, actualPalette, isEnabled, - index.column() == static_cast(AssetBrowserEntry::Column::Name) - ? qvariant_cast(entry->data(static_cast(AssetBrowserEntry::Column::Name))) - : qvariant_cast(entry->data(static_cast(AssetBrowserEntry::Column::Path))), + index.column() == aznumeric_cast(AssetBrowserEntry::Column::Name) + ? qvariant_cast(entry->data(aznumeric_cast(AssetBrowserEntry::Column::Name))) + : qvariant_cast(entry->data(aznumeric_cast(AssetBrowserEntry::Column::Path))), isSelected ? QPalette::HighlightedText : QPalette::Text); } } diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp index 412dc61465..35734042a0 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp @@ -312,9 +312,13 @@ void AzAssetBrowserWindow::LockToDefaultView(bool state) using namespace AzToolsFramework::AssetBrowser; SwitchDisplayView(!state); if (state == true) + { disconnect(m_filterModel.data(), &AssetBrowserFilterModel::stringFilterPopulated, this, &AzAssetBrowserWindow::SwitchDisplayView); + } else + { connect(m_filterModel.data(), &AssetBrowserFilterModel::stringFilterPopulated, this, &AzAssetBrowserWindow::SwitchDisplayView); + } } #include From dfb0d7f9f567ec0d1d8cfa449b5619190296c231 Mon Sep 17 00:00:00 2001 From: igarri Date: Fri, 21 May 2021 12:33:55 +0100 Subject: [PATCH 019/116] Fixed numeric_cast, style, const variables --- .../AssetBrowser/AssetBrowserFilterModel.cpp | 17 +++++++++-------- .../AssetBrowser/AssetBrowserFilterModel.h | 2 +- .../AssetBrowser/AssetBrowserModel.cpp | 2 +- .../AssetBrowser/AssetBrowserTableModel.cpp | 5 ----- .../AssetBrowser/AssetBrowserTableModel.h | 1 - .../AssetBrowser/Views/AssetBrowserTableView.h | 3 ++- .../AssetBrowser/Views/AssetBrowserTreeView.cpp | 2 +- .../AssetBrowser/Views/EntryDelegate.cpp | 2 +- .../AzAssetBrowser/AzAssetBrowserWindow.cpp | 4 ---- 9 files changed, 15 insertions(+), 23 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp index c5723832c7..7c7f2aa601 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp @@ -135,28 +135,29 @@ namespace AzToolsFramework auto compFilter = qobject_cast >(m_filter); if (compFilter) { - auto& subFilters = compFilter->GetSubFilters(); + const auto& subFilters = compFilter->GetSubFilters(); - auto it = AZStd::find_if(subFilters.begin(), subFilters.end(), [subFilters](FilterConstType filter) -> bool + auto compositeFilterIterator = AZStd::find_if(subFilters.begin(), subFilters.end(), [subFilters](FilterConstType filter) -> bool { - auto assetTypeFilter = qobject_cast >(filter); + const auto assetTypeFilter = qobject_cast >(filter); return !assetTypeFilter.isNull(); }); - if (it != subFilters.end()) + if (compositeFilterIterator != subFilters.end()) { - m_assetTypeFilter = qobject_cast >(*it); + m_assetTypeFilter = qobject_cast >(*compositeFilterIterator); } auto compStringFilterIter = AZStd::find_if(subFilters.begin(), subFilters.end(), [](FilterConstType filter) -> bool { //The real StringFilter is really a CompositeFilter with just one StringFilter in its subfilter list //To know if it is actually a StringFilter we have to get that subfilter and check if it is a Stringfilter. - auto stringCompositeFilter = qobject_cast >(filter); + const auto stringCompositeFilter = qobject_cast >(filter); bool isStringFilter = false; if (stringCompositeFilter) { const auto& stringSubfilters = stringCompositeFilter->GetSubFilters(); - auto canBeCasted = [](FilterConstType filt) -> bool { + auto canBeCasted = [](FilterConstType filt) -> bool + { auto strFilter = qobject_cast>(filt); return !strFilter.isNull(); }; @@ -173,7 +174,7 @@ namespace AzToolsFramework }); if (compStringFilterIter != subFilters.end()) { - auto compStringFilter = qobject_cast>(*compStringFilterIter); + const auto compStringFilter = qobject_cast>(*compStringFilterIter); if (!compStringFilter->GetSubFilters().isEmpty() && compStringFilter->GetSubFilters()[0]) { m_stringFilter = qobject_cast>(compStringFilter->GetSubFilters()[0]); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h index 7a6faf9f18..5d22791699 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h @@ -68,7 +68,7 @@ namespace AzToolsFramework protected: //set for filtering columns //if the column is in the set the column is not filtered and is shown - AZStd::fixed_unordered_set(AssetBrowserEntry::Column::Count)> m_showColumn; + AZStd::fixed_unordered_set(AssetBrowserEntry::Column::Count)> m_showColumn; bool m_alreadyRecomputingFilters = false; //asset source name match filter FilterConstType m_filter; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.cpp index a5cfad09ba..c0f78baccb 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.cpp @@ -163,7 +163,7 @@ namespace AzToolsFramework int AssetBrowserModel::columnCount(const QModelIndex& /*parent*/) const { - return static_cast(AssetBrowserEntry::Column::Count); + return aznumeric_cast(AssetBrowserEntry::Column::Count); } QVariant AssetBrowserModel::data(const QModelIndex& index, int role) const diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp index 6d9803dfd4..40f8318a2d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp @@ -81,11 +81,6 @@ namespace AzToolsFramework return parent.isValid() ? QModelIndex() : createIndex(row, column, m_indexMap[row].internalPointer()); } - QModelIndex AssetBrowserTableModel::parent([[maybe_unused]] const QModelIndex& child) const - { - return QModelIndex(); - } - int AssetBrowserTableModel::rowCount(const QModelIndex& parent) const { return !parent.isValid() ? m_indexMap.size() : 0; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h index b0497213a0..6b64ceaf92 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h @@ -36,7 +36,6 @@ namespace AzToolsFramework // QSortFilterProxyModel void setSourceModel(QAbstractItemModel* sourceModel) override; QModelIndex mapToSource(const QModelIndex& proxyIndex) const override; - QModelIndex parent(const QModelIndex& child) const override; QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; public Q_SLOTS: diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h index 482a072373..65f97d1a6d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h @@ -68,7 +68,8 @@ namespace AzToolsFramework protected Q_SLOTS: void selectionChanged(const QItemSelection& selected, const QItemSelection& deselected) override; void rowsAboutToBeRemoved(const QModelIndex& parent, int start, int end) override; - void layoutChangedSlot(const QList &parents = QList(), QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint); + void layoutChangedSlot(const QList &parents = QList(), + QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint); private: QString m_name; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.cpp index 660c04ccd4..b93caf85f7 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.cpp @@ -176,7 +176,7 @@ namespace AzToolsFramework void AssetBrowserTreeView::OnAssetBrowserComponentReady() { - hideColumn(static_cast(AssetBrowserEntry::Column::Path)); + hideColumn(aznumeric_cast(AssetBrowserEntry::Column::Path)); if (!m_name.isEmpty()) { auto crc = AZ::Crc32(m_name.toUtf8().data()); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp index dff8a170c7..c73c00981b 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp @@ -75,7 +75,7 @@ namespace AzToolsFramework auto sourceEntry = azrtti_cast(entry); QPalette actualPalette(option.palette); - if (index.column() == static_cast(AssetBrowserEntry::Column::Name)) + if (index.column() == aznumeric_cast(AssetBrowserEntry::Column::Name)) { int thumbX = DrawThumbnail(painter, iconTopLeft, iconSize, entry->GetThumbnailKey()); if (sourceEntry) diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp index 35734042a0..1b123dd000 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp @@ -110,7 +110,6 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) connect(m_filterModel.data(), &AssetBrowserFilterModel::stringFilterPopulated, this, &AzAssetBrowserWindow::SwitchDisplayView); connect(m_ui->m_viewSwitcherCheckBox, &QCheckBox::stateChanged, this, &AzAssetBrowserWindow::LockToDefaultView); - } m_ui->m_assetBrowserTreeViewWidget->setModel(m_filterModel.data()); @@ -124,17 +123,14 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) m_ui->m_assetBrowserTreeViewWidget->UpdateAfterFilter(hasFilter, selectFirstFilteredIndex); }); - connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::selectionChangedSignal, this, &AzAssetBrowserWindow::SelectionChangedSlot); connect(m_ui->m_assetBrowserTreeViewWidget, &QAbstractItemView::doubleClicked, this, &AzAssetBrowserWindow::DoubleClickedItem); - connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::ClearStringFilter, m_ui->m_searchWidget, &SearchWidget::ClearStringFilter); connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::ClearTypeFilter, m_ui->m_searchWidget, &SearchWidget::ClearTypeFilter); - m_ui->m_assetBrowserTreeViewWidget->SetName("AssetBrowserTreeView_main"); } From 6a0cf974560d5d617d601cc9c765d7de022be1ea Mon Sep 17 00:00:00 2001 From: igarri Date: Mon, 24 May 2021 13:19:35 +0100 Subject: [PATCH 020/116] Fixed Selection in AssetBrowserTreeView --- .../AssetBrowser/AssetBrowserFilterModel.cpp | 5 +++-- .../AssetBrowser/Views/AssetBrowserTreeView.cpp | 4 +++- Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp | 5 ++--- .../Code/Editor/Model/UnitTestBrowserFilterModel.cpp | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp index 7c7f2aa601..fc2fc41656 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp @@ -23,8 +23,9 @@ AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") #include AZ_POP_DISABLE_WARNING -AZ_CVAR_EXTERNED(bool, ed_useNewAssetBrowserTableView); - +AZ_CVAR( + bool, ed_useNewAssetBrowserTableView, false, nullptr, AZ::ConsoleFunctorFlags::Null, + "Use the new AssetBrowser TableView for searching assets."); namespace AzToolsFramework { namespace AssetBrowser diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.cpp index b93caf85f7..52c785d678 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.cpp @@ -99,8 +99,10 @@ namespace AzToolsFramework AZStd::vector AssetBrowserTreeView::GetSelectedAssets() const { + + const QModelIndexList& selectedIndexes = selectionModel()->selectedRows(); QModelIndexList sourceIndexes; - for (const auto& index : selectedIndexes()) + for (const auto& index : selectedIndexes) { //If we check for more than one column then the model will try to select the same entry several times. if (index.column() == 0) diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp index 1b123dd000..e722d6d03e 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp @@ -33,9 +33,8 @@ AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING #include AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING -AZ_CVAR( - bool, ed_useNewAssetBrowserTableView, false, nullptr, AZ::ConsoleFunctorFlags::Null, - "Use the new AssetBrowser TableView for searching assets."); +AZ_CVAR_EXTERNED(bool, ed_useNewAssetBrowserTableView); + class ListenerForShowAssetEditorEvent : public QObject diff --git a/Gems/ScriptCanvas/Code/Editor/Model/UnitTestBrowserFilterModel.cpp b/Gems/ScriptCanvas/Code/Editor/Model/UnitTestBrowserFilterModel.cpp index 665c81fa57..1a4d95c585 100644 --- a/Gems/ScriptCanvas/Code/Editor/Model/UnitTestBrowserFilterModel.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Model/UnitTestBrowserFilterModel.cpp @@ -34,7 +34,7 @@ namespace ScriptCanvasEditor { setDynamicSortFilter(true); - m_showColumn.insert(AssetBrowserModel::m_column); + m_showColumn.insert(aznumeric_cast(AssetBrowserEntry::Column::DisplayName)); UnitTestWidgetNotificationBus::Handler::BusConnect(); From 6ca37bbf84e14118ccb1000ea51eed2d887a3473 Mon Sep 17 00:00:00 2001 From: igarri Date: Thu, 27 May 2021 14:04:02 +0100 Subject: [PATCH 021/116] Checking variable constness --- .../AssetBrowser/AssetBrowserFilterModel.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp index fc2fc41656..2660b660e4 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp @@ -26,6 +26,7 @@ AZ_POP_DISABLE_WARNING AZ_CVAR( bool, ed_useNewAssetBrowserTableView, false, nullptr, AZ::ConsoleFunctorFlags::Null, "Use the new AssetBrowser TableView for searching assets."); +#pragma optimize("", off) namespace AzToolsFramework { namespace AssetBrowser @@ -138,17 +139,18 @@ namespace AzToolsFramework { const auto& subFilters = compFilter->GetSubFilters(); - auto compositeFilterIterator = AZStd::find_if(subFilters.begin(), subFilters.end(), [subFilters](FilterConstType filter) -> bool + const auto compositeFilterIterator = AZStd::find_if(subFilters.begin(), subFilters.end(), [subFilters](FilterConstType filter) -> bool { const auto assetTypeFilter = qobject_cast >(filter); return !assetTypeFilter.isNull(); }); + if (compositeFilterIterator != subFilters.end()) { m_assetTypeFilter = qobject_cast >(*compositeFilterIterator); } - auto compStringFilterIter = AZStd::find_if(subFilters.begin(), subFilters.end(), [](FilterConstType filter) -> bool + const auto compStringFilterIter = AZStd::find_if(subFilters.begin(), subFilters.end(), [](FilterConstType filter) -> bool { //The real StringFilter is really a CompositeFilter with just one StringFilter in its subfilter list //To know if it is actually a StringFilter we have to get that subfilter and check if it is a Stringfilter. @@ -162,7 +164,7 @@ namespace AzToolsFramework auto strFilter = qobject_cast>(filt); return !strFilter.isNull(); }; - auto stringSubfliterConstIter = AZStd::find_if(stringSubfilters.begin(), stringSubfilters.end(), canBeCasted); + const auto stringSubfliterConstIter = AZStd::find_if(stringSubfilters.begin(), stringSubfilters.end(), canBeCasted); //A Composite StringFilter will only have just one subfilter and nothing more. if (stringSubfliterConstIter != stringSubfilters.end() && stringSubfilters.size() == 1) @@ -176,6 +178,7 @@ namespace AzToolsFramework if (compStringFilterIter != subFilters.end()) { const auto compStringFilter = qobject_cast>(*compStringFilterIter); + if (!compStringFilter->GetSubFilters().isEmpty() && compStringFilter->GetSubFilters()[0]) { m_stringFilter = qobject_cast>(compStringFilter->GetSubFilters()[0]); @@ -185,7 +188,8 @@ namespace AzToolsFramework } invalidateFilter(); Q_EMIT filterChanged(); - emit stringFilterPopulated(!m_stringFilter.isNull()); + bool isNullAB = m_stringFilter.isNull(); + emit stringFilterPopulated(!isNullAB); } void AssetBrowserFilterModel::filterUpdatedSlot() @@ -205,5 +209,6 @@ namespace AzToolsFramework } // namespace AssetBrowser } // namespace AzToolsFramework// namespace AssetBrowser +#pragma optimize("", on) #include "AssetBrowser/moc_AssetBrowserFilterModel.cpp" From 00a529ad74d139419ea2e4f331b21509a01dcf85 Mon Sep 17 00:00:00 2001 From: amzn-mike <80125227+amzn-mike@users.noreply.github.com> Date: Fri, 28 May 2021 14:56:52 -0500 Subject: [PATCH 022/116] Fix AssImpTransformImporter logic for bone nodes For bone nodes, the Transform is computed by multiplying the parent offsetMatrix by the inverse of the node's offsetMatrix Note that this currently disables the LimitBoneWeights option since that results in the removal of bone nodes that are not attached to a mesh. Without the bones there is no way to retrieve the offsetMatrix, so the Transform cannot be computed correctly Fixes LYN-3755 --- .../Importers/AssImpTransformImporter.cpp | 59 ++++++++++++++++--- .../SDKWrapper/AssImpSceneWrapper.cpp | 5 +- 2 files changed, 55 insertions(+), 9 deletions(-) diff --git a/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpTransformImporter.cpp b/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpTransformImporter.cpp index 5357c32fa9..bcc007e3a7 100644 --- a/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpTransformImporter.cpp +++ b/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpTransformImporter.cpp @@ -46,22 +46,69 @@ namespace AZ serializeContext->Class()->Version(1); } } - + + void GetAllBones(const aiScene* scene, AZStd::unordered_map& boneLookup) + { + for (unsigned meshIndex = 0; meshIndex < scene->mNumMeshes; ++meshIndex) + { + const aiMesh* mesh = scene->mMeshes[meshIndex]; + + for (unsigned boneIndex = 0; boneIndex < mesh->mNumBones; ++boneIndex) + { + const aiBone* bone = mesh->mBones[boneIndex]; + + boneLookup[bone->mName.C_Str()] = bone; + } + } + } + Events::ProcessingResult AssImpTransformImporter::ImportTransform(AssImpSceneNodeAppendedContext& context) { AZ_TraceContext("Importer", "transform"); const aiNode* currentNode = context.m_sourceNode.GetAssImpNode(); const aiScene* scene = context.m_sourceScene.GetAssImpScene(); - + if (currentNode == scene->mRootNode || IsPivotNode(currentNode->mName)) { return Events::ProcessingResult::Ignored; } - aiMatrix4x4 combinedTransform = GetConcatenatedLocalTransform(currentNode); + AZStd::unordered_map boneLookup; + GetAllBones(scene, boneLookup); + + auto boneIterator = boneLookup.find(currentNode->mName.C_Str()); + const bool isBone = boneIterator != boneLookup.end(); + + aiMatrix4x4 combinedTransform; + + if (isBone) + { + auto parentNode = currentNode->mParent; + + aiMatrix4x4 offsetMatrix = boneIterator->second->mOffsetMatrix; + aiMatrix4x4 parentOffset {}; + + auto parentBoneIterator = boneLookup.find(parentNode->mName.C_Str()); + + if (parentNode && parentBoneIterator != boneLookup.end()) + { + const auto& parentBone = parentBoneIterator->second; + + parentOffset = parentBone->mOffsetMatrix; + } + + auto inverseOffset = offsetMatrix; + inverseOffset.Inverse(); + + combinedTransform = parentOffset * inverseOffset; + } + else + { + combinedTransform = GetConcatenatedLocalTransform(currentNode); + } DataTypes::MatrixType localTransform = AssImpSDKWrapper::AssImpTypeConverter::ToTransform(combinedTransform); - + context.m_sourceSceneSystem.SwapTransformForUpAxis(localTransform); context.m_sourceSceneSystem.ConvertUnit(localTransform); @@ -105,9 +152,7 @@ namespace AZ } else { - bool addedData = context.m_scene.GetGraph().SetContent( - context.m_currentGraphPosition, - transformData); + bool addedData = context.m_scene.GetGraph().SetContent(context.m_currentGraphPosition, transformData); AZ_Error(SceneAPI::Utilities::ErrorWindow, addedData, "Failed to add node data"); return addedData ? Events::ProcessingResult::Success : Events::ProcessingResult::Failure; diff --git a/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp b/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp index 791af4bf68..9186a2fb7a 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp +++ b/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp @@ -69,13 +69,14 @@ namespace AZ // aiProcess_JoinIdenticalVertices is not enabled because O3DE has a mesh optimizer that also does this, // this flag is disabled to keep AssImp output similar to FBX SDK to reduce downstream bugs for the initial AssImp release. // There's currently a minimum of properties and flags set to maximize compatibility with the existing node graph. + + // aiProcess_LimitBoneWeights is not enabled because it will remove bones which are not associated with a mesh. + // This results in the loss of the offset matrix data for nodes without a mesh which is required for the Transform Importer. m_importer.SetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, false); m_importer.SetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, false); m_sceneFileName = fileName; m_assImpScene = m_importer.ReadFile(fileName, aiProcess_Triangulate //Triangulates all faces of all meshes - | aiProcess_LimitBoneWeights //Limits the number of bones that can affect a vertex to a maximum value - //dropping the least important and re-normalizing | aiProcess_GenNormals); //Generate normals for meshes #if AZ_TRAIT_COMPILER_SUPPORT_CSIGNAL From 0d5247be345493fb699e54dc0eaad41af35fa87b Mon Sep 17 00:00:00 2001 From: moudgils Date: Tue, 1 Jun 2021 09:58:45 -0700 Subject: [PATCH 023/116] Fix metal shader pipeline crashes for LuminanceHistogramGenerator and MorphTargetCS due to the use of atomic operations with typed buffers. Switching them to use Structured buffers. Plus misc cleanup --- .../Common/Assets/Shaders/MorphTargets/MorphTargetCS.shader | 4 +--- .../Common/Assets/Shaders/MorphTargets/MorphTargetSRG.azsli | 2 +- .../Assets/Shaders/PostProcessing/LuminanceHeatmap.azsl | 4 ++-- .../Shaders/PostProcessing/LuminanceHistogramGenerator.azsl | 2 +- .../PostProcessing/LuminanceHistogramGenerator.shader | 4 +--- .../Assets/Shaders/SkinnedMesh/LinearSkinningPassSRG.azsli | 2 +- .../PostProcessing/LuminanceHistogramGeneratorPass.cpp | 2 +- .../Source/SkinnedMesh/SkinnedMeshOutputStreamManager.cpp | 4 ++-- .../RHI/Code/Include/Atom/RHI/ShaderResourceGroupData.h | 1 - Gems/Atom/RHI/DX12/Code/Source/RHI/CommandList.h | 6 ++++++ 10 files changed, 16 insertions(+), 15 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/MorphTargets/MorphTargetCS.shader b/Gems/Atom/Feature/Common/Assets/Shaders/MorphTargets/MorphTargetCS.shader index 95ffc36a11..08b1e7c298 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/MorphTargets/MorphTargetCS.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/MorphTargets/MorphTargetCS.shader @@ -10,7 +10,5 @@ "type": "Compute" } ] - }, - "DisabledRHIBackends": ["metal"] - + } } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/MorphTargets/MorphTargetSRG.azsli b/Gems/Atom/Feature/Common/Assets/Shaders/MorphTargets/MorphTargetSRG.azsli index 7ec5b43368..171e803c2c 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/MorphTargets/MorphTargetSRG.azsli +++ b/Gems/Atom/Feature/Common/Assets/Shaders/MorphTargets/MorphTargetSRG.azsli @@ -16,7 +16,7 @@ ShaderResourceGroup MorphTargetPassSrg : SRG_PerPass { - RWBuffer m_accumulatedDeltas; + RWStruturedBuffer m_accumulatedDeltas; } // This class represents the data that is passed to the morph target compute shader of an individual delta diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHeatmap.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHeatmap.azsl index df92e36f9a..4559b6c9ef 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHeatmap.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHeatmap.azsl @@ -1,4 +1,4 @@ -/* + /* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * @@ -37,7 +37,7 @@ ShaderResourceGroup PassSrg : SRG_PerPass Texture2D m_sceneLuminance; // This should be of size NUM_HISTOGRAM_BINS. - Buffer m_histogram; + StructuredBuffer m_histogram; Sampler LinearSampler { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.azsl index 05cc870eea..9d01a12fd6 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.azsl @@ -20,7 +20,7 @@ ShaderResourceGroup PassSrg : SRG_PerPass { Texture2D m_inputTexture; - RWBuffer m_outputTexture; + RWStructuredBuffer m_outputTexture; } groupshared uint shared_histogramBins[NUM_HISTOGRAM_BINS]; diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.shader index 566144bab8..f3dd11e11a 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.shader @@ -12,7 +12,5 @@ "type": "Compute" } ] - }, - "DisabledRHIBackends": ["metal"] - + } } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/SkinnedMesh/LinearSkinningPassSRG.azsli b/Gems/Atom/Feature/Common/Assets/Shaders/SkinnedMesh/LinearSkinningPassSRG.azsli index 5a9e44bade..e5407d2d9e 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/SkinnedMesh/LinearSkinningPassSRG.azsli +++ b/Gems/Atom/Feature/Common/Assets/Shaders/SkinnedMesh/LinearSkinningPassSRG.azsli @@ -16,7 +16,7 @@ ShaderResourceGroup PassSrg : SRG_PerPass { - RWBuffer m_skinnedMeshOutputStream; + RWStructuredBuffer m_skinnedMeshOutputStream; } ShaderResourceGroup InstanceSrg : SRG_PerDraw diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/LuminanceHistogramGeneratorPass.cpp b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/LuminanceHistogramGeneratorPass.cpp index 758c21bc4e..a3c494dee9 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/LuminanceHistogramGeneratorPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/LuminanceHistogramGeneratorPass.cpp @@ -72,7 +72,7 @@ namespace AZ desc.m_bufferName = AZStd::string::format("LuminanceHistogramBuffer_%s", uuidString.c_str()); desc.m_elementSize = sizeof(uint32_t); desc.m_byteCount = NumHistogramBins * sizeof(uint32_t); - desc.m_elementFormat = RHI::Format::R32_UINT; + desc.m_elementFormat = RHI::Format::Unknown; m_histogram = RPI::BufferSystemInterface::Get()->CreateBufferFromCommonPool(desc); AZ_Assert(m_histogram != nullptr, "Unable to allocate buffer"); } diff --git a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshOutputStreamManager.cpp b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshOutputStreamManager.cpp index 1cb782d8b1..1b14611e84 100644 --- a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshOutputStreamManager.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshOutputStreamManager.cpp @@ -67,8 +67,8 @@ namespace AZ creator.SetBuffer(nullptr, 0, bufferDescriptor); RHI::BufferViewDescriptor viewDescriptor; - viewDescriptor.m_elementFormat = RHI::Format::R32_FLOAT; - viewDescriptor.m_elementSize = RHI::GetFormatSize(viewDescriptor.m_elementFormat); + viewDescriptor.m_elementFormat = RHI::Format::Unknown; + viewDescriptor.m_elementSize = sizeof(float); viewDescriptor.m_elementCount = aznumeric_cast(m_sizeInBytes) / viewDescriptor.m_elementSize; viewDescriptor.m_elementOffset = 0; creator.SetBufferViewDescriptor(viewDescriptor); diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/ShaderResourceGroupData.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/ShaderResourceGroupData.h index ce2c6c77ec..afcab28a1d 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/ShaderResourceGroupData.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/ShaderResourceGroupData.h @@ -410,7 +410,6 @@ namespace AZ // For any other type the buffer view's element size should match the stride. if (shaderInputBuffer.m_strideSize != bufferViewDescriptor.m_elementSize) { - // [GFX TODO][ATOM-5735][AZSL] ByteAddressBuffer shader input is setting a stride of 16 instead of 4 AZ_Error("ShaderResourceGroupData", false, "Buffer Input '%s[%d]': Does not match expected stride size %d", shaderInputBuffer.m_name.GetCStr(), arrayIndex, bufferViewDescriptor.m_elementSize); return false; diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandList.h b/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandList.h index a6fe57f6d8..6f09ea1d5f 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandList.h +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandList.h @@ -271,6 +271,12 @@ namespace AZ ShaderResourceBindings& bindings = GetShaderResourceBindingsByPipelineType(pipelineType); const PipelineState* pipelineState = static_cast(item.m_pipelineState); + if(!pipelineState) + { + AZ_Assert(false, "Pipeline state not provided"); + return false; + } + bool updatePipelineState = m_state.m_pipelineState != pipelineState; // The pipeline state gets set first. if (updatePipelineState) From 485a45d3c2a12bd7194210939ca75a58f9640bd2 Mon Sep 17 00:00:00 2001 From: igarri Date: Wed, 2 Jun 2021 15:32:03 +0100 Subject: [PATCH 024/116] Made some corrections --- .../AssetBrowser/AssetBrowserFilterModel.cpp | 11 +-- .../AssetBrowser/AssetBrowserTableModel.cpp | 10 ++- .../Views/AssetBrowserTableView.cpp | 9 +- .../AzAssetBrowser/AzAssetBrowserWindow.cpp | 83 ++++++++++--------- 4 files changed, 60 insertions(+), 53 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp index 2660b660e4..adb4ae66c4 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp @@ -26,7 +26,6 @@ AZ_POP_DISABLE_WARNING AZ_CVAR( bool, ed_useNewAssetBrowserTableView, false, nullptr, AZ::ConsoleFunctorFlags::Null, "Use the new AssetBrowser TableView for searching assets."); -#pragma optimize("", off) namespace AzToolsFramework { namespace AssetBrowser @@ -139,7 +138,7 @@ namespace AzToolsFramework { const auto& subFilters = compFilter->GetSubFilters(); - const auto compositeFilterIterator = AZStd::find_if(subFilters.begin(), subFilters.end(), [subFilters](FilterConstType filter) -> bool + const auto compositeFilterIterator = AZStd::find_if(subFilters.cbegin(), subFilters.cend(), [subFilters](FilterConstType filter) -> bool { const auto assetTypeFilter = qobject_cast >(filter); return !assetTypeFilter.isNull(); @@ -150,7 +149,7 @@ namespace AzToolsFramework m_assetTypeFilter = qobject_cast >(*compositeFilterIterator); } - const auto compStringFilterIter = AZStd::find_if(subFilters.begin(), subFilters.end(), [](FilterConstType filter) -> bool + const auto compStringFilterIter = AZStd::find_if(subFilters.cbegin(), subFilters.cend(), [](FilterConstType filter) -> bool { //The real StringFilter is really a CompositeFilter with just one StringFilter in its subfilter list //To know if it is actually a StringFilter we have to get that subfilter and check if it is a Stringfilter. @@ -164,7 +163,7 @@ namespace AzToolsFramework auto strFilter = qobject_cast>(filt); return !strFilter.isNull(); }; - const auto stringSubfliterConstIter = AZStd::find_if(stringSubfilters.begin(), stringSubfilters.end(), canBeCasted); + const auto stringSubfliterConstIter = AZStd::find_if(stringSubfilters.cbegin(), stringSubfilters.cend(), canBeCasted); //A Composite StringFilter will only have just one subfilter and nothing more. if (stringSubfliterConstIter != stringSubfilters.end() && stringSubfilters.size() == 1) @@ -188,8 +187,7 @@ namespace AzToolsFramework } invalidateFilter(); Q_EMIT filterChanged(); - bool isNullAB = m_stringFilter.isNull(); - emit stringFilterPopulated(!isNullAB); + emit stringFilterPopulated(!m_stringFilter.isNull()); } void AssetBrowserFilterModel::filterUpdatedSlot() @@ -209,6 +207,5 @@ namespace AzToolsFramework } // namespace AssetBrowser } // namespace AzToolsFramework// namespace AssetBrowser -#pragma optimize("", on) #include "AssetBrowser/moc_AssetBrowserFilterModel.cpp" diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp index 40f8318a2d..70d66f4e1f 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp @@ -9,8 +9,8 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ -#include #include +#include #include namespace AzToolsFramework @@ -26,7 +26,9 @@ namespace AzToolsFramework void AssetBrowserTableModel::setSourceModel(QAbstractItemModel* sourceModel) { m_filterModel = qobject_cast(sourceModel); - AZ_Assert(m_filterModel, "Error in AssetBrowserTableModel initialization, class expects source model to be an AssetBrowserFilterModel."); + AZ_Assert( + m_filterModel, + "Error in AssetBrowserTableModel initialization, class expects source model to be an AssetBrowserFilterModel."); QSortFilterProxyModel::setSourceModel(sourceModel); } @@ -86,7 +88,8 @@ namespace AzToolsFramework return !parent.isValid() ? m_indexMap.size() : 0; } - int AssetBrowserTableModel::BuildTableModelMap(const QAbstractItemModel* model, const QModelIndex& parent /*= QModelIndex()*/, int row /*= 0*/) + int AssetBrowserTableModel::BuildTableModelMap( + const QAbstractItemModel* model, const QModelIndex& parent /*= QModelIndex()*/, int row /*= 0*/) { int rows = model ? model->rowCount(parent) : 0; for (int i = 0; i < rows; ++i) @@ -134,7 +137,6 @@ namespace AzToolsFramework } BuildTableModelMap(sourceModel()); emit layoutChanged(); - } } // namespace AssetBrowser } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp index f7128cb504..894bbd8700 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp @@ -37,7 +37,6 @@ AZ_PUSH_DISABLE_WARNING( #include #include AZ_POP_DISABLE_WARNING -#pragma optimize("", off) namespace AzToolsFramework { namespace AssetBrowser @@ -128,7 +127,8 @@ namespace AzToolsFramework QTableView::rowsAboutToBeRemoved(parent, start, end); } - void AssetBrowserTableView::layoutChangedSlot([[maybe_unused]] const QList& parents,[[maybe_unused]] QAbstractItemModel::LayoutChangeHint hint) + void AssetBrowserTableView::layoutChangedSlot( + [[maybe_unused]] const QList& parents, [[maybe_unused]] QAbstractItemModel::LayoutChangeHint hint) { scrollToTop(); } @@ -159,7 +159,6 @@ namespace AzToolsFramework void AssetBrowserTableView::OnContextMenu([[maybe_unused]] const QPoint& point) { - const auto& selectedAssets = GetSelectedAssets(); if (selectedAssets.size() != 1) { @@ -167,7 +166,8 @@ namespace AzToolsFramework } QMenu menu(this); - AssetBrowserInteractionNotificationBus::Broadcast(&AssetBrowserInteractionNotificationBus::Events::AddContextMenuActions, this, &menu, selectedAssets); + AssetBrowserInteractionNotificationBus::Broadcast( + &AssetBrowserInteractionNotificationBus::Events::AddContextMenuActions, this, &menu, selectedAssets); if (!menu.isEmpty()) { menu.exec(QCursor::pos()); @@ -175,5 +175,4 @@ namespace AzToolsFramework } } // namespace AssetBrowser } // namespace AzToolsFramework -#pragma optimize("", on) #include "AssetBrowser/Views/moc_AssetBrowserTableView.cpp" diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp index e722d6d03e..90b597e273 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp @@ -1,26 +1,26 @@ /* -* 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. -* -*/ + * 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 "EditorDefs.h" #include "AzAssetBrowserWindow.h" // AzToolsFramework +#include #include #include +#include #include #include -#include -#include // AzQtComponents #include @@ -35,7 +35,6 @@ AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING AZ_CVAR_EXTERNED(bool, ed_useNewAssetBrowserTableView); - class ListenerForShowAssetEditorEvent : public QObject , private AzToolsFramework::EditorEvents::Bus::Handler @@ -113,22 +112,29 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) m_ui->m_assetBrowserTreeViewWidget->setModel(m_filterModel.data()); - connect(m_ui->m_searchWidget->GetFilter().data(), &AssetBrowserEntryFilter::updatedSignal, - m_filterModel.data(), &AssetBrowserFilterModel::filterUpdatedSlot); - connect(m_filterModel.data(), &AssetBrowserFilterModel::filterChanged, this, [this]() - { - const bool hasFilter = !m_ui->m_searchWidget->GetFilterString().isEmpty(); - const bool selectFirstFilteredIndex = false; - m_ui->m_assetBrowserTreeViewWidget->UpdateAfterFilter(hasFilter, selectFirstFilteredIndex); - }); + connect( + m_ui->m_searchWidget->GetFilter().data(), &AssetBrowserEntryFilter::updatedSignal, m_filterModel.data(), + &AssetBrowserFilterModel::filterUpdatedSlot); + connect( + m_filterModel.data(), &AssetBrowserFilterModel::filterChanged, this, + [this]() + { + const bool hasFilter = !m_ui->m_searchWidget->GetFilterString().isEmpty(); + const bool selectFirstFilteredIndex = false; + m_ui->m_assetBrowserTreeViewWidget->UpdateAfterFilter(hasFilter, selectFirstFilteredIndex); + }); - connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::selectionChangedSignal, - this, &AzAssetBrowserWindow::SelectionChangedSlot); + connect( + m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::selectionChangedSignal, this, + &AzAssetBrowserWindow::SelectionChangedSlot); connect(m_ui->m_assetBrowserTreeViewWidget, &QAbstractItemView::doubleClicked, this, &AzAssetBrowserWindow::DoubleClickedItem); - connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::ClearStringFilter, m_ui->m_searchWidget, &SearchWidget::ClearStringFilter); - connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::ClearTypeFilter, m_ui->m_searchWidget, &SearchWidget::ClearTypeFilter); + connect( + m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::ClearStringFilter, m_ui->m_searchWidget, + &SearchWidget::ClearStringFilter); + connect( + m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::ClearTypeFilter, m_ui->m_searchWidget, &SearchWidget::ClearTypeFilter); m_ui->m_assetBrowserTreeViewWidget->SetName("AssetBrowserTreeView_main"); } @@ -199,18 +205,21 @@ void AzAssetBrowserWindow::SelectAsset(const QString& assetPath) // interferes with the update from the select and expand, and if you don't // queue it, the tree doesn't expand reliably. - QTimer::singleShot(0, this, [this, filteredIndex = index] { - // the treeview has a filter model so we have to backwards go from that - QModelIndex index = m_filterModel->mapFromSource(filteredIndex); + QTimer::singleShot( + 0, this, + [this, filteredIndex = index] + { + // the treeview has a filter model so we have to backwards go from that + QModelIndex index = m_filterModel->mapFromSource(filteredIndex); - QTreeView* treeView = m_ui->m_assetBrowserTreeViewWidget; - ExpandTreeToIndex(treeView, index); + QTreeView* treeView = m_ui->m_assetBrowserTreeViewWidget; + ExpandTreeToIndex(treeView, index); - treeView->scrollTo(index); - treeView->setCurrentIndex(index); + treeView->scrollTo(index); + treeView->setCurrentIndex(index); - treeView->selectionModel()->select(index, QItemSelectionModel::ClearAndSelect); - }); + treeView->selectionModel()->select(index, QItemSelectionModel::ClearAndSelect); + }); } } @@ -243,11 +252,12 @@ void AzAssetBrowserWindow::DoubleClickedItem([[maybe_unused]] const QModelIndex& assetIdToOpen = AZ::Data::AssetId(sourceEntry->GetSourceUuid(), 0); fullFilePath = entry->GetFullPath(); } - + bool handledBySomeone = false; if (assetIdToOpen.IsValid()) { - AssetBrowserInteractionNotificationBus::Broadcast(&AssetBrowserInteractionNotifications::OpenAssetInAssociatedEditor, assetIdToOpen, handledBySomeone); + AssetBrowserInteractionNotificationBus::Broadcast( + &AssetBrowserInteractionNotifications::OpenAssetInAssociatedEditor, assetIdToOpen, handledBySomeone); } if (!handledBySomeone && !fullFilePath.empty()) @@ -255,7 +265,6 @@ void AzAssetBrowserWindow::DoubleClickedItem([[maybe_unused]] const QModelIndex& AzAssetBrowserRequestHandler::OpenWithOS(fullFilePath); } } - } void AzAssetBrowserWindow::DoubleClickedItemTableModel([[maybe_unused]] const QModelIndex& element) From eb67b6b452a768c10e2a905711e2ab1710bcbc4a Mon Sep 17 00:00:00 2001 From: igarri Date: Thu, 3 Jun 2021 13:36:47 +0100 Subject: [PATCH 025/116] Adding namespace aliases and API comments --- .../Views/AssetBrowserTableView.h | 2 +- .../AzAssetBrowser/AzAssetBrowserWindow.cpp | 71 +++++++++---------- 2 files changed, 36 insertions(+), 37 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h index 65f97d1a6d..15bc95f13c 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h @@ -32,7 +32,7 @@ namespace AzToolsFramework class AssetBrowserFilterModel; class EntryDelegate; - class AssetBrowserTableView + class AssetBrowserTableView //! Table view that displays the asset browser entries in a list. : public QTableView , public AssetBrowserViewRequestBus::Handler , public AssetBrowserComponentNotificationBus::Handler diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp index 90b597e273..481cc35635 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp @@ -74,8 +74,9 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) m_ui->setupUi(this); m_ui->m_searchWidget->Setup(true, true); - using namespace AzToolsFramework::AssetBrowser; - AssetBrowserComponentRequestBus::BroadcastResult(m_assetBrowserModel, &AssetBrowserComponentRequests::GetAssetBrowserModel); + namespace AB = AzToolsFramework::AssetBrowser; + + AB::AssetBrowserComponentRequestBus::BroadcastResult(m_assetBrowserModel, &AB::AssetBrowserComponentRequests::GetAssetBrowserModel); AZ_Assert(m_assetBrowserModel, "Failed to get filebrowser model"); m_filterModel->setSourceModel(m_assetBrowserModel); m_filterModel->SetFilter(m_ui->m_searchWidget->GetFilter()); @@ -89,34 +90,34 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) m_tableModel->setSourceModel(m_filterModel.data()); m_ui->m_assetBrowserTableViewWidget->setModel(m_tableModel.data()); connect( - m_filterModel.data(), &AssetBrowserFilterModel::filterChanged, m_tableModel.data(), - &AssetBrowserTableModel::UpdateTableModelMaps); + m_filterModel.data(), &AB::AssetBrowserFilterModel::filterChanged, m_tableModel.data(), + &AB::AssetBrowserTableModel::UpdateTableModelMaps); connect( - m_ui->m_assetBrowserTableViewWidget, &AssetBrowserTableView::selectionChangedSignal, this, + m_ui->m_assetBrowserTableViewWidget, &AB::AssetBrowserTableView::selectionChangedSignal, this, &AzAssetBrowserWindow::SelectionChangedSlot); connect( m_ui->m_assetBrowserTableViewWidget, &QAbstractItemView::doubleClicked, this, &AzAssetBrowserWindow::DoubleClickedItemTableModel); connect( - m_ui->m_assetBrowserTableViewWidget, &AssetBrowserTableView::ClearStringFilter, m_ui->m_searchWidget, - &SearchWidget::ClearStringFilter); + m_ui->m_assetBrowserTableViewWidget, &AB::AssetBrowserTableView::ClearStringFilter, m_ui->m_searchWidget, + &AB::SearchWidget::ClearStringFilter); connect( - m_ui->m_assetBrowserTableViewWidget, &AssetBrowserTableView::ClearTypeFilter, m_ui->m_searchWidget, - &SearchWidget::ClearTypeFilter); + m_ui->m_assetBrowserTableViewWidget, &AB::AssetBrowserTableView::ClearTypeFilter, m_ui->m_searchWidget, + &AB::SearchWidget::ClearTypeFilter); m_ui->m_assetBrowserTableViewWidget->SetName("AssetBrowserTableView_main"); - connect(m_filterModel.data(), &AssetBrowserFilterModel::stringFilterPopulated, this, &AzAssetBrowserWindow::SwitchDisplayView); + connect(m_filterModel.data(), &AB::AssetBrowserFilterModel::stringFilterPopulated, this, &AzAssetBrowserWindow::SwitchDisplayView); connect(m_ui->m_viewSwitcherCheckBox, &QCheckBox::stateChanged, this, &AzAssetBrowserWindow::LockToDefaultView); } m_ui->m_assetBrowserTreeViewWidget->setModel(m_filterModel.data()); connect( - m_ui->m_searchWidget->GetFilter().data(), &AssetBrowserEntryFilter::updatedSignal, m_filterModel.data(), - &AssetBrowserFilterModel::filterUpdatedSlot); + m_ui->m_searchWidget->GetFilter().data(), &AB::AssetBrowserEntryFilter::updatedSignal, m_filterModel.data(), + &AB::AssetBrowserFilterModel::filterUpdatedSlot); connect( - m_filterModel.data(), &AssetBrowserFilterModel::filterChanged, this, + m_filterModel.data(), &AB::AssetBrowserFilterModel::filterChanged, this, [this]() { const bool hasFilter = !m_ui->m_searchWidget->GetFilterString().isEmpty(); @@ -125,16 +126,17 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) }); connect( - m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::selectionChangedSignal, this, + m_ui->m_assetBrowserTreeViewWidget, &AB::AssetBrowserTreeView::selectionChangedSignal, this, &AzAssetBrowserWindow::SelectionChangedSlot); connect(m_ui->m_assetBrowserTreeViewWidget, &QAbstractItemView::doubleClicked, this, &AzAssetBrowserWindow::DoubleClickedItem); connect( - m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::ClearStringFilter, m_ui->m_searchWidget, - &SearchWidget::ClearStringFilter); + m_ui->m_assetBrowserTreeViewWidget, &AB::AssetBrowserTreeView::ClearStringFilter, m_ui->m_searchWidget, + &AB::SearchWidget::ClearStringFilter); connect( - m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::ClearTypeFilter, m_ui->m_searchWidget, &SearchWidget::ClearTypeFilter); + m_ui->m_assetBrowserTreeViewWidget, &AB::AssetBrowserTreeView::ClearTypeFilter, m_ui->m_searchWidget, + &AB::SearchWidget::ClearTypeFilter); m_ui->m_assetBrowserTreeViewWidget->SetName("AssetBrowserTreeView_main"); } @@ -192,8 +194,6 @@ static void ExpandTreeToIndex(QTreeView* treeView, const QModelIndex& index) void AzAssetBrowserWindow::SelectAsset(const QString& assetPath) { - using namespace AzToolsFramework::AssetBrowser; - QModelIndex index = m_assetBrowserModel->findIndex(assetPath); if (index.isValid()) { @@ -232,21 +232,21 @@ void AzAssetBrowserWindow::SelectionChangedSlot(const QItemSelection& /*selected // just becuase on some OS clicking once is activation. void AzAssetBrowserWindow::DoubleClickedItem([[maybe_unused]] const QModelIndex& element) { - using namespace AzToolsFramework; - using namespace AzToolsFramework::AssetBrowser; + namespace AB = AzToolsFramework::AssetBrowser; + // assumption: Double clicking an item selects it before telling us we double clicked it. const auto& selectedAssets = m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets(); - for (const AssetBrowserEntry* entry : selectedAssets) + for (const AB::AssetBrowserEntry* entry : selectedAssets) { AZ::Data::AssetId assetIdToOpen; AZStd::string fullFilePath; - if (const ProductAssetBrowserEntry* productEntry = azrtti_cast(entry)) + if (const AB::ProductAssetBrowserEntry* productEntry = azrtti_cast(entry)) { assetIdToOpen = productEntry->GetAssetId(); fullFilePath = entry->GetFullPath(); } - else if (const SourceAssetBrowserEntry* sourceEntry = azrtti_cast(entry)) + else if (const AB::SourceAssetBrowserEntry* sourceEntry = azrtti_cast(entry)) { // manufacture an empty AssetID with the source's UUID assetIdToOpen = AZ::Data::AssetId(sourceEntry->GetSourceUuid(), 0); @@ -256,8 +256,8 @@ void AzAssetBrowserWindow::DoubleClickedItem([[maybe_unused]] const QModelIndex& bool handledBySomeone = false; if (assetIdToOpen.IsValid()) { - AssetBrowserInteractionNotificationBus::Broadcast( - &AssetBrowserInteractionNotifications::OpenAssetInAssociatedEditor, assetIdToOpen, handledBySomeone); + AB::AssetBrowserInteractionNotificationBus::Broadcast( + &AB::AssetBrowserInteractionNotifications::OpenAssetInAssociatedEditor, assetIdToOpen, handledBySomeone); } if (!handledBySomeone && !fullFilePath.empty()) @@ -269,21 +269,20 @@ void AzAssetBrowserWindow::DoubleClickedItem([[maybe_unused]] const QModelIndex& void AzAssetBrowserWindow::DoubleClickedItemTableModel([[maybe_unused]] const QModelIndex& element) { - using namespace AzToolsFramework; - using namespace AzToolsFramework::AssetBrowser; + namespace AB = AzToolsFramework::AssetBrowser; // assumption: Double clicking an item selects it before telling us we double clicked it. const auto& selectedAssets = m_ui->m_assetBrowserTableViewWidget->GetSelectedAssets(); - for (const AssetBrowserEntry* entry : selectedAssets) + for (const AB::AssetBrowserEntry* entry : selectedAssets) { AZ::Data::AssetId assetIdToOpen; AZStd::string fullFilePath; - if (const ProductAssetBrowserEntry* productEntry = azrtti_cast(entry)) + if (const AB::ProductAssetBrowserEntry* productEntry = azrtti_cast(entry)) { assetIdToOpen = productEntry->GetAssetId(); fullFilePath = entry->GetFullPath(); } - else if (const SourceAssetBrowserEntry* sourceEntry = azrtti_cast(entry)) + else if (const AB::SourceAssetBrowserEntry* sourceEntry = azrtti_cast(entry)) { // manufacture an empty AssetID with the source's UUID assetIdToOpen = AZ::Data::AssetId(sourceEntry->GetSourceUuid(), 0); @@ -293,8 +292,8 @@ void AzAssetBrowserWindow::DoubleClickedItemTableModel([[maybe_unused]] const QM bool handledBySomeone = false; if (assetIdToOpen.IsValid()) { - AssetBrowserInteractionNotificationBus::Broadcast( - &AssetBrowserInteractionNotifications::OpenAssetInAssociatedEditor, assetIdToOpen, handledBySomeone); + AB::AssetBrowserInteractionNotificationBus::Broadcast( + &AB::AssetBrowserInteractionNotifications::OpenAssetInAssociatedEditor, assetIdToOpen, handledBySomeone); } if (!handledBySomeone && !fullFilePath.empty()) @@ -312,12 +311,12 @@ void AzAssetBrowserWindow::SwitchDisplayView(bool state) void AzAssetBrowserWindow::LockToDefaultView(bool state) { - using namespace AzToolsFramework; - using namespace AzToolsFramework::AssetBrowser; + using AzToolsFramework::AssetBrowser::AssetBrowserFilterModel; SwitchDisplayView(!state); if (state == true) { - disconnect(m_filterModel.data(), &AssetBrowserFilterModel::stringFilterPopulated, this, &AzAssetBrowserWindow::SwitchDisplayView); + disconnect( + m_filterModel.data(), &AssetBrowserFilterModel::stringFilterPopulated, this, &AzAssetBrowserWindow::SwitchDisplayView); } else { From 0e4a632417625d1dceb28a2d62d14a0aa8d277e9 Mon Sep 17 00:00:00 2001 From: moudgils Date: Thu, 3 Jun 2021 22:45:50 -0700 Subject: [PATCH 026/116] Add support for re-binding SRG entries if the drawItem has a new pso which changes how a srg is used in the shader. Also optimized api usage to use single call for UseResource and for setting stream buffers. --- .../Shaders/MorphTargets/MorphTargetSRG.azsli | 2 +- .../Metal/Code/Source/RHI/ArgumentBuffer.cpp | 133 +++++++++--------- .../Metal/Code/Source/RHI/ArgumentBuffer.h | 15 +- .../RHI/Metal/Code/Source/RHI/CommandList.cpp | 56 ++++++-- .../RHI/Metal/Code/Source/RHI/CommandList.h | 1 + .../Metal/Code/Source/RHI/PipelineLayout.cpp | 7 + .../Metal/Code/Source/RHI/PipelineLayout.h | 6 + 7 files changed, 134 insertions(+), 86 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/MorphTargets/MorphTargetSRG.azsli b/Gems/Atom/Feature/Common/Assets/Shaders/MorphTargets/MorphTargetSRG.azsli index 171e803c2c..83193c8559 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/MorphTargets/MorphTargetSRG.azsli +++ b/Gems/Atom/Feature/Common/Assets/Shaders/MorphTargets/MorphTargetSRG.azsli @@ -16,7 +16,7 @@ ShaderResourceGroup MorphTargetPassSrg : SRG_PerPass { - RWStruturedBuffer m_accumulatedDeltas; + RWStructuredBuffer m_accumulatedDeltas; } // This class represents the data that is passed to the morph target compute shader of an individual delta diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp index 6ffd15e0bc..1e2edc6520 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp @@ -386,6 +386,11 @@ namespace AZ void ArgumentBuffer::AddUntrackedResourcesToEncoder(id commandEncoder, const ShaderResourceGroupVisibility& srgResourcesVisInfo) const { + + ComputeResourcesToMakeResidentMap resourcesToMakeResidentCompute; + GraphicsResourcesToMakeResidentMap resourcesToMakeResidentGraphics; + + //Cache the constant buffer associated with a srg if (m_constantBufferSize) { uint8_t numBitsSet = RHI::CountBitsSet(static_cast(srgResourcesVisInfo.m_constantDataStageMask)); @@ -393,28 +398,19 @@ namespace AZ { if(RHI::CheckBitsAny(srgResourcesVisInfo.m_constantDataStageMask, RHI::ShaderStageMask::Compute)) { - [static_cast>(commandEncoder) useResource:m_constantBuffer.GetGpuAddress>() usage:MTLResourceUsageRead]; + resourcesToMakeResidentCompute[MTLResourceUsageRead].m_resourceArray[resourcesToMakeResidentCompute[MTLResourceUsageRead].m_resourceArrayLen++] = m_constantBuffer.GetGpuAddress>(); } else { MTLRenderStages mtlRenderStages = GetRenderStages(srgResourcesVisInfo.m_constantDataStageMask); - [static_cast>(commandEncoder) useResource:m_constantBuffer.GetGpuAddress>() - usage:MTLResourceUsageRead - stages:mtlRenderStages]; + AZStd::pair key = AZStd::make_pair(MTLResourceUsageRead, mtlRenderStages); + resourcesToMakeResidentGraphics[key].m_resourceArray[resourcesToMakeResidentGraphics[key].m_resourceArrayLen++] = m_constantBuffer.GetGpuAddress>(); } - } } - ApplyUseResource(commandEncoder, m_resourceBindings, srgResourcesVisInfo); - } - - void ArgumentBuffer::ApplyUseResource(id encoder, - const ResourceBindingsMap& resourceMap, - const ShaderResourceGroupVisibility& srgResourcesVisInfo) const - { - - CommandEncoderType encodeType = CommandEncoderType::Invalid; - for (const auto& it : resourceMap) + + //Cach all the resources within a srg that are used by the shader based on the visibility information + for (const auto& it : m_resourceBindings) { //Extract the visibility mask for the give resource auto visMaskIt = srgResourcesVisInfo.m_resourcesStageMask.find(it.first); @@ -426,75 +422,50 @@ namespace AZ { if(RHI::CheckBitsAny(visMaskIt->second, RHI::ShaderStageMask::Compute)) { - //Call UseResource on all resources for Compute stage - ApplyUseResourceToCompute(encoder, it.second); - encodeType = CommandEncoderType::Compute; + ApplyUseResourceToCompute(commandEncoder, it.second, resourcesToMakeResidentCompute); } else { - //Call UseResource on all resources for Vertex and Fragment stages AZ_Assert(RHI::CheckBitsAny(visMaskIt->second, RHI::ShaderStageMask::Vertex) || RHI::CheckBitsAny(visMaskIt->second, RHI::ShaderStageMask::Fragment), "The visibility mask %i is not set for Vertex or fragment stage", visMaskIt->second); - ApplyUseResourceToGraphic(encoder, visMaskIt->second, it.second); - encodeType = CommandEncoderType::Render; + ApplyUseResourceToGraphic(commandEncoder, visMaskIt->second, it.second, resourcesToMakeResidentGraphics); } } } - } - - void ArgumentBuffer::ApplyUseResourceToCompute(id encoder, const ResourceBindingsSet& resourceBindingDataSet) const - { - for (const auto& resourceBindingData : resourceBindingDataSet) - { - ResourceType rescType = resourceBindingData.m_resourcPtr->GetResourceType(); - switch(rescType) - { - case ResourceType::MtlTextureType: - { - MTLResourceUsage resourceUsage = GetImageResourceUsage(resourceBindingData.m_imageAccess); - [static_cast>(encoder) useResource:resourceBindingData.m_resourcPtr->GetGpuAddress>() usage:resourceUsage]; - - break; - } - case ResourceType::MtlBufferType: - { - MTLResourceUsage resourceUsage = GetBufferResourceUsage(resourceBindingData.m_bufferAccess); - [static_cast>(encoder) useResource:resourceBindingData.m_resourcPtr->GetGpuAddress>() usage:resourceUsage]; - - break; - } - default: - { - AZ_Assert(false, "Undefined Resource type"); - } - } - } - } - - void ArgumentBuffer::ApplyUseResourceToGraphic(id encoder, RHI::ShaderStageMask visShaderMask, const ResourceBindingsSet& resourceBindingDataSet) const - { - MTLRenderStages mtlRenderStages = GetRenderStages(visShaderMask); + //Call UseResource on all resources for Compute stage + for (const auto& key : resourcesToMakeResidentCompute) + { + [static_cast>(commandEncoder) useResources: key.second.m_resourceArray.data() + count: key.second.m_resourceArrayLen + usage: key.first]; + } + + //Call UseResource on all resources for Vertex and Fragment stages + for (const auto& key : resourcesToMakeResidentGraphics) + { + [static_cast>(commandEncoder) useResources: key.second.m_resourceArray.data() + count: key.second.m_resourceArrayLen + usage: key.first.first + stages: key.first.second]; + } + } + + void ArgumentBuffer::ApplyUseResourceToCompute(id encoder, const ResourceBindingsSet& resourceBindingDataSet, ComputeResourcesToMakeResidentMap& resourcesToMakeResidentMap) const + { for (const auto& resourceBindingData : resourceBindingDataSet) { ResourceType rescType = resourceBindingData.m_resourcPtr->GetResourceType(); + MTLResourceUsage resourceUsage = MTLResourceUsageRead; switch(rescType) { case ResourceType::MtlTextureType: { - MTLResourceUsage resourceUsage = GetImageResourceUsage(resourceBindingData.m_imageAccess); - [static_cast>(encoder) useResource:resourceBindingData.m_resourcPtr->GetGpuAddress>() - usage:resourceUsage - stages:mtlRenderStages]; - + resourceUsage |= GetImageResourceUsage(resourceBindingData.m_imageAccess); break; } case ResourceType::MtlBufferType: { - MTLResourceUsage resourceUsage = GetBufferResourceUsage(resourceBindingData.m_bufferAccess); - [static_cast>(encoder) useResource:resourceBindingData.m_resourcPtr->GetGpuAddress>() - usage:resourceUsage - stages:mtlRenderStages]; - + resourceUsage |= GetBufferResourceUsage(resourceBindingData.m_bufferAccess); break; } default: @@ -502,8 +473,38 @@ namespace AZ AZ_Assert(false, "Undefined Resource type"); } } + resourcesToMakeResidentMap[resourceUsage].m_resourceArray[resourcesToMakeResidentMap[resourceUsage].m_resourceArrayLen++] = resourceBindingData.m_resourcPtr->GetGpuAddress>(); + } + } + + void ArgumentBuffer::ApplyUseResourceToGraphic(id encoder, RHI::ShaderStageMask visShaderMask, const ResourceBindingsSet& resourceBindingDataSet, GraphicsResourcesToMakeResidentMap& resourcesToMakeResidentMap) const + { + + MTLRenderStages mtlRenderStages = GetRenderStages(visShaderMask); + MTLResourceUsage resourceUsage = MTLResourceUsageRead; + for (const auto& resourceBindingData : resourceBindingDataSet) + { + ResourceType rescType = resourceBindingData.m_resourcPtr->GetResourceType(); + switch(rescType) + { + case ResourceType::MtlTextureType: + { + resourceUsage |= GetImageResourceUsage(resourceBindingData.m_imageAccess); + break; + } + case ResourceType::MtlBufferType: + { + resourceUsage |= GetBufferResourceUsage(resourceBindingData.m_bufferAccess); + break; + } + default: + { + AZ_Assert(false, "Undefined Resource type"); + } + } + AZStd::pair key = AZStd::make_pair(resourceUsage, mtlRenderStages); + resourcesToMakeResidentMap[key].m_resourceArray[resourcesToMakeResidentMap[key].m_resourceArrayLen++] = resourceBindingData.m_resourcPtr->GetGpuAddress>(); } } - } } diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.h b/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.h index a5a8e00e69..2434b8312d 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.h +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.h @@ -119,8 +119,17 @@ namespace AZ using ResourceBindingsMap = AZStd::unordered_map; ResourceBindingsMap m_resourceBindings; - void ApplyUseResourceToCompute(id encoder, const ResourceBindingsSet& resourceBindingData) const; - void ApplyUseResourceToGraphic(id encoder, RHI::ShaderStageMask visShaderMask, const ResourceBindingsSet& resourceBindingDataSet) const; + static const int MaxEntriesInArgTable = 31; + struct MetalResourceArray + { + AZStd::array, MaxEntriesInArgTable> m_resourceArray; + int m_resourceArrayLen = 0; + }; + using ComputeResourcesToMakeResidentMap = AZStd::unordered_map; + using GraphicsResourcesToMakeResidentMap = AZStd::unordered_map, MetalResourceArray>; + + void ApplyUseResourceToCompute(id encoder, const ResourceBindingsSet& resourceBindingData, ComputeResourcesToMakeResidentMap& resourcesToMakeResidentMap) const; + void ApplyUseResourceToGraphic(id encoder, RHI::ShaderStageMask visShaderMask, const ResourceBindingsSet& resourceBindingDataSet, GraphicsResourcesToMakeResidentMap& resourcesToMakeResidentMap) const; //! Use visibility information to call UseResource on all resources for this Argument Buffer void ApplyUseResource(id encoder, const ResourceBindingsMap& resourceMap, @@ -144,8 +153,6 @@ namespace AZ #endif ShaderResourceGroupPool* m_srgPool = nullptr; - - static const int MaxEntriesInArgTable = 31; NSCache* m_samplerCache; }; } diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandList.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandList.cpp index 3eca8dabd8..10fbe372b1 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandList.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandList.cpp @@ -258,24 +258,19 @@ namespace AZ continue; } + uint32_t srgVisIndex = pipelineLayout.GetSlotByIndex(shaderResourceGroup->GetBindingSlot()); + const RHI::ShaderStageMask& srgVisInfo = pipelineLayout.GetSrgVisibility(srgVisIndex); + if (bindings.m_srgsByIndex[srgIndex] != shaderResourceGroup) { bindings.m_srgsByIndex[srgIndex] = shaderResourceGroup; auto& compiledArgBuffer = shaderResourceGroup->GetCompiledArgumentBuffer(); - id argBuffer = compiledArgBuffer.GetArgEncoderBuffer(); size_t argBufferOffset = compiledArgBuffer.GetOffset(); - - uint32_t srgVisIndex = pipelineLayout.GetSlotByIndex(shaderResourceGroup->GetBindingSlot()); - const RHI::ShaderStageMask& srgVisInfo = pipelineLayout.GetSrgVisibility(srgVisIndex); - + if(srgVisInfo != RHI::ShaderStageMask::None) { - const ShaderResourceGroupVisibility& srgResourcesVisInfo = pipelineLayout.GetSrgResourcesVisibility(srgVisIndex); - - //For graphics and compute encoder bind the argument buffer and - //make the resource resident for the duration of the work associated with the current scope - //and ensure that it's in a format compatible with the appropriate metal function. + //For graphics and compute encoder bind the argument buffer if(m_commandEncoderType == CommandEncoderType::Render) { id renderEncoder = GetEncoder>(); @@ -293,7 +288,6 @@ namespace AZ offset:argBufferOffset atIndex:slotIndex]; } - shaderResourceGroup->AddUntrackedResourcesToEncoder(m_encoder, srgResourcesVisInfo); } else if(m_commandEncoderType == CommandEncoderType::Compute) { @@ -301,6 +295,28 @@ namespace AZ [computeEncoder setBuffer:argBuffer offset:argBufferOffset atIndex:pipelineLayout.GetSlotByIndex(srgIndex)]; + } + } + } + + //Check againgst the srg resources visibility hash as it is possible for draw items to have different PSO in the same pass. + const AZ::HashValue64 srgResourcesVisHash = pipelineLayout.GetSrgResourcesVisibilityHash(srgVisIndex); + if(bindings.m_srgVisHashByIndex[srgIndex] != srgResourcesVisHash) + { + bindings.m_srgVisHashByIndex[srgIndex] = srgResourcesVisHash; + if(srgVisInfo != RHI::ShaderStageMask::None) + { + const ShaderResourceGroupVisibility& srgResourcesVisInfo = pipelineLayout.GetSrgResourcesVisibility(srgVisIndex); + + //For graphics and compute encoder bind the argument buffer and + //make the resource resident for the duration of the work associated with the current scope + //and ensure that it's in a format compatible with the appropriate metal function. + if(m_commandEncoderType == CommandEncoderType::Render) + { + shaderResourceGroup->AddUntrackedResourcesToEncoder(m_encoder, srgResourcesVisInfo); + } + else if(m_commandEncoderType == CommandEncoderType::Compute) + { shaderResourceGroup->AddUntrackedResourcesToEncoder(m_encoder, srgResourcesVisInfo); } } @@ -447,6 +463,7 @@ namespace AZ for (size_t i = 0; i < bindings.m_srgsByIndex.size(); ++i) { bindings.m_srgsByIndex[i] = nullptr; + bindings.m_srgVisHashByIndex[i] = AZ::HashValue64{0}; } const PipelineLayout& pipelineLayout = pipelineState->GetPipelineLayout(); @@ -469,6 +486,10 @@ namespace AZ void CommandList::SetStreamBuffers(const RHI::StreamBufferView* streams, uint32_t count) { + int bufferArrayLen = 0; + AZStd::array, METAL_MAX_ENTRIES_BUFFER_ARG_TABLE> mtlStreamBuffers; + AZStd::array mtlStreamBufferOffsets; + AZ::HashValue64 streamsHash = AZ::HashValue64{0}; for (uint32_t i = 0; i < count; ++i) { @@ -479,18 +500,23 @@ namespace AZ { m_state.m_streamsHash = streamsHash; AZ_Assert(count <= METAL_MAX_ENTRIES_BUFFER_ARG_TABLE , "Slots needed cannot exceed METAL_MAX_ENTRIES_BUFFER_ARG_TABLE"); - for (uint32_t i = 0; i < count; ++i) + + NSRange range = {METAL_MAX_ENTRIES_BUFFER_ARG_TABLE - count, count}; + //For metal the stream buffers are populated from bottom to top as the top slots are taken by argument buffers + for (int i = count-1; i >= 0; --i) { if (streams[i].GetBuffer()) { const Buffer * buff = static_cast(streams[i].GetBuffer()); id mtlBuff = buff->GetMemoryView().GetGpuAddress>(); - uint32_t VBIndex = (METAL_MAX_ENTRIES_BUFFER_ARG_TABLE - 1) - i; uint32_t offset = streams[i].GetByteOffset() + buff->GetMemoryView().GetOffset(); - id renderEncoder = GetEncoder>(); - [renderEncoder setVertexBuffer: mtlBuff offset: offset atIndex: VBIndex]; + mtlStreamBuffers[bufferArrayLen] = mtlBuff; + mtlStreamBufferOffsets[bufferArrayLen] = offset; + bufferArrayLen++; } } + id renderEncoder = GetEncoder>(); + [renderEncoder setVertexBuffers: mtlStreamBuffers.data() offsets: mtlStreamBufferOffsets.data() withRange: range]; } } diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandList.h b/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandList.h index 6660beb2c4..dd4e382471 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandList.h +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandList.h @@ -99,6 +99,7 @@ namespace AZ { AZStd::array m_srgsByIndex; AZStd::array m_srgsBySlot; + AZStd::array m_srgVisHashByIndex; }; ShaderResourceBindings& GetShaderResourceBindingsByPipelineType(RHI::PipelineStateType pipelineType); diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/PipelineLayout.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/PipelineLayout.cpp index f237884aab..70d36f8d6d 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/PipelineLayout.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/PipelineLayout.cpp @@ -70,6 +70,7 @@ namespace AZ m_srgVisibilities.resize(RHI::Limits::Pipeline::ShaderResourceGroupCountMax); m_srgResourcesVisibility.resize(RHI::Limits::Pipeline::ShaderResourceGroupCountMax); + m_srgResourcesVisibilityHash.resize(RHI::Limits::Pipeline::ShaderResourceGroupCountMax); for (uint32_t srgLayoutIdx = 0; srgLayoutIdx < groupLayoutCount; ++srgLayoutIdx) { const RHI::ShaderResourceGroupLayout& srgLayout = *descriptor.GetShaderResourceGroupLayout(srgLayoutIdx); @@ -111,6 +112,7 @@ namespace AZ m_srgVisibilities[srgIndex] = mask; m_srgResourcesVisibility[srgIndex] = srgVis; + m_srgResourcesVisibilityHash[srgIndex] = srgVis.GetHash(); } // Cache the inline constant size and slot index @@ -141,6 +143,11 @@ namespace AZ return m_srgResourcesVisibility[index]; } + const AZ::HashValue64 PipelineLayout::GetSrgResourcesVisibilityHash(uint32_t index) const + { + return m_srgResourcesVisibilityHash[index]; + } + uint32_t PipelineLayout::GetRootConstantsSize() const { return m_rootConstantsSize; diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/PipelineLayout.h b/Gems/Atom/RHI/Metal/Code/Source/RHI/PipelineLayout.h index e8cd249393..6fd06ea29b 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/PipelineLayout.h +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/PipelineLayout.h @@ -57,6 +57,9 @@ namespace AZ /// Returns srgVisibility data const ShaderResourceGroupVisibility& GetSrgResourcesVisibility(uint32_t index) const; + /// Returns srgVisibility hash + const AZ::HashValue64 GetSrgResourcesVisibilityHash(uint32_t index) const; + /// Returns the root constant specific layout information uint32_t GetRootConstantsSize() const; uint32_t GetRootConstantsSlotIndex() const; @@ -84,6 +87,9 @@ namespace AZ /// Cache Visibility across all the resources within the SRG AZStd::fixed_vector m_srgResourcesVisibility; + /// Cache Visibility hash across all the resources within the SRG + AZStd::fixed_vector m_srgResourcesVisibilityHash; + uint32_t m_rootConstantSlotIndex = (uint32_t)-1; uint32_t m_rootConstantsSize = 0; }; From 3d1abdc4e3934888ad253d0563f614b094496418 Mon Sep 17 00:00:00 2001 From: igarri Date: Fri, 4 Jun 2021 12:16:32 +0100 Subject: [PATCH 027/116] Pull request corrections, namespaces, style, etc --- .../Entries/RootAssetBrowserEntry.cpp | 2 +- .../AssetBrowser/Search/Filter.h | 1 + .../AssetBrowser/Views/EntryDelegate.cpp | 8 +-- .../AzAssetBrowser/AzAssetBrowserWindow.cpp | 61 +++++++++---------- 4 files changed, 36 insertions(+), 36 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/RootAssetBrowserEntry.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/RootAssetBrowserEntry.cpp index 2ccc2cd6bf..e626f31b62 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/RootAssetBrowserEntry.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/RootAssetBrowserEntry.cpp @@ -287,7 +287,7 @@ namespace AzToolsFramework product->m_assetType.ToString(product->m_assetTypeString); AZ::Data::AssetCatalogRequestBus::BroadcastResult(product->m_relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, assetId); QString displayPath = QString::fromUtf8(product->m_relativePath.c_str()); - displayPath.remove(QString("/" + QString::fromUtf8(product->m_name.c_str()))); + displayPath.remove(QString(AZ_CORRECT_DATABASE_SEPARATOR + QString::fromUtf8(product->m_name.c_str()))); product->m_displayPath = displayPath; EntryCache::GetInstance()->m_productAssetIdMap[assetId] = product; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.h index 135dd00925..b67b699862 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.h @@ -110,6 +110,7 @@ namespace AzToolsFramework ~StringFilter() override = default; void SetFilterString(const QString& filterString); + protected: QString GetNameInternal() const override; bool MatchInternal(const AssetBrowserEntry* entry) const override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp index c73c00981b..d0ac05020d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp @@ -95,13 +95,13 @@ namespace AzToolsFramework remainingRect.adjust(thumbX, 0, 0, 0); // bump it to the right by the size of the thumbnail remainingRect.adjust(ENTRY_SPACING_LEFT_PIXELS, 0, 0, 0); // bump it to the right by the spacing. } - QString displayString = qvariant_cast(index.data(index.column())); + QString displayString = index.column() == aznumeric_cast(AssetBrowserEntry::Column::Name) + ? qvariant_cast(entry->data(aznumeric_cast(AssetBrowserEntry::Column::Name))) + : qvariant_cast(entry->data(aznumeric_cast(AssetBrowserEntry::Column::Path))); style->drawItemText( painter, remainingRect, option.displayAlignment, actualPalette, isEnabled, - index.column() == aznumeric_cast(AssetBrowserEntry::Column::Name) - ? qvariant_cast(entry->data(aznumeric_cast(AssetBrowserEntry::Column::Name))) - : qvariant_cast(entry->data(aznumeric_cast(AssetBrowserEntry::Column::Path))), + displayString, isSelected ? QPalette::HighlightedText : QPalette::Text); } } diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp index 481cc35635..60ff6f9549 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp @@ -74,9 +74,9 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) m_ui->setupUi(this); m_ui->m_searchWidget->Setup(true, true); - namespace AB = AzToolsFramework::AssetBrowser; + namespace AzAssetBrowser = AzToolsFramework::AssetBrowser; - AB::AssetBrowserComponentRequestBus::BroadcastResult(m_assetBrowserModel, &AB::AssetBrowserComponentRequests::GetAssetBrowserModel); + AzAssetBrowser::AssetBrowserComponentRequestBus::BroadcastResult(m_assetBrowserModel, &AzAssetBrowser::AssetBrowserComponentRequests::GetAssetBrowserModel); AZ_Assert(m_assetBrowserModel, "Failed to get filebrowser model"); m_filterModel->setSourceModel(m_assetBrowserModel); m_filterModel->SetFilter(m_ui->m_searchWidget->GetFilter()); @@ -90,34 +90,34 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) m_tableModel->setSourceModel(m_filterModel.data()); m_ui->m_assetBrowserTableViewWidget->setModel(m_tableModel.data()); connect( - m_filterModel.data(), &AB::AssetBrowserFilterModel::filterChanged, m_tableModel.data(), - &AB::AssetBrowserTableModel::UpdateTableModelMaps); + m_filterModel.data(), &AzAssetBrowser::AssetBrowserFilterModel::filterChanged, m_tableModel.data(), + &AzAssetBrowser::AssetBrowserTableModel::UpdateTableModelMaps); connect( - m_ui->m_assetBrowserTableViewWidget, &AB::AssetBrowserTableView::selectionChangedSignal, this, + m_ui->m_assetBrowserTableViewWidget, &AzAssetBrowser::AssetBrowserTableView::selectionChangedSignal, this, &AzAssetBrowserWindow::SelectionChangedSlot); connect( m_ui->m_assetBrowserTableViewWidget, &QAbstractItemView::doubleClicked, this, &AzAssetBrowserWindow::DoubleClickedItemTableModel); connect( - m_ui->m_assetBrowserTableViewWidget, &AB::AssetBrowserTableView::ClearStringFilter, m_ui->m_searchWidget, - &AB::SearchWidget::ClearStringFilter); + m_ui->m_assetBrowserTableViewWidget, &AzAssetBrowser::AssetBrowserTableView::ClearStringFilter, m_ui->m_searchWidget, + &AzAssetBrowser::SearchWidget::ClearStringFilter); connect( - m_ui->m_assetBrowserTableViewWidget, &AB::AssetBrowserTableView::ClearTypeFilter, m_ui->m_searchWidget, - &AB::SearchWidget::ClearTypeFilter); + m_ui->m_assetBrowserTableViewWidget, &AzAssetBrowser::AssetBrowserTableView::ClearTypeFilter, m_ui->m_searchWidget, + &AzAssetBrowser::SearchWidget::ClearTypeFilter); m_ui->m_assetBrowserTableViewWidget->SetName("AssetBrowserTableView_main"); - connect(m_filterModel.data(), &AB::AssetBrowserFilterModel::stringFilterPopulated, this, &AzAssetBrowserWindow::SwitchDisplayView); + connect(m_filterModel.data(), &AzAssetBrowser::AssetBrowserFilterModel::stringFilterPopulated, this, &AzAssetBrowserWindow::SwitchDisplayView); connect(m_ui->m_viewSwitcherCheckBox, &QCheckBox::stateChanged, this, &AzAssetBrowserWindow::LockToDefaultView); } m_ui->m_assetBrowserTreeViewWidget->setModel(m_filterModel.data()); connect( - m_ui->m_searchWidget->GetFilter().data(), &AB::AssetBrowserEntryFilter::updatedSignal, m_filterModel.data(), - &AB::AssetBrowserFilterModel::filterUpdatedSlot); + m_ui->m_searchWidget->GetFilter().data(), &AzAssetBrowser::AssetBrowserEntryFilter::updatedSignal, m_filterModel.data(), + &AzAssetBrowser::AssetBrowserFilterModel::filterUpdatedSlot); connect( - m_filterModel.data(), &AB::AssetBrowserFilterModel::filterChanged, this, + m_filterModel.data(), &AzAssetBrowser::AssetBrowserFilterModel::filterChanged, this, [this]() { const bool hasFilter = !m_ui->m_searchWidget->GetFilterString().isEmpty(); @@ -126,17 +126,17 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) }); connect( - m_ui->m_assetBrowserTreeViewWidget, &AB::AssetBrowserTreeView::selectionChangedSignal, this, + m_ui->m_assetBrowserTreeViewWidget, &AzAssetBrowser::AssetBrowserTreeView::selectionChangedSignal, this, &AzAssetBrowserWindow::SelectionChangedSlot); connect(m_ui->m_assetBrowserTreeViewWidget, &QAbstractItemView::doubleClicked, this, &AzAssetBrowserWindow::DoubleClickedItem); connect( - m_ui->m_assetBrowserTreeViewWidget, &AB::AssetBrowserTreeView::ClearStringFilter, m_ui->m_searchWidget, - &AB::SearchWidget::ClearStringFilter); + m_ui->m_assetBrowserTreeViewWidget, &AzAssetBrowser::AssetBrowserTreeView::ClearStringFilter, m_ui->m_searchWidget, + &AzAssetBrowser::SearchWidget::ClearStringFilter); connect( - m_ui->m_assetBrowserTreeViewWidget, &AB::AssetBrowserTreeView::ClearTypeFilter, m_ui->m_searchWidget, - &AB::SearchWidget::ClearTypeFilter); + m_ui->m_assetBrowserTreeViewWidget, &AzAssetBrowser::AssetBrowserTreeView::ClearTypeFilter, m_ui->m_searchWidget, + &AzAssetBrowser::SearchWidget::ClearTypeFilter); m_ui->m_assetBrowserTreeViewWidget->SetName("AssetBrowserTreeView_main"); } @@ -232,21 +232,21 @@ void AzAssetBrowserWindow::SelectionChangedSlot(const QItemSelection& /*selected // just becuase on some OS clicking once is activation. void AzAssetBrowserWindow::DoubleClickedItem([[maybe_unused]] const QModelIndex& element) { - namespace AB = AzToolsFramework::AssetBrowser; + namespace AzAssetBrowser = AzToolsFramework::AssetBrowser; // assumption: Double clicking an item selects it before telling us we double clicked it. const auto& selectedAssets = m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets(); - for (const AB::AssetBrowserEntry* entry : selectedAssets) + for (const AzAssetBrowser::AssetBrowserEntry* entry : selectedAssets) { AZ::Data::AssetId assetIdToOpen; AZStd::string fullFilePath; - if (const AB::ProductAssetBrowserEntry* productEntry = azrtti_cast(entry)) + if (const AzAssetBrowser::ProductAssetBrowserEntry* productEntry = azrtti_cast(entry)) { assetIdToOpen = productEntry->GetAssetId(); fullFilePath = entry->GetFullPath(); } - else if (const AB::SourceAssetBrowserEntry* sourceEntry = azrtti_cast(entry)) + else if (const AzAssetBrowser::SourceAssetBrowserEntry* sourceEntry = azrtti_cast(entry)) { // manufacture an empty AssetID with the source's UUID assetIdToOpen = AZ::Data::AssetId(sourceEntry->GetSourceUuid(), 0); @@ -256,8 +256,8 @@ void AzAssetBrowserWindow::DoubleClickedItem([[maybe_unused]] const QModelIndex& bool handledBySomeone = false; if (assetIdToOpen.IsValid()) { - AB::AssetBrowserInteractionNotificationBus::Broadcast( - &AB::AssetBrowserInteractionNotifications::OpenAssetInAssociatedEditor, assetIdToOpen, handledBySomeone); + AzAssetBrowser::AssetBrowserInteractionNotificationBus::Broadcast( + &AzAssetBrowser::AssetBrowserInteractionNotifications::OpenAssetInAssociatedEditor, assetIdToOpen, handledBySomeone); } if (!handledBySomeone && !fullFilePath.empty()) @@ -269,20 +269,19 @@ void AzAssetBrowserWindow::DoubleClickedItem([[maybe_unused]] const QModelIndex& void AzAssetBrowserWindow::DoubleClickedItemTableModel([[maybe_unused]] const QModelIndex& element) { - namespace AB = AzToolsFramework::AssetBrowser; - // assumption: Double clicking an item selects it before telling us we double clicked it. + namespace AzAssetBrowser = AzToolsFramework::AssetBrowser; const auto& selectedAssets = m_ui->m_assetBrowserTableViewWidget->GetSelectedAssets(); - for (const AB::AssetBrowserEntry* entry : selectedAssets) + for (const AzAssetBrowser::AssetBrowserEntry* entry : selectedAssets) { AZ::Data::AssetId assetIdToOpen; AZStd::string fullFilePath; - if (const AB::ProductAssetBrowserEntry* productEntry = azrtti_cast(entry)) + if (const AzAssetBrowser::ProductAssetBrowserEntry* productEntry = azrtti_cast(entry)) { assetIdToOpen = productEntry->GetAssetId(); fullFilePath = entry->GetFullPath(); } - else if (const AB::SourceAssetBrowserEntry* sourceEntry = azrtti_cast(entry)) + else if (const AzAssetBrowser::SourceAssetBrowserEntry* sourceEntry = azrtti_cast(entry)) { // manufacture an empty AssetID with the source's UUID assetIdToOpen = AZ::Data::AssetId(sourceEntry->GetSourceUuid(), 0); @@ -292,8 +291,8 @@ void AzAssetBrowserWindow::DoubleClickedItemTableModel([[maybe_unused]] const QM bool handledBySomeone = false; if (assetIdToOpen.IsValid()) { - AB::AssetBrowserInteractionNotificationBus::Broadcast( - &AB::AssetBrowserInteractionNotifications::OpenAssetInAssociatedEditor, assetIdToOpen, handledBySomeone); + AzAssetBrowser::AssetBrowserInteractionNotificationBus::Broadcast( + &AzAssetBrowser::AssetBrowserInteractionNotifications::OpenAssetInAssociatedEditor, assetIdToOpen, handledBySomeone); } if (!handledBySomeone && !fullFilePath.empty()) From c6d0887210c367f58b086d90f5f20759887d5e72 Mon Sep 17 00:00:00 2001 From: moudgils Date: Sun, 6 Jun 2021 10:24:42 -0700 Subject: [PATCH 028/116] Minor method name changes --- Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp | 8 ++++---- Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp index 1e2edc6520..5d6c275184 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp @@ -422,12 +422,12 @@ namespace AZ { if(RHI::CheckBitsAny(visMaskIt->second, RHI::ShaderStageMask::Compute)) { - ApplyUseResourceToCompute(commandEncoder, it.second, resourcesToMakeResidentCompute); + CollectResourcesForCompute(commandEncoder, it.second, resourcesToMakeResidentCompute); } else { AZ_Assert(RHI::CheckBitsAny(visMaskIt->second, RHI::ShaderStageMask::Vertex) || RHI::CheckBitsAny(visMaskIt->second, RHI::ShaderStageMask::Fragment), "The visibility mask %i is not set for Vertex or fragment stage", visMaskIt->second); - ApplyUseResourceToGraphic(commandEncoder, visMaskIt->second, it.second, resourcesToMakeResidentGraphics); + CollectResourcesForGraphics(commandEncoder, visMaskIt->second, it.second, resourcesToMakeResidentGraphics); } } } @@ -450,7 +450,7 @@ namespace AZ } } - void ArgumentBuffer::ApplyUseResourceToCompute(id encoder, const ResourceBindingsSet& resourceBindingDataSet, ComputeResourcesToMakeResidentMap& resourcesToMakeResidentMap) const + void ArgumentBuffer::CollectResourcesForCompute(id encoder, const ResourceBindingsSet& resourceBindingDataSet, ComputeResourcesToMakeResidentMap& resourcesToMakeResidentMap) const { for (const auto& resourceBindingData : resourceBindingDataSet) { @@ -477,7 +477,7 @@ namespace AZ } } - void ArgumentBuffer::ApplyUseResourceToGraphic(id encoder, RHI::ShaderStageMask visShaderMask, const ResourceBindingsSet& resourceBindingDataSet, GraphicsResourcesToMakeResidentMap& resourcesToMakeResidentMap) const + void ArgumentBuffer::CollectResourcesForGraphics(id encoder, RHI::ShaderStageMask visShaderMask, const ResourceBindingsSet& resourceBindingDataSet, GraphicsResourcesToMakeResidentMap& resourcesToMakeResidentMap) const { MTLRenderStages mtlRenderStages = GetRenderStages(visShaderMask); diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.h b/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.h index 2434b8312d..06380162b6 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.h +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.h @@ -128,8 +128,8 @@ namespace AZ using ComputeResourcesToMakeResidentMap = AZStd::unordered_map; using GraphicsResourcesToMakeResidentMap = AZStd::unordered_map, MetalResourceArray>; - void ApplyUseResourceToCompute(id encoder, const ResourceBindingsSet& resourceBindingData, ComputeResourcesToMakeResidentMap& resourcesToMakeResidentMap) const; - void ApplyUseResourceToGraphic(id encoder, RHI::ShaderStageMask visShaderMask, const ResourceBindingsSet& resourceBindingDataSet, GraphicsResourcesToMakeResidentMap& resourcesToMakeResidentMap) const; + void CollectResourcesForCompute(id encoder, const ResourceBindingsSet& resourceBindingData, ComputeResourcesToMakeResidentMap& resourcesToMakeResidentMap) const; + void CollectResourcesForGraphics(id encoder, RHI::ShaderStageMask visShaderMask, const ResourceBindingsSet& resourceBindingDataSet, GraphicsResourcesToMakeResidentMap& resourcesToMakeResidentMap) const; //! Use visibility information to call UseResource on all resources for this Argument Buffer void ApplyUseResource(id encoder, const ResourceBindingsMap& resourceMap, From e795dd5210b1da9d689b4ce34c9eb155be868d5b Mon Sep 17 00:00:00 2001 From: moudgils Date: Tue, 8 Jun 2021 22:35:48 -0700 Subject: [PATCH 029/116] - Added enums for write mask and adding suppooort for that across all backends. - Batch calls to bind argument buffers - Fix swapchain creation for Editor --- .../Include/Atom/RHI.Reflect/RenderStates.h | 18 +++ .../RHI/DX12/Code/Source/RHI/Conversions.cpp | 25 ++- .../RHI/DX12/Code/Source/RHI/Conversions.h | 2 + .../RHI/Metal/Code/Source/RHI/CommandList.cpp | 143 +++++++++++++++--- .../RHI/Metal/Code/Source/RHI/CommandList.h | 4 + .../RHI/Metal/Code/Source/RHI/Conversions.cpp | 22 ++- .../Metal/Code/Source/RHI/PipelineLayout.cpp | 4 +- .../RHI/Metal/Code/Source/RHI/SwapChain.cpp | 29 ++-- .../RHI/Metal/Code/Source/RHI/SwapChain.h | 2 + .../RHI/Vulkan/Code/Source/RHI/Conversion.cpp | 8 +- 10 files changed, 213 insertions(+), 44 deletions(-) diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/RenderStates.h b/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/RenderStates.h index 51b15c4bcf..d5c55e2c7f 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/RenderStates.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/RenderStates.h @@ -160,6 +160,24 @@ namespace AZ StencilState m_stencil; }; + enum class WriteChannel : uint32_t + { + ColorWriteMaskRed = 0, + ColorWriteMaskGreen, + ColorWriteMaskBlue, + ColorWriteMaskAlpha, + }; + + enum class WriteChannelMask : uint32_t + { + ColorWriteMaskNone = 0, + ColorWriteMaskRed = AZ_BIT(static_cast(WriteChannel::ColorWriteMaskRed)), + ColorWriteMaskGreen = AZ_BIT(static_cast(WriteChannel::ColorWriteMaskGreen)), + ColorWriteMaskBlue = AZ_BIT(static_cast(WriteChannel::ColorWriteMaskBlue)), + ColorWriteMaskAlpha = AZ_BIT(static_cast(WriteChannel::ColorWriteMaskAlpha)), + ColorWriteMaskAll = ColorWriteMaskRed | ColorWriteMaskGreen | ColorWriteMaskBlue | ColorWriteMaskAlpha + }; + struct TargetBlendState { AZ_TYPE_INFO(TargetBlendState, "{2CDF00FE-614D-44FC-929F-E6B50C348578}"); diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.cpp index a3d14e3803..73d80ed78c 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.cpp @@ -10,6 +10,7 @@ * */ #include "RHI/Atom_RHI_DX12_precompiled.h" +#include #include #include #include @@ -1268,7 +1269,7 @@ namespace AZ dst.BlendOpAlpha = ConvertBlendOp(src.m_blendAlphaOp); dst.DestBlend = ConvertBlendFactor(src.m_blendDest); dst.DestBlendAlpha = ConvertBlendFactor(src.m_blendAlphaDest); - dst.RenderTargetWriteMask = src.m_writeMask; + dst.RenderTargetWriteMask = ConvertColorWriteMask(src.m_writeMask); dst.SrcBlend = ConvertBlendFactor(src.m_blendSource); dst.SrcBlendAlpha = ConvertBlendFactor(src.m_blendAlphaSource); dst.LogicOp = D3D12_LOGIC_OP_CLEAR; @@ -1355,6 +1356,28 @@ namespace AZ }; return table[(uint32_t)mask]; } + + uint32_t ConvertColorWriteMask(uint8_t writeMask) + { + uint32_t dflags = 0; + if (RHI::CheckBitsAny(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskRed))) + { + dflags |= D3D12_COLOR_WRITE_ENABLE_RED; + } + if (RHI::CheckBitsAny(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskGreen))) + { + dflags |= D3D12_COLOR_WRITE_ENABLE_GREEN; + } + if (RHI::CheckBitsAny(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskBlue))) + { + dflags |= D3D12_COLOR_WRITE_ENABLE_BLUE; + } + if (RHI::CheckBitsAny(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskAlpha))) + { + dflags |= D3D12_COLOR_WRITE_ENABLE_ALPHA; + } + return dflags; + } D3D12_DEPTH_STENCIL_DESC ConvertDepthStencilState(const RHI::DepthStencilState& depthStencil) { diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.h b/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.h index d8385203f8..887598de79 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.h +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.h @@ -164,5 +164,7 @@ namespace AZ uint32_t shaderRegisterSpace, D3D12_SHADER_VISIBILITY shaderVisibility, D3D12_STATIC_SAMPLER_DESC& staticSamplerDesc); + + uint32_t ConvertColorWriteMask(uint8_t writeMask); } } diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandList.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandList.cpp index 10fbe372b1..7df8f1e547 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandList.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandList.cpp @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -249,68 +250,88 @@ namespace AZ ShaderResourceBindings& bindings = GetShaderResourceBindingsByPipelineType(stateType); const PipelineLayout& pipelineLayout = pipelineState->GetPipelineLayout(); - for (uint32_t srgIndex = 0; srgIndex < RHI::Limits::Pipeline::ShaderResourceGroupCountMax; ++srgIndex) + uint32_t bufferVertexRegisterIdMin = RHI::Limits::Pipeline::ShaderResourceGroupCountMax; + uint32_t bufferFragmentOrComputeRegisterIdMin = RHI::Limits::Pipeline::ShaderResourceGroupCountMax; + uint32_t bufferVertexRegisterIdMax = 0; + uint32_t bufferFragmentOrComputeRegisterIdMax = 0; + + MetalArgumentBufferArray mtlVertexArgBuffers; + MetalArgumentBufferArrayOffsets mtlVertexArgBufferOffsets; + MetalArgumentBufferArray mtlFragmentOrComputeArgBuffers; + MetalArgumentBufferArrayOffsets mtlFragmentOrComputeArgBufferOffsets; + + mtlVertexArgBuffers.fill(nil); + mtlFragmentOrComputeArgBuffers.fill(nil); + mtlVertexArgBufferOffsets.fill(0); + mtlFragmentOrComputeArgBufferOffsets.fill(0); + + for (uint32_t slot = 0; slot < RHI::Limits::Pipeline::ShaderResourceGroupCountMax; ++slot) { - const ShaderResourceGroup* shaderResourceGroup = bindings.m_srgsBySlot[srgIndex]; - uint32_t slotIndex = pipelineLayout.GetSlotByIndex(srgIndex); + const ShaderResourceGroup* shaderResourceGroup = bindings.m_srgsBySlot[slot]; + uint32_t slotIndex = pipelineLayout.GetIndexBySlot(slot); if(!shaderResourceGroup || slotIndex == RHI::Limits::Pipeline::ShaderResourceGroupCountMax) { continue; } - uint32_t srgVisIndex = pipelineLayout.GetSlotByIndex(shaderResourceGroup->GetBindingSlot()); + uint32_t srgVisIndex = pipelineLayout.GetIndexBySlot(shaderResourceGroup->GetBindingSlot()); const RHI::ShaderStageMask& srgVisInfo = pipelineLayout.GetSrgVisibility(srgVisIndex); - if (bindings.m_srgsByIndex[srgIndex] != shaderResourceGroup) + bool isSrgUpdatd = bindings.m_srgsByIndex[slot] != shaderResourceGroup; + if(isSrgUpdatd) { - bindings.m_srgsByIndex[srgIndex] = shaderResourceGroup; + bindings.m_srgsByIndex[slot] = shaderResourceGroup; auto& compiledArgBuffer = shaderResourceGroup->GetCompiledArgumentBuffer(); id argBuffer = compiledArgBuffer.GetArgEncoderBuffer(); size_t argBufferOffset = compiledArgBuffer.GetOffset(); if(srgVisInfo != RHI::ShaderStageMask::None) { - //For graphics and compute encoder bind the argument buffer + //For graphics and compute shader stages, cache all the argument buffers, offsets and track the min/max indices if(m_commandEncoderType == CommandEncoderType::Render) { id renderEncoder = GetEncoder>(); uint8_t numBitsSet = RHI::CountBitsSet(static_cast(srgVisInfo)); if( numBitsSet > 1 || srgVisInfo == RHI::ShaderStageMask::Vertex) { - [renderEncoder setVertexBuffer:argBuffer - offset:argBufferOffset - atIndex:slotIndex]; + mtlVertexArgBuffers[slotIndex] = argBuffer; + mtlVertexArgBufferOffsets[slotIndex] = argBufferOffset; + bufferVertexRegisterIdMin = AZStd::min(slotIndex, bufferVertexRegisterIdMin); + bufferVertexRegisterIdMax = AZStd::max(slotIndex, bufferVertexRegisterIdMax); + } if( numBitsSet > 1 || srgVisInfo == RHI::ShaderStageMask::Fragment) { - [renderEncoder setFragmentBuffer:argBuffer - offset:argBufferOffset - atIndex:slotIndex]; + mtlFragmentOrComputeArgBuffers[slotIndex] = argBuffer; + mtlFragmentOrComputeArgBufferOffsets[slotIndex] = argBufferOffset; + bufferFragmentOrComputeRegisterIdMin = AZStd::min(slotIndex, bufferFragmentOrComputeRegisterIdMin); + bufferFragmentOrComputeRegisterIdMax = AZStd::max(slotIndex, bufferFragmentOrComputeRegisterIdMax); } } else if(m_commandEncoderType == CommandEncoderType::Compute) { - id computeEncoder = GetEncoder>(); - [computeEncoder setBuffer:argBuffer - offset:argBufferOffset - atIndex:pipelineLayout.GetSlotByIndex(srgIndex)]; + mtlFragmentOrComputeArgBuffers[slotIndex] = argBuffer; + mtlFragmentOrComputeArgBufferOffsets[slotIndex] = argBufferOffset; + bufferFragmentOrComputeRegisterIdMin = AZStd::min(slotIndex, bufferFragmentOrComputeRegisterIdMin); + bufferFragmentOrComputeRegisterIdMax = AZStd::max(slotIndex, bufferFragmentOrComputeRegisterIdMax); } } } - //Check againgst the srg resources visibility hash as it is possible for draw items to have different PSO in the same pass. + //Check if the srg has been updated or if the srg resources visibility hash has been updated + //as it is possible for draw items to have different PSOs in the same pass. const AZ::HashValue64 srgResourcesVisHash = pipelineLayout.GetSrgResourcesVisibilityHash(srgVisIndex); - if(bindings.m_srgVisHashByIndex[srgIndex] != srgResourcesVisHash) + if(bindings.m_srgVisHashByIndex[slot] != srgResourcesVisHash || isSrgUpdatd) { - bindings.m_srgVisHashByIndex[srgIndex] = srgResourcesVisHash; + bindings.m_srgVisHashByIndex[slot] = srgResourcesVisHash; if(srgVisInfo != RHI::ShaderStageMask::None) { const ShaderResourceGroupVisibility& srgResourcesVisInfo = pipelineLayout.GetSrgResourcesVisibility(srgVisIndex); - //For graphics and compute encoder bind the argument buffer and - //make the resource resident for the duration of the work associated with the current scope - //and ensure that it's in a format compatible with the appropriate metal function. + //For graphics and compute encoder make the resource resident (call UseResource) for the duration + //of the work associated with the current scope and ensure that it's in a + //format compatible with the appropriate metal function. if(m_commandEncoderType == CommandEncoderType::Render) { shaderResourceGroup->AddUntrackedResourcesToEncoder(m_encoder, srgResourcesVisInfo); @@ -322,9 +343,81 @@ namespace AZ } } } - + + //For graphics and compute encoder bind all the argument buffers + if(m_commandEncoderType == CommandEncoderType::Render) + { + BindArgumentBuffers(RHI::ShaderStage::Vertex, bufferVertexRegisterIdMin, bufferVertexRegisterIdMax, mtlVertexArgBuffers, mtlVertexArgBufferOffsets); + BindArgumentBuffers(RHI::ShaderStage::Fragment, bufferFragmentOrComputeRegisterIdMin, bufferFragmentOrComputeRegisterIdMax, mtlFragmentOrComputeArgBuffers, mtlFragmentOrComputeArgBufferOffsets); + } + else if(m_commandEncoderType == CommandEncoderType::Compute) + { + BindArgumentBuffers(RHI::ShaderStage::Compute, bufferFragmentOrComputeRegisterIdMin, bufferFragmentOrComputeRegisterIdMax, mtlFragmentOrComputeArgBuffers, mtlFragmentOrComputeArgBufferOffsets); + } + return true; } + + void CommandList::BindArgumentBuffers(RHI::ShaderStage shaderStage, uint16_t registerIdMin, uint16_t registerIdMax, MetalArgumentBufferArray& mtlArgBuffers, MetalArgumentBufferArrayOffsets mtlArgBufferOffsets) + { + //Metal Api only lets you bind multiple argument buffers in an array as long as there are no gaps in the array + //In order to accomodate that we break up the calls when a gap is noticed in the array and reconfigure the NSRange. + uint16_t startingIndex = registerIdMin; + bool trackingRange = true; + for(int i = registerIdMin; i <= registerIdMax+1; i++) + { + if(trackingRange) + { + if(mtlArgBuffers[i] == nil) + { + NSRange range = { startingIndex, i-startingIndex }; + + switch(shaderStage) + { + case RHI::ShaderStage::Vertex: + { + id renderEncoder = GetEncoder>(); + [renderEncoder setVertexBuffers:&mtlArgBuffers[startingIndex] + offsets:&mtlArgBufferOffsets[startingIndex] + withRange:range]; + break; + } + case RHI::ShaderStage::Fragment: + { + id renderEncoder = GetEncoder>(); + [renderEncoder setFragmentBuffers:&mtlArgBuffers[startingIndex] + offsets:&mtlArgBufferOffsets[startingIndex] + withRange:range]; + break; + } + case RHI::ShaderStage::Compute: + { + id computeEncoder = GetEncoder>(); + [computeEncoder setBuffers:&mtlArgBuffers[startingIndex] + offsets:&mtlArgBufferOffsets[startingIndex] + withRange:range]; + break; + } + default: + { + AZ_Assert(false, "Not supported"); + } + } + + trackingRange = false; + + } + } + else + { + if(mtlArgBuffers[i] != nil) + { + startingIndex = i; + trackingRange = true; + } + } + } + } void CommandList::Submit(const RHI::DrawItem& drawItem) { @@ -486,7 +579,7 @@ namespace AZ void CommandList::SetStreamBuffers(const RHI::StreamBufferView* streams, uint32_t count) { - int bufferArrayLen = 0; + uint16_t bufferArrayLen = 0; AZStd::array, METAL_MAX_ENTRIES_BUFFER_ARG_TABLE> mtlStreamBuffers; AZStd::array mtlStreamBufferOffsets; diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandList.h b/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandList.h index dd4e382471..9dd14cd175 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandList.h +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandList.h @@ -102,6 +102,10 @@ namespace AZ AZStd::array m_srgVisHashByIndex; }; + using MetalArgumentBufferArray = AZStd::array, RHI::Limits::Pipeline::ShaderResourceGroupCountMax>; + using MetalArgumentBufferArrayOffsets = AZStd::array; + void BindArgumentBuffers(RHI::ShaderStage shaderStage, uint16_t registerIdMin, uint16_t registerIdMax, MetalArgumentBufferArray& mtlArgBuffers, MetalArgumentBufferArrayOffsets mtlArgBufferOffsets); + ShaderResourceBindings& GetShaderResourceBindingsByPipelineType(RHI::PipelineStateType pipelineType); //! This is kept as a separate struct so that we can robustly reset it. Every property diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/Conversions.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/Conversions.cpp index f95e871d33..e41ba9bf2a 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/Conversions.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/Conversions.cpp @@ -12,6 +12,7 @@ #include "Atom_RHI_Metal_precompiled.h" #include +#include #include #include #include @@ -456,8 +457,25 @@ namespace AZ MTLColorWriteMask ConvertColorWriteMask(AZ::u8 writeMask) { - //todo::Based on the mask set the correct writemask - return MTLColorWriteMaskAll; + MTLColorWriteMask colorMask = MTLColorWriteMaskNone; + if (RHI::CheckBitsAny(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskRed))) + { + colorMask |= MTLColorWriteMaskRed; + } + if (RHI::CheckBitsAny(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskGreen))) + { + colorMask |= MTLColorWriteMaskGreen; + } + if (RHI::CheckBitsAny(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskBlue))) + { + colorMask |= MTLColorWriteMaskBlue; + } + if (RHI::CheckBitsAny(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskAlpha))) + { + colorMask |= MTLColorWriteMaskAlpha; + } + + return colorMask; } MTLVertexFormat ConvertVertexFormat(RHI::Format format) diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/PipelineLayout.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/PipelineLayout.cpp index 70d36f8d6d..9a30a04deb 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/PipelineLayout.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/PipelineLayout.cpp @@ -125,12 +125,12 @@ namespace AZ size_t PipelineLayout::GetSlotByIndex(size_t index) const { - return m_slotToIndexTable[index]; + return m_indexToSlotTable[index]; } size_t PipelineLayout::GetIndexBySlot(size_t slot) const { - return m_indexToSlotTable[slot]; + return m_slotToIndexTable[slot]; } const RHI::ShaderStageMask& PipelineLayout::GetSrgVisibility(uint32_t index) const diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/SwapChain.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/SwapChain.cpp index 1f870548cc..94599bc390 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/SwapChain.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/SwapChain.cpp @@ -73,6 +73,10 @@ namespace AZ m_metalView.metalLayer.drawableSize = CGSizeMake(descriptor.m_dimensions.m_imageWidth, descriptor.m_dimensions.m_imageHeight); } + else + { + AddSubView(); + } m_drawables.resize(descriptor.m_dimensions.m_imageCount); @@ -83,6 +87,20 @@ namespace AZ return RHI::ResultCode::Success; } + void SwapChain::AddSubView() + { + NativeViewType* superView = reinterpret_cast(m_nativeWindow); + + CGFloat screenScale = Platform::GetScreenScale(); + CGRect screenBounds = [superView bounds]; + m_metalView = [[RHIMetalView alloc] initWithFrame: screenBounds + scale: screenScale + device: m_mtlDevice]; + + [m_metalView retain]; + [superView addSubview: m_metalView]; + } + void SwapChain::ShutdownInternal() { if (m_viewController) @@ -161,16 +179,7 @@ namespace AZ } else { - NativeViewType* superView = reinterpret_cast(m_nativeWindow); - - CGFloat screenScale = Platform::GetScreenScale(); - CGRect screenBounds = [superView bounds]; - m_metalView = [[RHIMetalView alloc] initWithFrame: screenBounds - scale: screenScale - device: m_mtlDevice]; - - [m_metalView retain]; - [superView addSubview: m_metalView]; + AddSubView(); } } return RHI::ResultCode::Success; diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/SwapChain.h b/Gems/Atom/RHI/Metal/Code/Source/RHI/SwapChain.h index d455f3dd0c..dfe8b3365d 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/SwapChain.h +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/SwapChain.h @@ -49,6 +49,8 @@ namespace AZ RHI::ResultCode ResizeInternal(const RHI::SwapChainDimensions& dimensions, RHI::SwapChainDimensions* nativeDimensions) override; ////////////////////////////////////////////////////////////////////////// + void AddSubView(); + id m_mtlCommandBuffer; RHIMetalView* m_metalView = nullptr; NativeViewControllerType* m_viewController = nullptr; diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Conversion.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Conversion.cpp index accc18b5ec..7945dd2894 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Conversion.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Conversion.cpp @@ -334,19 +334,19 @@ namespace AZ VkColorComponentFlags ConvertComponentFlags(uint8_t sflags) { VkColorComponentFlags dflags = 0; - if (RHI::CheckBitsAny(sflags, static_cast(1))) + if (RHI::CheckBitsAny(sflags, static_cast(RHI::WriteChannelMask::ColorWriteMaskRed))) { dflags |= VK_COLOR_COMPONENT_R_BIT; } - if (RHI::CheckBitsAny(sflags, static_cast(2))) + if (RHI::CheckBitsAny(sflags, static_cast(RHI::WriteChannelMask::ColorWriteMaskGreen))) { dflags |= VK_COLOR_COMPONENT_G_BIT; } - if (RHI::CheckBitsAny(sflags, static_cast(4))) + if (RHI::CheckBitsAny(sflags, static_cast(RHI::WriteChannelMask::ColorWriteMaskBlue))) { dflags |= VK_COLOR_COMPONENT_B_BIT; } - if (RHI::CheckBitsAny(sflags, static_cast(8))) + if (RHI::CheckBitsAny(sflags, static_cast(RHI::WriteChannelMask::ColorWriteMaskAlpha))) { dflags |= VK_COLOR_COMPONENT_A_BIT; } From 66bbcb08e51991b9140a93a59f9e3a455e962dce Mon Sep 17 00:00:00 2001 From: igarri Date: Wed, 9 Jun 2021 11:02:09 +0100 Subject: [PATCH 030/116] Fixing Thumbnails preview from TableView --- .../AssetBrowser/AssetBrowserTableModel.cpp | 4 +- .../Views/AssetBrowserTreeView.cpp | 7 +-- .../AzAssetBrowser/AzAssetBrowserWindow.cpp | 46 ++++--------------- .../AzAssetBrowser/AzAssetBrowserWindow.h | 1 - 4 files changed, 12 insertions(+), 46 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp index 70d66f4e1f..60f15970b1 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp @@ -95,7 +95,9 @@ namespace AzToolsFramework for (int i = 0; i < rows; ++i) { QModelIndex index = model->index(i, 0, parent); - if (!model->hasChildren(index)) + AssetBrowserEntry* entry = GetAssetEntry(m_filterModel->mapToSource(index)); + //We only wanna see the source assets. + if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Source) { beginInsertRows(parent, row, row); m_indexMap[row] = index; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.cpp index 12a43218d4..026343c2a4 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.cpp @@ -100,16 +100,11 @@ namespace AzToolsFramework AZStd::vector AssetBrowserTreeView::GetSelectedAssets() const { - const QModelIndexList& selectedIndexes = selectionModel()->selectedRows(); QModelIndexList sourceIndexes; for (const auto& index : selectedIndexes) { - //If we check for more than one column then the model will try to select the same entry several times. - if (index.column() == 0) - { - sourceIndexes.push_back(m_assetBrowserSortFilterProxyModel->mapToSource(index)); - } + sourceIndexes.push_back(m_assetBrowserSortFilterProxyModel->mapToSource(index)); } AZStd::vector entries; diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp index 60ff6f9549..1bc8b9d324 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp @@ -97,7 +97,7 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) &AzAssetBrowserWindow::SelectionChangedSlot); connect( m_ui->m_assetBrowserTableViewWidget, &QAbstractItemView::doubleClicked, this, - &AzAssetBrowserWindow::DoubleClickedItemTableModel); + &AzAssetBrowserWindow::DoubleClickedItem); connect( m_ui->m_assetBrowserTableViewWidget, &AzAssetBrowser::AssetBrowserTableView::ClearStringFilter, m_ui->m_searchWidget, &AzAssetBrowser::SearchWidget::ClearStringFilter); @@ -163,7 +163,10 @@ QObject* AzAssetBrowserWindow::createListenerForShowAssetEditorEvent(QObject* pa void AzAssetBrowserWindow::UpdatePreview() const { - auto selectedAssets = m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets(); + const auto& selectedAssets = m_ui->m_assetBrowserTreeViewWidget->isVisible() + ? m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets() + : m_ui->m_assetBrowserTableViewWidget->GetSelectedAssets(); + if (selectedAssets.size() != 1) { m_ui->m_previewerFrame->Clear(); @@ -234,43 +237,10 @@ void AzAssetBrowserWindow::DoubleClickedItem([[maybe_unused]] const QModelIndex& { namespace AzAssetBrowser = AzToolsFramework::AssetBrowser; - // assumption: Double clicking an item selects it before telling us we double clicked it. - const auto& selectedAssets = m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets(); - for (const AzAssetBrowser::AssetBrowserEntry* entry : selectedAssets) - { - AZ::Data::AssetId assetIdToOpen; - AZStd::string fullFilePath; + const auto& selectedAssets = m_ui->m_assetBrowserTreeViewWidget->isVisible() + ? m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets() + : m_ui->m_assetBrowserTableViewWidget->GetSelectedAssets(); - if (const AzAssetBrowser::ProductAssetBrowserEntry* productEntry = azrtti_cast(entry)) - { - assetIdToOpen = productEntry->GetAssetId(); - fullFilePath = entry->GetFullPath(); - } - else if (const AzAssetBrowser::SourceAssetBrowserEntry* sourceEntry = azrtti_cast(entry)) - { - // manufacture an empty AssetID with the source's UUID - assetIdToOpen = AZ::Data::AssetId(sourceEntry->GetSourceUuid(), 0); - fullFilePath = entry->GetFullPath(); - } - - bool handledBySomeone = false; - if (assetIdToOpen.IsValid()) - { - AzAssetBrowser::AssetBrowserInteractionNotificationBus::Broadcast( - &AzAssetBrowser::AssetBrowserInteractionNotifications::OpenAssetInAssociatedEditor, assetIdToOpen, handledBySomeone); - } - - if (!handledBySomeone && !fullFilePath.empty()) - { - AzAssetBrowserRequestHandler::OpenWithOS(fullFilePath); - } - } -} - -void AzAssetBrowserWindow::DoubleClickedItemTableModel([[maybe_unused]] const QModelIndex& element) -{ - namespace AzAssetBrowser = AzToolsFramework::AssetBrowser; - const auto& selectedAssets = m_ui->m_assetBrowserTableViewWidget->GetSelectedAssets(); for (const AzAssetBrowser::AssetBrowserEntry* entry : selectedAssets) { AZ::Data::AssetId assetIdToOpen; diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.h b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.h index 1174335995..57a5371ab9 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.h +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.h @@ -63,7 +63,6 @@ private: private Q_SLOTS: void SelectionChangedSlot(const QItemSelection& selected, const QItemSelection& deselected) const; void DoubleClickedItem(const QModelIndex& element); - void DoubleClickedItemTableModel(const QModelIndex& element); void SwitchDisplayView(bool state); void LockToDefaultView(bool state); }; From dda6fee2276f5e2418159a40dc6f978ddf789ab6 Mon Sep 17 00:00:00 2001 From: gallowj Date: Wed, 9 Jun 2021 09:58:38 -0500 Subject: [PATCH 031/116] fixed a type-o --- Gems/AtomContent/gem.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/AtomContent/gem.json b/Gems/AtomContent/gem.json index 941e7dea20..b043cbbaca 100644 --- a/Gems/AtomContent/gem.json +++ b/Gems/AtomContent/gem.json @@ -8,7 +8,7 @@ "Gem" ], "user_tags": [ - "AtomConent" + "AtomContent" ], "icon_path": "preview.png" } From d5916630b88fc19bd017c9fff6591a3db2a7818a Mon Sep 17 00:00:00 2001 From: gallowj Date: Wed, 9 Jun 2021 14:27:59 -0500 Subject: [PATCH 032/116] Changes related to ATOM-15021, this allows maya on py2.7 to work with .o3de\boostrap changes --- .../Solutions/.wing/DCCsi_7x.wpr | 6 ++++++ .../DccScriptingInterface/azpy/config_utils.py | 8 +++++--- .../DccScriptingInterface/azpy/constants.py | 13 ++++++++++++- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Solutions/.wing/DCCsi_7x.wpr b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Solutions/.wing/DCCsi_7x.wpr index d57e91f35d..aa7a8c4bd9 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Solutions/.wing/DCCsi_7x.wpr +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Solutions/.wing/DCCsi_7x.wpr @@ -69,10 +69,16 @@ proj.launch-config = {loc('../../SDK/Atom/Scripts/Python/DCC_Materials/maya_mate loc('../../azpy/__init__.py'): ('custom', (u'', 'launch-oobMrvXFf1SwtYBg')), + loc('../../azpy/constants.py'): ('custom', + (u'', + 'launch-GeaM41WYMGA1sEfm')), loc('../../azpy/env_base.py'): ('project', (u'', 'launch-GeaM41WYMGA1sEfm')), loc('../../azpy/maya/callbacks/node_message_callback_handler.py'): ('c'\ 'ustom', + (u'', + 'launch-GeaM41WYMGA1sEfm')), + loc('../../config.py'): ('custom', (u'', 'launch-GeaM41WYMGA1sEfm'))} diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/config_utils.py b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/config_utils.py index 0a0c6b8337..5b5c5aa079 100755 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/config_utils.py +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/config_utils.py @@ -165,12 +165,14 @@ def get_current_project(): bootstrap_box = None try: - bootstrap_box = Box.from_json(filename=PATH_USER_O3DE_BOOTSTRAP, + bootstrap_box = Box.from_json(filename=str(Path(PATH_USER_O3DE_BOOTSTRAP).resolve()), encoding="utf-8", errors="strict", object_pairs_hook=OrderedDict) - except FileExistsError as e: - _LOGGER.error('File does not exist: {}'.format(PATH_USER_O3DE_BOOTSTRAP)) + except Exception as e: + # this file runs in py2.7 for Maya 2020, FileExistsError is not defined + _LOGGER.error('FileExistsError: {}'.format(PATH_USER_O3DE_BOOTSTRAP)) + _LOGGER.error('exception is: {}'.format(e)) if bootstrap_box: # this seems fairly hard coded - what if the data changes? diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/constants.py b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/constants.py index e10221d324..7f6b0e4523 100755 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/constants.py +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/constants.py @@ -226,7 +226,18 @@ TAG_DEFAULT_PY = str('Launch_pyBASE.bat') FILENAME_DEFAULT_CONFIG = str('DCCSI_config.json') # new o3de related paths -PATH_USER_O3DE = str('{home}\\{o3de}').format(home=expanduser("~"), +# os.path.expanduser("~") returns different values in py2.7 vs 3 +PATH_USER_HOME = expanduser("~") +_LOGGER.debug('user home: {}'.format(PATH_USER_HOME)) + +# special case, make sure didn't return \documents +parts = os.path.split(PATH_USER_HOME) + +if str(parts[1].lower()) == 'documents': + PATH_USER_HOME = parts[0] + _LOGGER.debug('user home CORRECTED: {}'.format(PATH_USER_HOME)) + +PATH_USER_O3DE = str('{home}\\{o3de}').format(home=PATH_USER_HOME, o3de=TAG_O3DE_FOLDER) PATH_USER_O3DE_REGISTRY = str('{0}\\Registry').format(PATH_USER_O3DE) PATH_USER_O3DE_BOOTSTRAP = str('{reg}\\{file}').format(reg=PATH_USER_O3DE_REGISTRY, From ca475fab80dff4e94fdcfd4334447dc9b2813347 Mon Sep 17 00:00:00 2001 From: moudgils Date: Wed, 9 Jun 2021 15:28:22 -0700 Subject: [PATCH 033/116] Fix Editor crash where the scissor regions is bigger than the metal drawable --- .../RHI/Metal/Code/Source/Platform/Mac/RHI/Metal_RHI_Mac.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/RHI/Metal/Code/Source/Platform/Mac/RHI/Metal_RHI_Mac.cpp b/Gems/Atom/RHI/Metal/Code/Source/Platform/Mac/RHI/Metal_RHI_Mac.cpp index cc8c4c80c0..b81c51a57b 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/Platform/Mac/RHI/Metal_RHI_Mac.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/Platform/Mac/RHI/Metal_RHI_Mac.cpp @@ -94,7 +94,7 @@ namespace Platform void ResizeInternal(RHIMetalView* metalView, CGSize viewSize) { - [metalView resizeSubviewsWithOldSize:viewSize]; + [metalView.metalLayer setDrawableSize: viewSize]; } RHIMetalView* GetMetalView(NativeWindowType* nativeWindow) From a55edd518ace92f3ef6de5e660271b5d7be49376 Mon Sep 17 00:00:00 2001 From: moudgils Date: Wed, 9 Jun 2021 18:35:52 -0700 Subject: [PATCH 034/116] Update some comments --- Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp | 3 ++- Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.h | 2 ++ Gems/Atom/RHI/Metal/Code/Source/RHI/CommandList.cpp | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp index 5d6c275184..6bdb5a4aa8 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp @@ -386,8 +386,9 @@ namespace AZ void ArgumentBuffer::AddUntrackedResourcesToEncoder(id commandEncoder, const ShaderResourceGroupVisibility& srgResourcesVisInfo) const { - + //Map tp cache all the resoources based on the usage as we can batch all the resources for a given usage ComputeResourcesToMakeResidentMap resourcesToMakeResidentCompute; + //Map tp cache all the resoources based on the usage and shader stage as we can batch all the resources for a given usage/shader usage GraphicsResourcesToMakeResidentMap resourcesToMakeResidentGraphics; //Cache the constant buffer associated with a srg diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.h b/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.h index 06380162b6..eab9389e9b 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.h +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.h @@ -125,7 +125,9 @@ namespace AZ AZStd::array, MaxEntriesInArgTable> m_resourceArray; int m_resourceArrayLen = 0; }; + //Map tp cache all the resoources based on the usage as we can batch all the resources for a given usage using ComputeResourcesToMakeResidentMap = AZStd::unordered_map; + //Map tp cache all the resoources based on the usage and shader stage as we can batch all the resources for a given usage/shader usage using GraphicsResourcesToMakeResidentMap = AZStd::unordered_map, MetalResourceArray>; void CollectResourcesForCompute(id encoder, const ResourceBindingsSet& resourceBindingData, ComputeResourcesToMakeResidentMap& resourcesToMakeResidentMap) const; diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandList.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandList.cpp index 7df8f1e547..5546be1bd9 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandList.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandList.cpp @@ -255,6 +255,7 @@ namespace AZ uint32_t bufferVertexRegisterIdMax = 0; uint32_t bufferFragmentOrComputeRegisterIdMax = 0; + //Arrays to cache all the buffers and offsets in order to make batch calls MetalArgumentBufferArray mtlVertexArgBuffers; MetalArgumentBufferArrayOffsets mtlVertexArgBufferOffsets; MetalArgumentBufferArray mtlFragmentOrComputeArgBuffers; @@ -298,7 +299,6 @@ namespace AZ mtlVertexArgBufferOffsets[slotIndex] = argBufferOffset; bufferVertexRegisterIdMin = AZStd::min(slotIndex, bufferVertexRegisterIdMin); bufferVertexRegisterIdMax = AZStd::max(slotIndex, bufferVertexRegisterIdMax); - } if( numBitsSet > 1 || srgVisInfo == RHI::ShaderStageMask::Fragment) @@ -595,7 +595,7 @@ namespace AZ AZ_Assert(count <= METAL_MAX_ENTRIES_BUFFER_ARG_TABLE , "Slots needed cannot exceed METAL_MAX_ENTRIES_BUFFER_ARG_TABLE"); NSRange range = {METAL_MAX_ENTRIES_BUFFER_ARG_TABLE - count, count}; - //For metal the stream buffers are populated from bottom to top as the top slots are taken by argument buffers + //The stream buffers are populated from bottom to top as the top slots are taken by argument buffers for (int i = count-1; i >= 0; --i) { if (streams[i].GetBuffer()) From 8e3a68a34f02903942622ee4863d62433c7bf325 Mon Sep 17 00:00:00 2001 From: moudgils Date: Wed, 9 Jun 2021 18:37:27 -0700 Subject: [PATCH 035/116] Fix comment spelling --- Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp | 4 ++-- Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp index 6bdb5a4aa8..068bc5f162 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp @@ -386,9 +386,9 @@ namespace AZ void ArgumentBuffer::AddUntrackedResourcesToEncoder(id commandEncoder, const ShaderResourceGroupVisibility& srgResourcesVisInfo) const { - //Map tp cache all the resoources based on the usage as we can batch all the resources for a given usage + //Map to cache all the resources based on the usage as we can batch all the resources for a given usage ComputeResourcesToMakeResidentMap resourcesToMakeResidentCompute; - //Map tp cache all the resoources based on the usage and shader stage as we can batch all the resources for a given usage/shader usage + //Map to cache all the resources based on the usage and shader stage as we can batch all the resources for a given usage/shader usage GraphicsResourcesToMakeResidentMap resourcesToMakeResidentGraphics; //Cache the constant buffer associated with a srg diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.h b/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.h index eab9389e9b..7cc77ae478 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.h +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.h @@ -125,9 +125,9 @@ namespace AZ AZStd::array, MaxEntriesInArgTable> m_resourceArray; int m_resourceArrayLen = 0; }; - //Map tp cache all the resoources based on the usage as we can batch all the resources for a given usage + //Map to cache all the resources based on the usage as we can batch all the resources for a given usage using ComputeResourcesToMakeResidentMap = AZStd::unordered_map; - //Map tp cache all the resoources based on the usage and shader stage as we can batch all the resources for a given usage/shader usage + //Map to cache all the resources based on the usage and shader stage as we can batch all the resources for a given usage/shader usage using GraphicsResourcesToMakeResidentMap = AZStd::unordered_map, MetalResourceArray>; void CollectResourcesForCompute(id encoder, const ResourceBindingsSet& resourceBindingData, ComputeResourcesToMakeResidentMap& resourcesToMakeResidentMap) const; From 5a53c074c2fc938ff84600dbbadd2fbb003af563 Mon Sep 17 00:00:00 2001 From: igarri Date: Thu, 10 Jun 2021 15:14:35 +0100 Subject: [PATCH 036/116] Fixing Header Data in AssetBrowserTableModel --- .../AssetBrowser/AssetBrowserTableModel.cpp | 11 +- .../AssetBrowser/AssetBrowserTableModel.h | 3 + .../AzAssetBrowser/AzAssetBrowserWindow.ui | 424 +++++++++--------- 3 files changed, 222 insertions(+), 216 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp index 60f15970b1..d22486d481 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp @@ -46,16 +46,7 @@ namespace AzToolsFramework { if (role == Qt::DisplayRole && orientation == Qt::Horizontal) { - auto columnRole = aznumeric_cast(role); - switch (columnRole) - { - case AssetBrowserEntry::Column::Name: - return tr("Name"); - case AssetBrowserEntry::Column::Path: - return tr("Path"); - default: - return QString::number(section); - } + return tr(AssetBrowserEntry::m_columnNames[section]); } return QSortFilterProxyModel::headerData(section, orientation, role); } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h index 6b64ceaf92..e438bf6271 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h @@ -38,8 +38,10 @@ namespace AzToolsFramework QModelIndex mapToSource(const QModelIndex& proxyIndex) const override; QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + public Q_SLOTS: void UpdateTableModelMaps(); + protected: int rowCount(const QModelIndex& parent = QModelIndex()) const override; QVariant headerData(int section, Qt::Orientation orientation, int role /* = Qt::DisplayRole */) const override; @@ -48,6 +50,7 @@ namespace AzToolsFramework private: AssetBrowserEntry* GetAssetEntry(QModelIndex index) const; int BuildTableModelMap(const QAbstractItemModel* model, const QModelIndex& parent = QModelIndex(), int row = 0); + private: QPointer m_filterModel; QMap m_indexMap; diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.ui b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.ui index d9e42ef906..37eb1521f3 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.ui +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.ui @@ -1,211 +1,223 @@ - AzAssetBrowserWindowClass - - - - 0 - 0 - 691 - 554 - - - - Asset Browser - - - - 0 - - - - - - 1 - 1 - - - - true - - - - - 0 - 0 - 671 - 534 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - 0 - 0 - - - - - - - - Switch View - - - - - - - - - - 0 - 0 - - - - Qt::Horizontal - - - false - - - - - 0 - 0 - - - - vertical-align: top - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed - - - QAbstractItemView::DropOnly - - - QAbstractItemView::SingleSelection - - - QAbstractItemView::SelectRows - - - QAbstractItemView::ScrollPerPixel - - - false - - - true - - - - - - - - 1 - 0 - - - - QAbstractItemView::DragOnly - - - - - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - - - - + AzAssetBrowserWindowClass + + + + 0 + 0 + 691 + 554 + + + + Asset Browser + + + + 0 + + + + + + 1 + 1 + + + + true + + + + + 0 + 0 + 671 + 534 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + 0 + 0 + + + + + + + + Switch View + + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + false + + + + + 0 + 0 + + + + vertical-align: top + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed + + + false + + + QAbstractItemView::DragOnly + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + QAbstractItemView::ScrollPerPixel + + + false + + + true + + + false + + + true + + + false + + + + + + + + 1 + 0 + + + + QAbstractItemView::DragOnly + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + - - - AzToolsFramework::AssetBrowser::SearchWidget - QWidget -
AzToolsFramework/AssetBrowser/Search/SearchWidget.h
- 1 -
- - AzToolsFramework::AssetBrowser::AssetBrowserTreeView - QTreeView -
AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.h
-
- - AzToolsFramework::AssetBrowser::PreviewerFrame - QFrame -
AzToolsFramework/AssetBrowser/Previewer/PreviewerFrame.h
- 1 -
- - AzToolsFramework::AssetBrowser::AssetBrowserTableView - QTableView -
AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h
-
-
- - +
+
+
+ + + AzToolsFramework::AssetBrowser::SearchWidget + QWidget +
AzToolsFramework/AssetBrowser/Search/SearchWidget.h
+ 1 +
+ + AzToolsFramework::AssetBrowser::AssetBrowserTreeView + QTreeView +
AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.h
+
+ + AzToolsFramework::AssetBrowser::PreviewerFrame + QFrame +
AzToolsFramework/AssetBrowser/Previewer/PreviewerFrame.h
+ 1 +
+ + AzToolsFramework::AssetBrowser::AssetBrowserTableView + QTableView +
AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h
+
+
+ +
From 3b249844d538cf10479eee5d869e50c8f225e353 Mon Sep 17 00:00:00 2001 From: moudgils Date: Thu, 10 Jun 2021 11:02:45 -0700 Subject: [PATCH 037/116] Minor formatting cleanup --- .../PostProcessing/LuminanceHeatmap.azsl | 2 +- .../Metal/Code/Source/RHI/ArgumentBuffer.cpp | 28 +++++++++++++----- .../Metal/Code/Source/RHI/ArgumentBuffer.h | 2 +- .../RHI/Metal/Code/Source/RHI/CommandList.cpp | 29 +++++++++++++++---- 4 files changed, 47 insertions(+), 14 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHeatmap.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHeatmap.azsl index 4559b6c9ef..4238392004 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHeatmap.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHeatmap.azsl @@ -1,4 +1,4 @@ - /* +/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp index 068bc5f162..680481d417 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp @@ -399,13 +399,17 @@ namespace AZ { if(RHI::CheckBitsAny(srgResourcesVisInfo.m_constantDataStageMask, RHI::ShaderStageMask::Compute)) { - resourcesToMakeResidentCompute[MTLResourceUsageRead].m_resourceArray[resourcesToMakeResidentCompute[MTLResourceUsageRead].m_resourceArrayLen++] = m_constantBuffer.GetGpuAddress>(); + uint16_t arrayIndex = resourcesToMakeResidentCompute[MTLResourceUsageRead].m_resourceArrayLen; + resourcesToMakeResidentCompute[MTLResourceUsageRead].m_resourceArray[arrayIndex] = m_constantBuffer.GetGpuAddress>(); + resourcesToMakeResidentCompute[MTLResourceUsageRead].m_resourceArrayLen++; } else { MTLRenderStages mtlRenderStages = GetRenderStages(srgResourcesVisInfo.m_constantDataStageMask); AZStd::pair key = AZStd::make_pair(MTLResourceUsageRead, mtlRenderStages); - resourcesToMakeResidentGraphics[key].m_resourceArray[resourcesToMakeResidentGraphics[key].m_resourceArrayLen++] = m_constantBuffer.GetGpuAddress>(); + uint16_t arrayIndex = resourcesToMakeResidentGraphics[key].m_resourceArrayLen; + resourcesToMakeResidentGraphics[key].m_resourceArray[arrayIndex] = m_constantBuffer.GetGpuAddress>(); + resourcesToMakeResidentGraphics[key].m_resourceArrayLen++; } } } @@ -451,7 +455,9 @@ namespace AZ } } - void ArgumentBuffer::CollectResourcesForCompute(id encoder, const ResourceBindingsSet& resourceBindingDataSet, ComputeResourcesToMakeResidentMap& resourcesToMakeResidentMap) const + void ArgumentBuffer::CollectResourcesForCompute(id encoder, + const ResourceBindingsSet& resourceBindingDataSet, + ComputeResourcesToMakeResidentMap& resourcesToMakeResidentMap) const { for (const auto& resourceBindingData : resourceBindingDataSet) { @@ -474,11 +480,16 @@ namespace AZ AZ_Assert(false, "Undefined Resource type"); } } - resourcesToMakeResidentMap[resourceUsage].m_resourceArray[resourcesToMakeResidentMap[resourceUsage].m_resourceArrayLen++] = resourceBindingData.m_resourcPtr->GetGpuAddress>(); + uint16_t arrayIndex = resourcesToMakeResidentMap[resourceUsage].m_resourceArrayLen; + resourcesToMakeResidentMap[resourceUsage].m_resourceArray[arrayIndex] = resourceBindingData.m_resourcPtr->GetGpuAddress>(); + resourcesToMakeResidentMap[resourceUsage].m_resourceArrayLen++; } } - void ArgumentBuffer::CollectResourcesForGraphics(id encoder, RHI::ShaderStageMask visShaderMask, const ResourceBindingsSet& resourceBindingDataSet, GraphicsResourcesToMakeResidentMap& resourcesToMakeResidentMap) const + void ArgumentBuffer::CollectResourcesForGraphics(id encoder, + RHI::ShaderStageMask visShaderMask, + const ResourceBindingsSet& resourceBindingDataSet, + GraphicsResourcesToMakeResidentMap& resourcesToMakeResidentMap) const { MTLRenderStages mtlRenderStages = GetRenderStages(visShaderMask); @@ -503,8 +514,11 @@ namespace AZ AZ_Assert(false, "Undefined Resource type"); } } - AZStd::pair key = AZStd::make_pair(resourceUsage, mtlRenderStages); - resourcesToMakeResidentMap[key].m_resourceArray[resourcesToMakeResidentMap[key].m_resourceArrayLen++] = resourceBindingData.m_resourcPtr->GetGpuAddress>(); + + AZStd::pair key = AZStd::make_pair(resourceUsage, mtlRenderStages); + uint16_t arrayIndex = resourcesToMakeResidentMap[key].m_resourceArrayLen; + resourcesToMakeResidentMap[key].m_resourceArray[arrayIndex] = resourceBindingData.m_resourcPtr->GetGpuAddress>(); + resourcesToMakeResidentMap[key].m_resourceArrayLen++; } } } diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.h b/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.h index 7cc77ae478..0825c07654 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.h +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.h @@ -123,7 +123,7 @@ namespace AZ struct MetalResourceArray { AZStd::array, MaxEntriesInArgTable> m_resourceArray; - int m_resourceArrayLen = 0; + uint16_t m_resourceArrayLen = 0; }; //Map to cache all the resources based on the usage as we can batch all the resources for a given usage using ComputeResourcesToMakeResidentMap = AZStd::unordered_map; diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandList.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandList.cpp index 5546be1bd9..7f65c9ea47 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandList.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandList.cpp @@ -347,18 +347,35 @@ namespace AZ //For graphics and compute encoder bind all the argument buffers if(m_commandEncoderType == CommandEncoderType::Render) { - BindArgumentBuffers(RHI::ShaderStage::Vertex, bufferVertexRegisterIdMin, bufferVertexRegisterIdMax, mtlVertexArgBuffers, mtlVertexArgBufferOffsets); - BindArgumentBuffers(RHI::ShaderStage::Fragment, bufferFragmentOrComputeRegisterIdMin, bufferFragmentOrComputeRegisterIdMax, mtlFragmentOrComputeArgBuffers, mtlFragmentOrComputeArgBufferOffsets); + BindArgumentBuffers(RHI::ShaderStage::Vertex, + bufferVertexRegisterIdMin, + bufferVertexRegisterIdMax, + mtlVertexArgBuffers, + mtlVertexArgBufferOffsets); + + BindArgumentBuffers(RHI::ShaderStage::Fragment, + bufferFragmentOrComputeRegisterIdMin, + bufferFragmentOrComputeRegisterIdMax, + mtlFragmentOrComputeArgBuffers, + mtlFragmentOrComputeArgBufferOffsets); } else if(m_commandEncoderType == CommandEncoderType::Compute) { - BindArgumentBuffers(RHI::ShaderStage::Compute, bufferFragmentOrComputeRegisterIdMin, bufferFragmentOrComputeRegisterIdMax, mtlFragmentOrComputeArgBuffers, mtlFragmentOrComputeArgBufferOffsets); + BindArgumentBuffers(RHI::ShaderStage::Compute, + bufferFragmentOrComputeRegisterIdMin, + bufferFragmentOrComputeRegisterIdMax, + mtlFragmentOrComputeArgBuffers, + mtlFragmentOrComputeArgBufferOffsets); } return true; } - void CommandList::BindArgumentBuffers(RHI::ShaderStage shaderStage, uint16_t registerIdMin, uint16_t registerIdMax, MetalArgumentBufferArray& mtlArgBuffers, MetalArgumentBufferArrayOffsets mtlArgBufferOffsets) + void CommandList::BindArgumentBuffers(RHI::ShaderStage shaderStage, + uint16_t registerIdMin, + uint16_t registerIdMax, + MetalArgumentBufferArray& mtlArgBuffers, + MetalArgumentBufferArrayOffsets mtlArgBufferOffsets) { //Metal Api only lets you bind multiple argument buffers in an array as long as there are no gaps in the array //In order to accomodate that we break up the calls when a gap is noticed in the array and reconfigure the NSRange. @@ -609,7 +626,9 @@ namespace AZ } } id renderEncoder = GetEncoder>(); - [renderEncoder setVertexBuffers: mtlStreamBuffers.data() offsets: mtlStreamBufferOffsets.data() withRange: range]; + [renderEncoder setVertexBuffers: mtlStreamBuffers.data() + offsets: mtlStreamBufferOffsets.data() + withRange: range]; } } From bbae6490d974c8d7084a9c615be5d0334f2b19e6 Mon Sep 17 00:00:00 2001 From: srikappa-amzn Date: Thu, 10 Jun 2021 14:38:14 -0700 Subject: [PATCH 038/116] Enabled LyTestTools trait only for windows and mac --- cmake/Platform/Android/PAL_android.cmake | 1 + cmake/Platform/Linux/PAL_linux.cmake | 1 + cmake/Platform/Mac/PAL_mac.cmake | 1 + cmake/Platform/Windows/PAL_windows.cmake | 1 + cmake/Platform/iOS/PAL_ios.cmake | 1 + scripts/ctest/CMakeLists.txt | 24 +++++++++++++----------- 6 files changed, 18 insertions(+), 11 deletions(-) diff --git a/cmake/Platform/Android/PAL_android.cmake b/cmake/Platform/Android/PAL_android.cmake index 5f35767f98..dd61e35e53 100644 --- a/cmake/Platform/Android/PAL_android.cmake +++ b/cmake/Platform/Android/PAL_android.cmake @@ -24,6 +24,7 @@ ly_set(PAL_TRAIT_BUILD_CPACK_SUPPORTED FALSE) # Test library support ly_set(PAL_TRAIT_TEST_GOOGLE_TEST_SUPPORTED FALSE) ly_set(PAL_TRAIT_TEST_GOOGLE_BENCHMARK_SUPPORTED FALSE) +ly_set(PAL_TRAIT_TEST_LYTESTTOOLS_SUPPORTED FALSE) ly_set(PAL_TRAIT_TEST_PYTEST_SUPPORTED FALSE) ly_set(PAL_TRAIT_TEST_TARGET_TYPE MODULE) diff --git a/cmake/Platform/Linux/PAL_linux.cmake b/cmake/Platform/Linux/PAL_linux.cmake index 40b73adcec..c15f2bada9 100644 --- a/cmake/Platform/Linux/PAL_linux.cmake +++ b/cmake/Platform/Linux/PAL_linux.cmake @@ -24,6 +24,7 @@ ly_set(PAL_TRAIT_BUILD_CPACK_SUPPORTED FALSE) # Test library support ly_set(PAL_TRAIT_TEST_GOOGLE_TEST_SUPPORTED TRUE) ly_set(PAL_TRAIT_TEST_GOOGLE_BENCHMARK_SUPPORTED TRUE) +ly_set(PAL_TRAIT_TEST_LYTESTTOOLS_SUPPORTED FALSE) ly_set(PAL_TRAIT_TEST_PYTEST_SUPPORTED TRUE) ly_set(PAL_TRAIT_TEST_TARGET_TYPE MODULE) diff --git a/cmake/Platform/Mac/PAL_mac.cmake b/cmake/Platform/Mac/PAL_mac.cmake index 988d36af14..f49578a83a 100644 --- a/cmake/Platform/Mac/PAL_mac.cmake +++ b/cmake/Platform/Mac/PAL_mac.cmake @@ -24,6 +24,7 @@ ly_set(PAL_TRAIT_BUILD_CPACK_SUPPORTED FALSE) # Test library support ly_set(PAL_TRAIT_TEST_GOOGLE_TEST_SUPPORTED TRUE) ly_set(PAL_TRAIT_TEST_GOOGLE_BENCHMARK_SUPPORTED TRUE) +ly_set(PAL_TRAIT_TEST_LYTESTTOOLS_SUPPORTED TRUE) ly_set(PAL_TRAIT_TEST_PYTEST_SUPPORTED FALSE) ly_set(PAL_TRAIT_TEST_TARGET_TYPE MODULE) diff --git a/cmake/Platform/Windows/PAL_windows.cmake b/cmake/Platform/Windows/PAL_windows.cmake index ddcc3a27c7..fbf65db63f 100644 --- a/cmake/Platform/Windows/PAL_windows.cmake +++ b/cmake/Platform/Windows/PAL_windows.cmake @@ -24,6 +24,7 @@ ly_set(PAL_TRAIT_BUILD_CPACK_SUPPORTED TRUE) # Test library support ly_set(PAL_TRAIT_TEST_GOOGLE_TEST_SUPPORTED TRUE) ly_set(PAL_TRAIT_TEST_GOOGLE_BENCHMARK_SUPPORTED TRUE) +ly_set(PAL_TRAIT_TEST_LYTESTTOOLS_SUPPORTED TRUE) ly_set(PAL_TRAIT_TEST_PYTEST_SUPPORTED TRUE) ly_set(PAL_TRAIT_TEST_TARGET_TYPE MODULE) diff --git a/cmake/Platform/iOS/PAL_ios.cmake b/cmake/Platform/iOS/PAL_ios.cmake index a6828a1bc7..981bb9cab1 100644 --- a/cmake/Platform/iOS/PAL_ios.cmake +++ b/cmake/Platform/iOS/PAL_ios.cmake @@ -24,6 +24,7 @@ ly_set(PAL_TRAIT_BUILD_CPACK_SUPPORTED FALSE) # Test library support ly_set(PAL_TRAIT_TEST_GOOGLE_TEST_SUPPORTED FALSE) ly_set(PAL_TRAIT_TEST_GOOGLE_BENCHMARK_SUPPORTED FALSE) +ly_set(PAL_TRAIT_TEST_LYTESTTOOLS_SUPPORTED FALSE) ly_set(PAL_TRAIT_TEST_PYTEST_SUPPORTED FALSE) ly_set(PAL_TRAIT_TEST_TARGET_TYPE MODULE) diff --git a/scripts/ctest/CMakeLists.txt b/scripts/ctest/CMakeLists.txt index 575be53cc7..c4f86087b1 100644 --- a/scripts/ctest/CMakeLists.txt +++ b/scripts/ctest/CMakeLists.txt @@ -21,18 +21,20 @@ endif() ################################################################################ foreach(suite_name ${LY_TEST_GLOBAL_KNOWN_SUITE_NAMES}) - ly_add_pytest( - NAME pytest_sanity_${suite_name}_no_gpu - PATH ${CMAKE_CURRENT_LIST_DIR}/sanity_test.py - TEST_SUITE ${suite_name} - ) + if(PAL_TRAIT_TEST_LYTESTTOOLS_SUPPORTED) + ly_add_pytest( + NAME pytest_sanity_${suite_name}_no_gpu + PATH ${CMAKE_CURRENT_LIST_DIR}/sanity_test.py + TEST_SUITE ${suite_name} + ) - ly_add_pytest( - NAME pytest_sanity_${suite_name}_requires_gpu - PATH ${CMAKE_CURRENT_LIST_DIR}/sanity_test.py - TEST_SUITE ${suite_name} - TEST_REQUIRES gpu - ) + ly_add_pytest( + NAME pytest_sanity_${suite_name}_requires_gpu + PATH ${CMAKE_CURRENT_LIST_DIR}/sanity_test.py + TEST_SUITE ${suite_name} + TEST_REQUIRES gpu + ) + endif() endforeach() # EPB Sanity test is being registered here to validate that the ly_add_editor_python_test function works. From b18b03b8fb8d1a79d14fead2475fea25d1c4b660 Mon Sep 17 00:00:00 2001 From: moudgils Date: Thu, 10 Jun 2021 14:40:52 -0700 Subject: [PATCH 039/116] Added comments and more format fixes --- .../Shaders/MorphTargets/MorphTargetSRG.azsli | 3 +++ .../LuminanceHistogramGenerator.azsl | 4 +++ .../RHI/DX12/Code/Source/RHI/Conversions.cpp | 10 +++++++ .../Metal/Code/Source/RHI/ArgumentBuffer.cpp | 26 +++++++++---------- .../Metal/Code/Source/RHI/ArgumentBuffer.h | 13 +++++++--- .../RHI/Metal/Code/Source/RHI/CommandList.h | 6 ++++- .../RHI/Metal/Code/Source/RHI/Conversions.cpp | 10 +++++++ .../RHI/Vulkan/Code/Source/RHI/Conversion.cpp | 6 +++++ 8 files changed, 60 insertions(+), 18 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/MorphTargets/MorphTargetSRG.azsli b/Gems/Atom/Feature/Common/Assets/Shaders/MorphTargets/MorphTargetSRG.azsli index 83193c8559..f4b1beeb3e 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/MorphTargets/MorphTargetSRG.azsli +++ b/Gems/Atom/Feature/Common/Assets/Shaders/MorphTargets/MorphTargetSRG.azsli @@ -16,6 +16,9 @@ ShaderResourceGroup MorphTargetPassSrg : SRG_PerPass { + //Since we do Interlocked atomic operations on this buffer it can not be RWBuffer due to broken MetalSL generation. + //It stems from the fact that typed buffers gets converted to textures and that breaks with atomic operations. + //In future we can handle this under the hood via our metal shader pipeline RWStructuredBuffer m_accumulatedDeltas; } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.azsl index 9d01a12fd6..ee95515a2a 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.azsl @@ -20,6 +20,10 @@ ShaderResourceGroup PassSrg : SRG_PerPass { Texture2D m_inputTexture; + + //Since we do Interlocked atomic operations on this buffer it can not be RWBuffer due to broken MetalSL generation. + //It stems from the fact that typed buffers gets converted to textures and that breaks with atomic operations. + //In future we can handle this under the hood via our metal shader pipeline RWStructuredBuffer m_outputTexture; } diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.cpp index 73d80ed78c..9776734158 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.cpp @@ -1360,6 +1360,16 @@ namespace AZ uint32_t ConvertColorWriteMask(uint8_t writeMask) { uint32_t dflags = 0; + if(writeMask == 0) + { + return dflags; + } + + if(RHI::CheckBitsAll(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskAll))) + { + return D3D12_COLOR_WRITE_ENABLE_ALL; + } + if (RHI::CheckBitsAny(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskRed))) { dflags |= D3D12_COLOR_WRITE_ENABLE_RED; diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp index 680481d417..49ff4146fc 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp @@ -397,19 +397,18 @@ namespace AZ uint8_t numBitsSet = RHI::CountBitsSet(static_cast(srgResourcesVisInfo.m_constantDataStageMask)); if( numBitsSet > 0) { + id mtlconstantBufferResource = m_constantBuffer.GetGpuAddress>(); if(RHI::CheckBitsAny(srgResourcesVisInfo.m_constantDataStageMask, RHI::ShaderStageMask::Compute)) { - uint16_t arrayIndex = resourcesToMakeResidentCompute[MTLResourceUsageRead].m_resourceArrayLen; - resourcesToMakeResidentCompute[MTLResourceUsageRead].m_resourceArray[arrayIndex] = m_constantBuffer.GetGpuAddress>(); - resourcesToMakeResidentCompute[MTLResourceUsageRead].m_resourceArrayLen++; + uint16_t arrayIndex = resourcesToMakeResidentCompute[MTLResourceUsageRead].m_resourceArrayLen++; + resourcesToMakeResidentCompute[MTLResourceUsageRead].m_resourceArray[arrayIndex] = mtlconstantBufferResource; } else { MTLRenderStages mtlRenderStages = GetRenderStages(srgResourcesVisInfo.m_constantDataStageMask); AZStd::pair key = AZStd::make_pair(MTLResourceUsageRead, mtlRenderStages); - uint16_t arrayIndex = resourcesToMakeResidentGraphics[key].m_resourceArrayLen; - resourcesToMakeResidentGraphics[key].m_resourceArray[arrayIndex] = m_constantBuffer.GetGpuAddress>(); - resourcesToMakeResidentGraphics[key].m_resourceArrayLen++; + uint16_t arrayIndex = resourcesToMakeResidentGraphics[key].m_resourceArrayLen++; + resourcesToMakeResidentGraphics[key].m_resourceArray[arrayIndex] = mtlconstantBufferResource; } } } @@ -431,7 +430,8 @@ namespace AZ } else { - AZ_Assert(RHI::CheckBitsAny(visMaskIt->second, RHI::ShaderStageMask::Vertex) || RHI::CheckBitsAny(visMaskIt->second, RHI::ShaderStageMask::Fragment), "The visibility mask %i is not set for Vertex or fragment stage", visMaskIt->second); + bool isBoundToGraphics = RHI::CheckBitsAny(visMaskIt->second, RHI::ShaderStageMask::Vertex) || RHI::CheckBitsAny(visMaskIt->second, RHI::ShaderStageMask::Fragment); + AZ_Assert(isBoundToGraphics, "The visibility mask %i is not set for Vertex or fragment stage", visMaskIt->second); CollectResourcesForGraphics(commandEncoder, visMaskIt->second, it.second, resourcesToMakeResidentGraphics); } } @@ -480,9 +480,9 @@ namespace AZ AZ_Assert(false, "Undefined Resource type"); } } - uint16_t arrayIndex = resourcesToMakeResidentMap[resourceUsage].m_resourceArrayLen; - resourcesToMakeResidentMap[resourceUsage].m_resourceArray[arrayIndex] = resourceBindingData.m_resourcPtr->GetGpuAddress>(); - resourcesToMakeResidentMap[resourceUsage].m_resourceArrayLen++; + uint16_t arrayIndex = resourcesToMakeResidentMap[resourceUsage].m_resourceArrayLen++; + id mtlResourceToBind = resourceBindingData.m_resourcPtr->GetGpuAddress>(); + resourcesToMakeResidentMap[resourceUsage].m_resourceArray[arrayIndex] = mtlResourceToBind; } } @@ -516,9 +516,9 @@ namespace AZ } AZStd::pair key = AZStd::make_pair(resourceUsage, mtlRenderStages); - uint16_t arrayIndex = resourcesToMakeResidentMap[key].m_resourceArrayLen; - resourcesToMakeResidentMap[key].m_resourceArray[arrayIndex] = resourceBindingData.m_resourcPtr->GetGpuAddress>(); - resourcesToMakeResidentMap[key].m_resourceArrayLen++; + uint16_t arrayIndex = resourcesToMakeResidentMap[key].m_resourceArrayLen++; + id mtlResourceToBind = resourceBindingData.m_resourcPtr->GetGpuAddress>(); + resourcesToMakeResidentMap[key].m_resourceArray[arrayIndex] = mtlResourceToBind; } } } diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.h b/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.h index 0825c07654..c4cfd17390 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.h +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.h @@ -126,12 +126,17 @@ namespace AZ uint16_t m_resourceArrayLen = 0; }; //Map to cache all the resources based on the usage as we can batch all the resources for a given usage - using ComputeResourcesToMakeResidentMap = AZStd::unordered_map; + using ComputeResourcesToMakeResidentMap = AZStd::unordered_map; //Map to cache all the resources based on the usage and shader stage as we can batch all the resources for a given usage/shader usage - using GraphicsResourcesToMakeResidentMap = AZStd::unordered_map, MetalResourceArray>; + using GraphicsResourcesToMakeResidentMap = AZStd::unordered_map, MetalResourceArray>; - void CollectResourcesForCompute(id encoder, const ResourceBindingsSet& resourceBindingData, ComputeResourcesToMakeResidentMap& resourcesToMakeResidentMap) const; - void CollectResourcesForGraphics(id encoder, RHI::ShaderStageMask visShaderMask, const ResourceBindingsSet& resourceBindingDataSet, GraphicsResourcesToMakeResidentMap& resourcesToMakeResidentMap) const; + void CollectResourcesForCompute(id encoder, + const ResourceBindingsSet& resourceBindingData, + ComputeResourcesToMakeResidentMap& resourcesToMakeResidentMap) const; + void CollectResourcesForGraphics(id encoder, + RHI::ShaderStageMask visShaderMask, + const ResourceBindingsSet& resourceBindingDataSet, + GraphicsResourcesToMakeResidentMap& resourcesToMakeResidentMap) const; //! Use visibility information to call UseResource on all resources for this Argument Buffer void ApplyUseResource(id encoder, const ResourceBindingsMap& resourceMap, diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandList.h b/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandList.h index 9dd14cd175..8674124cc2 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandList.h +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandList.h @@ -104,7 +104,11 @@ namespace AZ using MetalArgumentBufferArray = AZStd::array, RHI::Limits::Pipeline::ShaderResourceGroupCountMax>; using MetalArgumentBufferArrayOffsets = AZStd::array; - void BindArgumentBuffers(RHI::ShaderStage shaderStage, uint16_t registerIdMin, uint16_t registerIdMax, MetalArgumentBufferArray& mtlArgBuffers, MetalArgumentBufferArrayOffsets mtlArgBufferOffsets); + void BindArgumentBuffers(RHI::ShaderStage shaderStage, + uint16_t registerIdMin, + uint16_t registerIdMax, + MetalArgumentBufferArray& mtlArgBuffers, + MetalArgumentBufferArrayOffsets mtlArgBufferOffsets); ShaderResourceBindings& GetShaderResourceBindingsByPipelineType(RHI::PipelineStateType pipelineType); diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/Conversions.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/Conversions.cpp index e41ba9bf2a..81e589e62e 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/Conversions.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/Conversions.cpp @@ -458,6 +458,16 @@ namespace AZ MTLColorWriteMask ConvertColorWriteMask(AZ::u8 writeMask) { MTLColorWriteMask colorMask = MTLColorWriteMaskNone; + if(writeMask == 0) + { + return colorMask; + } + + if(RHI::CheckBitsAll(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskAll))) + { + return MTLColorWriteMaskAll; + } + if (RHI::CheckBitsAny(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskRed))) { colorMask |= MTLColorWriteMaskRed; diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Conversion.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Conversion.cpp index 7945dd2894..5ce9731506 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Conversion.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Conversion.cpp @@ -334,6 +334,12 @@ namespace AZ VkColorComponentFlags ConvertComponentFlags(uint8_t sflags) { VkColorComponentFlags dflags = 0; + + if(sflags == 0) + { + return dflags; + } + if (RHI::CheckBitsAny(sflags, static_cast(RHI::WriteChannelMask::ColorWriteMaskRed))) { dflags |= VK_COLOR_COMPONENT_R_BIT; From 963894c7e3edbbca9f2891a6412b56a9c92eae31 Mon Sep 17 00:00:00 2001 From: moudgils Date: Thu, 10 Jun 2021 15:00:42 -0700 Subject: [PATCH 040/116] Modified the WriteColoorMask --- Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.cpp | 10 +++++----- Gems/Atom/RHI/Metal/Code/Source/RHI/Conversions.cpp | 10 +++++----- Gems/Atom/RHI/Vulkan/Code/Source/RHI/Conversion.cpp | 13 +++++++++---- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.cpp index 9776734158..8c7b9f4389 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.cpp @@ -1365,24 +1365,24 @@ namespace AZ return dflags; } - if(RHI::CheckBitsAll(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskAll))) + if(RHI::CheckBitsAll(writeMask, RHI::WriteChannelMask::ColorWriteMaskAll)) { return D3D12_COLOR_WRITE_ENABLE_ALL; } - if (RHI::CheckBitsAny(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskRed))) + if (RHI::CheckBitsAny(writeMask, RHI::WriteChannelMask::ColorWriteMaskRed)) { dflags |= D3D12_COLOR_WRITE_ENABLE_RED; } - if (RHI::CheckBitsAny(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskGreen))) + if (RHI::CheckBitsAny(writeMask, RHI::WriteChannelMask::ColorWriteMaskGreen)) { dflags |= D3D12_COLOR_WRITE_ENABLE_GREEN; } - if (RHI::CheckBitsAny(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskBlue))) + if (RHI::CheckBitsAny(writeMask, RHI::WriteChannelMask::ColorWriteMaskBlue)) { dflags |= D3D12_COLOR_WRITE_ENABLE_BLUE; } - if (RHI::CheckBitsAny(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskAlpha))) + if (RHI::CheckBitsAny(writeMask, RHI::WriteChannelMask::ColorWriteMaskAlpha)) { dflags |= D3D12_COLOR_WRITE_ENABLE_ALPHA; } diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/Conversions.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/Conversions.cpp index 81e589e62e..5b153fd648 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/Conversions.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/Conversions.cpp @@ -463,24 +463,24 @@ namespace AZ return colorMask; } - if(RHI::CheckBitsAll(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskAll))) + if(RHI::CheckBitsAll(writeMask, RHI::WriteChannelMask::ColorWriteMaskAll)) { return MTLColorWriteMaskAll; } - if (RHI::CheckBitsAny(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskRed))) + if (RHI::CheckBitsAny(writeMask, RHI::WriteChannelMask::ColorWriteMaskRed)) { colorMask |= MTLColorWriteMaskRed; } - if (RHI::CheckBitsAny(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskGreen))) + if (RHI::CheckBitsAny(writeMask, RHI::WriteChannelMask::ColorWriteMaskGreen)) { colorMask |= MTLColorWriteMaskGreen; } - if (RHI::CheckBitsAny(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskBlue))) + if (RHI::CheckBitsAny(writeMask, RHI::WriteChannelMask::ColorWriteMaskBlue)) { colorMask |= MTLColorWriteMaskBlue; } - if (RHI::CheckBitsAny(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskAlpha))) + if (RHI::CheckBitsAny(writeMask, RHI::WriteChannelMask::ColorWriteMaskAlpha)) { colorMask |= MTLColorWriteMaskAlpha; } diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Conversion.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Conversion.cpp index 5ce9731506..1ba002748b 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Conversion.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Conversion.cpp @@ -340,19 +340,24 @@ namespace AZ return dflags; } - if (RHI::CheckBitsAny(sflags, static_cast(RHI::WriteChannelMask::ColorWriteMaskRed))) + if(RHI::CheckBitsAll(writeMask, RHI::WriteChannelMask::ColorWriteMaskAll)) + { + return VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + } + + if (RHI::CheckBitsAny(sflags, RHI::WriteChannelMask::ColorWriteMaskRed)) { dflags |= VK_COLOR_COMPONENT_R_BIT; } - if (RHI::CheckBitsAny(sflags, static_cast(RHI::WriteChannelMask::ColorWriteMaskGreen))) + if (RHI::CheckBitsAny(sflags, RHI::WriteChannelMask::ColorWriteMaskGreen)) { dflags |= VK_COLOR_COMPONENT_G_BIT; } - if (RHI::CheckBitsAny(sflags, static_cast(RHI::WriteChannelMask::ColorWriteMaskBlue))) + if (RHI::CheckBitsAny(sflags, RHI::WriteChannelMask::ColorWriteMaskBlue)) { dflags |= VK_COLOR_COMPONENT_B_BIT; } - if (RHI::CheckBitsAny(sflags, static_cast(RHI::WriteChannelMask::ColorWriteMaskAlpha))) + if (RHI::CheckBitsAny(sflags, RHI::WriteChannelMask::ColorWriteMaskAlpha)) { dflags |= VK_COLOR_COMPONENT_A_BIT; } From c0cfe239fe8c4b4aa26a85a34ee188177f6a4bec Mon Sep 17 00:00:00 2001 From: moudgils Date: Thu, 10 Jun 2021 15:03:08 -0700 Subject: [PATCH 041/116] Modify WritecolorMask --- .../Include/Atom/RHI.Reflect/RenderStates.h | 18 +++++------------- .../RHI/DX12/Code/Source/RHI/Conversions.cpp | 10 +++++----- .../RHI/Metal/Code/Source/RHI/Conversions.cpp | 10 +++++----- .../RHI/Vulkan/Code/Source/RHI/Conversion.cpp | 10 +++++----- 4 files changed, 20 insertions(+), 28 deletions(-) diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/RenderStates.h b/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/RenderStates.h index d5c55e2c7f..651be829b5 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/RenderStates.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/RenderStates.h @@ -160,21 +160,13 @@ namespace AZ StencilState m_stencil; }; - enum class WriteChannel : uint32_t - { - ColorWriteMaskRed = 0, - ColorWriteMaskGreen, - ColorWriteMaskBlue, - ColorWriteMaskAlpha, - }; - - enum class WriteChannelMask : uint32_t + enum class WriteChannelMask : uint8_t { ColorWriteMaskNone = 0, - ColorWriteMaskRed = AZ_BIT(static_cast(WriteChannel::ColorWriteMaskRed)), - ColorWriteMaskGreen = AZ_BIT(static_cast(WriteChannel::ColorWriteMaskGreen)), - ColorWriteMaskBlue = AZ_BIT(static_cast(WriteChannel::ColorWriteMaskBlue)), - ColorWriteMaskAlpha = AZ_BIT(static_cast(WriteChannel::ColorWriteMaskAlpha)), + ColorWriteMaskRed = AZ_BIT(0), + ColorWriteMaskGreen = AZ_BIT(1), + ColorWriteMaskBlue = AZ_BIT(2), + ColorWriteMaskAlpha = AZ_BIT(3), ColorWriteMaskAll = ColorWriteMaskRed | ColorWriteMaskGreen | ColorWriteMaskBlue | ColorWriteMaskAlpha }; diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.cpp index 8c7b9f4389..9776734158 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.cpp @@ -1365,24 +1365,24 @@ namespace AZ return dflags; } - if(RHI::CheckBitsAll(writeMask, RHI::WriteChannelMask::ColorWriteMaskAll)) + if(RHI::CheckBitsAll(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskAll))) { return D3D12_COLOR_WRITE_ENABLE_ALL; } - if (RHI::CheckBitsAny(writeMask, RHI::WriteChannelMask::ColorWriteMaskRed)) + if (RHI::CheckBitsAny(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskRed))) { dflags |= D3D12_COLOR_WRITE_ENABLE_RED; } - if (RHI::CheckBitsAny(writeMask, RHI::WriteChannelMask::ColorWriteMaskGreen)) + if (RHI::CheckBitsAny(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskGreen))) { dflags |= D3D12_COLOR_WRITE_ENABLE_GREEN; } - if (RHI::CheckBitsAny(writeMask, RHI::WriteChannelMask::ColorWriteMaskBlue)) + if (RHI::CheckBitsAny(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskBlue))) { dflags |= D3D12_COLOR_WRITE_ENABLE_BLUE; } - if (RHI::CheckBitsAny(writeMask, RHI::WriteChannelMask::ColorWriteMaskAlpha)) + if (RHI::CheckBitsAny(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskAlpha))) { dflags |= D3D12_COLOR_WRITE_ENABLE_ALPHA; } diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/Conversions.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/Conversions.cpp index 5b153fd648..81e589e62e 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/Conversions.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/Conversions.cpp @@ -463,24 +463,24 @@ namespace AZ return colorMask; } - if(RHI::CheckBitsAll(writeMask, RHI::WriteChannelMask::ColorWriteMaskAll)) + if(RHI::CheckBitsAll(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskAll))) { return MTLColorWriteMaskAll; } - if (RHI::CheckBitsAny(writeMask, RHI::WriteChannelMask::ColorWriteMaskRed)) + if (RHI::CheckBitsAny(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskRed))) { colorMask |= MTLColorWriteMaskRed; } - if (RHI::CheckBitsAny(writeMask, RHI::WriteChannelMask::ColorWriteMaskGreen)) + if (RHI::CheckBitsAny(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskGreen))) { colorMask |= MTLColorWriteMaskGreen; } - if (RHI::CheckBitsAny(writeMask, RHI::WriteChannelMask::ColorWriteMaskBlue)) + if (RHI::CheckBitsAny(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskBlue))) { colorMask |= MTLColorWriteMaskBlue; } - if (RHI::CheckBitsAny(writeMask, RHI::WriteChannelMask::ColorWriteMaskAlpha)) + if (RHI::CheckBitsAny(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskAlpha))) { colorMask |= MTLColorWriteMaskAlpha; } diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Conversion.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Conversion.cpp index 1ba002748b..5a382267bb 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Conversion.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Conversion.cpp @@ -340,24 +340,24 @@ namespace AZ return dflags; } - if(RHI::CheckBitsAll(writeMask, RHI::WriteChannelMask::ColorWriteMaskAll)) + if(RHI::CheckBitsAll(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskAll))) { return VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; } - if (RHI::CheckBitsAny(sflags, RHI::WriteChannelMask::ColorWriteMaskRed)) + if (RHI::CheckBitsAny(sflags, static_cast(RHI::WriteChannelMask::ColorWriteMaskRed))) { dflags |= VK_COLOR_COMPONENT_R_BIT; } - if (RHI::CheckBitsAny(sflags, RHI::WriteChannelMask::ColorWriteMaskGreen)) + if (RHI::CheckBitsAny(sflags, static_cast(RHI::WriteChannelMask::ColorWriteMaskGreen))) { dflags |= VK_COLOR_COMPONENT_G_BIT; } - if (RHI::CheckBitsAny(sflags, RHI::WriteChannelMask::ColorWriteMaskBlue)) + if (RHI::CheckBitsAny(sflags, static_cast(RHI::WriteChannelMask::ColorWriteMaskBlue))) { dflags |= VK_COLOR_COMPONENT_B_BIT; } - if (RHI::CheckBitsAny(sflags, RHI::WriteChannelMask::ColorWriteMaskAlpha)) + if (RHI::CheckBitsAny(sflags, static_cast(RHI::WriteChannelMask::ColorWriteMaskAlpha))) { dflags |= VK_COLOR_COMPONENT_A_BIT; } From 7dd98c4e2b12c318d6533e254a52139b108e3589 Mon Sep 17 00:00:00 2001 From: moudgils Date: Thu, 10 Jun 2021 15:17:17 -0700 Subject: [PATCH 042/116] Missed a change --- Gems/Atom/RHI/Vulkan/Code/Source/RHI/Conversion.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Conversion.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Conversion.cpp index 5a382267bb..8cad9b1f56 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Conversion.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Conversion.cpp @@ -340,7 +340,7 @@ namespace AZ return dflags; } - if(RHI::CheckBitsAll(writeMask, static_cast(RHI::WriteChannelMask::ColorWriteMaskAll))) + if(RHI::CheckBitsAll(sflags, static_cast(RHI::WriteChannelMask::ColorWriteMaskAll))) { return VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; } From 7590ef04b26c9c68076dba8f5446fe8538a0caa6 Mon Sep 17 00:00:00 2001 From: jiaweig Date: Thu, 10 Jun 2021 16:48:48 -0700 Subject: [PATCH 043/116] Increase the platform limit to handle more objects. --- .../Assets/Config/Platform/Windows/DX12/PlatformLimits.azasset | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/Feature/Common/Assets/Config/Platform/Windows/DX12/PlatformLimits.azasset b/Gems/Atom/Feature/Common/Assets/Config/Platform/Windows/DX12/PlatformLimits.azasset index 7e71111ef1..3c88544e62 100644 --- a/Gems/Atom/Feature/Common/Assets/Config/Platform/Windows/DX12/PlatformLimits.azasset +++ b/Gems/Atom/Feature/Common/Assets/Config/Platform/Windows/DX12/PlatformLimits.azasset @@ -8,7 +8,7 @@ "$type": "DX12::PlatformLimitsDescriptor", "m_descriptorHeapLimits": { - "DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV": [16384, 262144], + "DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV": [1000000, 1000000], "DESCRIPTOR_HEAP_TYPE_SAMPLER": [2048, 2048], "DESCRIPTOR_HEAP_TYPE_RTV": [2048, 0], "DESCRIPTOR_HEAP_TYPE_DSV": [2048, 0] From f6f90ee4c2f4a34b8691bb698760e77f18274718 Mon Sep 17 00:00:00 2001 From: moudgils Date: Thu, 10 Jun 2021 21:45:38 -0700 Subject: [PATCH 044/116] Change ConvertColorWriteMask return type to uint8_t --- Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.cpp | 4 ++-- Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.cpp index 9776734158..a29c7ae402 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.cpp @@ -1357,9 +1357,9 @@ namespace AZ return table[(uint32_t)mask]; } - uint32_t ConvertColorWriteMask(uint8_t writeMask) + uint8_t ConvertColorWriteMask(uint8_t writeMask) { - uint32_t dflags = 0; + uint8_t dflags = 0; if(writeMask == 0) { return dflags; diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.h b/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.h index 887598de79..640a5fef31 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.h +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.h @@ -165,6 +165,6 @@ namespace AZ D3D12_SHADER_VISIBILITY shaderVisibility, D3D12_STATIC_SAMPLER_DESC& staticSamplerDesc); - uint32_t ConvertColorWriteMask(uint8_t writeMask); + uint8_t ConvertColorWriteMask(uint8_t writeMask); } } From ef87ce094a720319bbdb09b25761b7e7da8a6899 Mon Sep 17 00:00:00 2001 From: antonmic Date: Fri, 11 Jun 2021 00:52:24 -0700 Subject: [PATCH 045/116] Fixing pass binding issue that breaks certain ASV screenshot tests. Should also fix a crash on mac that was reported. --- .../Code/Include/Atom/RPI.Public/Pass/Pass.h | 6 +++++ .../RPI/Code/Source/RPI.Public/Pass/Pass.cpp | 24 ++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/Pass.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/Pass.h index 9d0b36d126..a4a26c3070 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/Pass.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/Pass.h @@ -265,6 +265,12 @@ namespace AZ // Update all bindings on this pass that are connected to bindings on other passes void UpdateConnectedBindings(); + // Update input and input/output bindings on this pass that are connected to bindings on other passes + void UpdateConnectedInputBindings(); + + // Update output bindings on this pass that are connected to bindings on other passes + void UpdateConnectedOutputBindings(); + protected: explicit Pass(const PassDescriptor& descriptor); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Pass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Pass.cpp index 99a6e23914..865a13e13d 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Pass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Pass.cpp @@ -1036,6 +1036,26 @@ namespace AZ } } + void Pass::UpdateConnectedInputBindings() + { + for (uint8_t idx : m_inputBindingIndices) + { + UpdateConnectedBinding(m_attachmentBindings[idx]); + } + for (uint8_t idx : m_inputOutputBindingIndices) + { + UpdateConnectedBinding(m_attachmentBindings[idx]); + } + } + + void Pass::UpdateConnectedOutputBindings() + { + for (uint8_t idx : m_outputBindingIndices) + { + UpdateConnectedBinding(m_attachmentBindings[idx]); + } + } + // --- Queuing functions with PassSystem --- void Pass::QueueForBuildAndInitialization() @@ -1264,7 +1284,7 @@ namespace AZ AZ_Assert(m_state == PassState::Idle, "Pass::FrameBegin - Pass [%s] is attempting to render, but is not in the Idle state.", m_path.GetCStr()); m_state = PassState::Rendering; - UpdateConnectedBindings(); + UpdateConnectedInputBindings(); UpdateOwnedAttachments(); CreateTransientAttachments(params.m_frameGraphBuilder->GetAttachmentDatabase()); @@ -1273,6 +1293,8 @@ namespace AZ // FrameBeginInternal needs to be the last function be called in FrameBegin because its implementation expects // all the attachments are imported to database (for example, ImageAttachmentPreview) FrameBeginInternal(params); + + UpdateConnectedOutputBindings(); } void Pass::FrameEnd() From f775ba7df83730870e71644da835a5660cc72be7 Mon Sep 17 00:00:00 2001 From: Steve Pham <82231385+spham-amzn@users.noreply.github.com> Date: Fri, 11 Jun 2021 08:12:49 -0700 Subject: [PATCH 046/116] Provide more informative error messages on android related environment / device related issues (#1261) - If gradle is installed, but JAVA_HOME is not set properly, no detail message is given. Bubble up the error message as part of the description - When deploying a newer API Level APK (30) to an API Level 29 device, a python callstack is given without any detail of the error. Now it will report the actual error that is from the adb call so the user can act upon it --- .../Platform/Android/android_deployment.py | 14 +++++++++----- cmake/Tools/common.py | 18 +++++++++++++----- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/cmake/Tools/Platform/Android/android_deployment.py b/cmake/Tools/Platform/Android/android_deployment.py index eb8361ec18..82d14a2746 100755 --- a/cmake/Tools/Platform/Android/android_deployment.py +++ b/cmake/Tools/Platform/Android/android_deployment.py @@ -184,11 +184,15 @@ class AndroidDeployment(object): call_arguments.extend(arg_list) - output = subprocess.check_output(call_arguments, - shell=True, - stderr=subprocess.DEVNULL).decode(common.DEFAULT_TEXT_READ_ENCODING, - common.ENCODING_ERROR_HANDLINGS) - return output + try: + output = subprocess.check_output(call_arguments, + shell=True, + stderr=subprocess.PIPE).decode(common.DEFAULT_TEXT_READ_ENCODING, + common.ENCODING_ERROR_HANDLINGS) + return output + except subprocess.CalledProcessError as err: + raise common.LmbrCmdError(err.stderr.decode(common.DEFAULT_TEXT_READ_ENCODING, + common.ENCODING_ERROR_HANDLINGS)) def adb_shell(self, command, device_id): """ diff --git a/cmake/Tools/common.py b/cmake/Tools/common.py index 1990041c86..cf4631c227 100755 --- a/cmake/Tools/common.py +++ b/cmake/Tools/common.py @@ -274,6 +274,8 @@ def verify_tool(override_tool_path, tool_name, tool_filename, argument_name, too :return: Tuple of the resolved tool version and the resolved override tool path if provided """ + tool_source = tool_name + try: # Use either the provided gradle override or the gradle in the path environment if override_tool_path: @@ -306,18 +308,17 @@ def verify_tool(override_tool_path, tool_name, tool_filename, argument_name, too tool_desc = f"{tool_name} path provided in the command line argument '{argument_name}={override_tool_path}' " else: resolved_override_tool_path = None - tool_source = tool_name tool_desc = f"installed {tool_name} in the system path" # Extract the version and verify version_output = subprocess.check_output([tool_source, tool_version_argument], - shell=True).decode(DEFAULT_TEXT_READ_ENCODING, - ENCODING_ERROR_HANDLINGS) + shell=True, + stderr=subprocess.PIPE).decode(DEFAULT_TEXT_READ_ENCODING, + ENCODING_ERROR_HANDLINGS) version_match = tool_version_regex.search(version_output) if not version_match: raise RuntimeError() - # Since we are doing a compare, strip out any non-numeric and non . character from the version otherwise we will get a TypeError on the LooseVersion comparison result_version_str = re.sub(r"[^\.0-9]", "", str(version_match.group(1)).strip()) result_version = LooseVersion(result_version_str) @@ -331,7 +332,14 @@ def verify_tool(override_tool_path, tool_name, tool_filename, argument_name, too return result_version, resolved_override_tool_path - except (CalledProcessError, WindowsError, RuntimeError) as e: + except CalledProcessError as e: + error_msg = e.output.decode(DEFAULT_TEXT_READ_ENCODING, + ENCODING_ERROR_HANDLINGS) + raise LmbrCmdError(f"{tool_name} cannot be resolved or there was a problem determining its version number. " + f"Either make sure its in the system path environment or a valid path is passed in " + f"through the {argument_name} argument.\n{error_msg}", + ERROR_CODE_ERROR_NOT_SUPPORTED) + except (WindowsError, RuntimeError) as e: logging.error(f"Call to '{tool_source}' resulted in error: {e}") raise LmbrCmdError(f"{tool_name} cannot be resolved or there was a problem determining its version number. " f"Either make sure its in the system path environment or a valid path is passed in " From a995aee35a60d93ab3ffc826afe024a8325b0814 Mon Sep 17 00:00:00 2001 From: chcurran Date: Fri, 11 Jun 2021 09:47:44 -0700 Subject: [PATCH 047/116] Properties__Index and Properties__NewIndex upvalue counts no reflect removal of net binding component --- .../AzFramework/AzFramework/Script/ScriptComponent.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/Script/ScriptComponent.cpp b/Code/Framework/AzFramework/AzFramework/Script/ScriptComponent.cpp index 4f8da821c1..d80094a071 100644 --- a/Code/Framework/AzFramework/AzFramework/Script/ScriptComponent.cpp +++ b/Code/Framework/AzFramework/AzFramework/Script/ScriptComponent.cpp @@ -693,11 +693,11 @@ namespace AzFramework // set the __index so we can read values in case we change the script // after we export the component lua_pushliteral(lua, "__index"); - lua_pushcclosure(lua, &Internal::Properties__Index, 1); + lua_pushcclosure(lua, &Internal::Properties__Index, 0); lua_rawset(lua, -3); lua_pushliteral(lua, "__newindex"); - lua_pushcclosure(lua, &Internal::Properties__NewIndex, 1); + lua_pushcclosure(lua, &Internal::Properties__NewIndex, 0); lua_rawset(lua, -3); } lua_pop(lua, 1); // pop the properties table (or the nil value) @@ -900,11 +900,11 @@ namespace AzFramework // Ensure that this instance of Properties table has the proper __index and __newIndex metamethods. lua_newtable(lua); // This new table will become the Properties instance metatable. Stack: ScriptRootTable PropertiesTable EntityTable "Properties" {} {} lua_pushliteral(lua, "__index"); // Stack: ScriptRootTable PropertiesTable EntityTable "Properties" {} {} __index - lua_pushcclosure(lua, &Internal::Properties__Index, 1); // Stack: ScriptRootTable PropertiesTable EntityTable "Properties" {} {} __index function + lua_pushcclosure(lua, &Internal::Properties__Index, 0); // Stack: ScriptRootTable PropertiesTable EntityTable "Properties" {} {} __index function lua_rawset(lua, -3); // Stack: ScriptRootTable PropertiesTable EntityTable "Properties" {} {__index=Internal::Properties__Index} lua_pushliteral(lua, "__newindex"); - lua_pushcclosure(lua, &Internal::Properties__NewIndex, 1); + lua_pushcclosure(lua, &Internal::Properties__NewIndex, 0); lua_rawset(lua, -3); // Stack: ScriptRootTable PropertiesTable EntityTable "Properties" {} {__index=Internal::Properties__Index __newindex=Internal::Properties__NewIndex} lua_setmetatable(lua, -2); // Stack: ScriptRootTable PropertiesTable EntityTable "Properties" {Meta{__index=Internal::Properties__Index __newindex=Internal::Properties__NewIndex} } From 0c7605c9b697522042f3161393d719dc76494ad8 Mon Sep 17 00:00:00 2001 From: Eric Phister <52085794+amzn-phist@users.noreply.github.com> Date: Fri, 11 Jun 2021 12:00:55 -0500 Subject: [PATCH 048/116] Update minimum required CMake version to 3.20 (#1253) * Update the minimum CMake version to 3.20 Sets the cmake_minimum_required calls to version 3.20 and updates the README.md to point at the general CMake download page instead of a stale link. * Remove unnecessary cmake minimum version It was using an old 3.0 version and can be removed. * Additional updates to CMake 3.20, build scripts Updates the version and remove logic to find a CMake in 3rdParty. * Removing backup path to ninja path in the build_ninja_windows.cmd The backup path for finding ninja was coming from the Perforce depot which isn't available for o3de builds. * Removing reference to 3rdParty Android SDK 29 from the build and run unit test script The Android SDK is not part of the new 3rdParty system and users are expected to install the Android SDK on their own in order to build the engine for Android. * Update the get_python scripts and README No longer try to append a CMake path to LY_3RDPARTY_PATH, but do still support LY_CMAKE_PATH because there are still uses of it. Remove mention of an LY_3RDPARTY_PATH-relative CMake path from the README.md. * Removing LY_NINJA_PATH from the build_ninja_windows.cmd Co-authored-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> --- AutomatedTesting/CMakeLists.txt | 2 +- CMakeLists.txt | 13 ++-------- Code/Framework/AzAutoGen/CMakeLists.txt | 2 -- README.md | 4 ++-- .../DefaultProject/Template/CMakeLists.txt | 2 +- .../Android/generate_android_project.py | 2 +- python/get_python.bat | 13 ++++------ python/get_python.cmake | 2 +- python/get_python.sh | 22 +++++------------ .../Android/build_and_run_unit_tests.cmd | 3 --- scripts/build/Platform/Linux/env_linux.sh | 24 ++++--------------- scripts/build/Platform/Mac/env_mac.sh | 12 ++-------- .../Platform/Windows/build_ninja_windows.cmd | 11 +-------- .../build/Platform/Windows/env_windows.cmd | 13 ++-------- 14 files changed, 28 insertions(+), 97 deletions(-) diff --git a/AutomatedTesting/CMakeLists.txt b/AutomatedTesting/CMakeLists.txt index e239ba7674..9a870b1279 100644 --- a/AutomatedTesting/CMakeLists.txt +++ b/AutomatedTesting/CMakeLists.txt @@ -10,7 +10,7 @@ # if(NOT PROJECT_NAME) - cmake_minimum_required(VERSION 3.19) + cmake_minimum_required(VERSION 3.20) project(AutomatedTesting LANGUAGES C CXX VERSION 1.0.0.0 diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ca9aeacb8..0585089325 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,17 +9,8 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# Cmake version 3.19 is the minimum version needed for all of Open 3D Engine's supported platforms -cmake_minimum_required(VERSION 3.19) - -# CMP0111 introduced in 3.19 has a bug that produces the policy to warn every time there is an -# INTERFACE IMPORTED library. We use this type of libraries for handling 3rdParty. The rest of -# the documentation states that INTERFACE IMPORTED libraries do not require to set locations, but -# the policy still warns about it. Issue: https://gitlab.kitware.com/cmake/cmake/-/issues/21470 -# The issue was fixed in 3.19.1 so we just disable the policy for 3.19 -if(CMAKE_VERSION VERSION_EQUAL 3.19) - cmake_policy(SET CMP0111 OLD) -endif() +# Cmake version 3.20 is the minimum version needed for all of Open 3D Engine's supported platforms +cmake_minimum_required(VERSION 3.20) include(cmake/LySet.cmake) include(cmake/Version.cmake) diff --git a/Code/Framework/AzAutoGen/CMakeLists.txt b/Code/Framework/AzAutoGen/CMakeLists.txt index 925e7aed29..4c79f268fe 100644 --- a/Code/Framework/AzAutoGen/CMakeLists.txt +++ b/Code/Framework/AzAutoGen/CMakeLists.txt @@ -9,8 +9,6 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -cmake_minimum_required(VERSION 3.0) - ly_add_target( NAME AzAutoGen HEADERONLY NAMESPACE AZ diff --git a/README.md b/README.md index 0c59837a62..7a9751529f 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ If you have the Git credential manager core or other credential helpers installe * Game Development with C++ * MSVC v142 - VS 2019 C++ x64/x86 * C++ 2019 redistributable update -* CMake 3.19.1 minimum: [https://cmake.org/files/LatestRelease/cmake-3.19.1-win64-x64.msi](https://cmake.org/files/LatestRelease/cmake-3.19.1-win64-x64.msi) +* CMake 3.20 minimum: [https://cmake.org/download/](https://cmake.org/download/) #### Optional @@ -105,7 +105,7 @@ If you have the Git credential manager core or other credential helpers installe 1. Install the following redistributables to the following: - Visual Studio and VC++ redistributable can be installed to any location - - CMake can be installed to any location, as long as it's available in the system path, otherwise it can be installed to: `<3rdParty Path>\CMake\3.19.1` + - CMake can be installed to any location, as long as it's available in the system path - WWise can be installed anywhere, but you will need to set an environment variable for CMake to detect it: `set LY_WWISE_INSTALL_PATH=` 1. Navigate into the repo folder, then download the python runtime with this command diff --git a/Templates/DefaultProject/Template/CMakeLists.txt b/Templates/DefaultProject/Template/CMakeLists.txt index 50e3a528e6..4dcfc5325b 100644 --- a/Templates/DefaultProject/Template/CMakeLists.txt +++ b/Templates/DefaultProject/Template/CMakeLists.txt @@ -12,7 +12,7 @@ # {END_LICENSE} if(NOT PROJECT_NAME) - cmake_minimum_required(VERSION 3.19) + cmake_minimum_required(VERSION 3.20) project(${Name} LANGUAGES C CXX VERSION 1.0.0.0 diff --git a/cmake/Tools/Platform/Android/generate_android_project.py b/cmake/Tools/Platform/Android/generate_android_project.py index d25b62dde8..5a52ac385e 100755 --- a/cmake/Tools/Platform/Android/generate_android_project.py +++ b/cmake/Tools/Platform/Android/generate_android_project.py @@ -48,7 +48,7 @@ def verify_gradle(override_gradle_path=None): CMAKE_ARGUMENT_NAME = '--cmake-install-path' -CMAKE_MIN_VERSION = LooseVersion('3.19.0') +CMAKE_MIN_VERSION = LooseVersion('3.20.0') CMAKE_VERSION_REGEX = re.compile(r'cmake version (\d+.\d+.?\d*)') CMAKE_EXECUTABLE = 'cmake' diff --git a/python/get_python.bat b/python/get_python.bat index e11c4ab92f..b3c3bf9cfb 100644 --- a/python/get_python.bat +++ b/python/get_python.bat @@ -32,18 +32,15 @@ IF !ERRORLEVEL!==0 ( cd /D %CMD_DIR%\.. REM IF you update this logic, update it in scripts/build/Platform/Windows/env_windows.cmd -REM If cmake is not found on path, try a known location, using LY_CMAKE_PATH as the first fallback +REM If cmake is not found on path, try a known location at LY_CMAKE_PATH where /Q cmake IF NOT !ERRORLEVEL!==0 ( IF "%LY_CMAKE_PATH%"=="" ( - IF "%LY_3RDPARTY_PATH%"=="" ( - ECHO ERROR: CMake was not found on the PATH and LY_3RDPARTY_PATH is not defined. - ECHO Please ensure CMake is on the path or set LY_3RDPARTY_PATH or LY_CMAKE_PATH. - EXIT /b 1 - ) - SET LY_CMAKE_PATH=!LY_3RDPARTY_PATH!\CMake\3.19.1\Windows\bin - echo CMake was not found on the path, will use known location: !LY_CMAKE_PATH! + ECHO ERROR: CMake was not found on the PATH and LY_CMAKE_PATH is not defined. + ECHO Please ensure CMake is on the path or set LY_CMAKE_PATH. + EXIT /b 1 ) + PATH !LY_CMAKE_PATH!;!PATH! where /Q cmake if NOT !ERRORLEVEL!==0 ( diff --git a/python/get_python.cmake b/python/get_python.cmake index 5d6bf6fd96..198d3f0ba3 100644 --- a/python/get_python.cmake +++ b/python/get_python.cmake @@ -16,7 +16,7 @@ # example: # cmake -DPAL_PLATFORM_NAME:string=Windows -DLY_3RDPARTY_PATH:string=%CMD_DIR% -P get_python.cmake -cmake_minimum_required(VERSION 3.17) +cmake_minimum_required(VERSION 3.20) if(LY_3RDPARTY_PATH) file(TO_CMAKE_PATH ${LY_3RDPARTY_PATH} LY_3RDPARTY_PATH) diff --git a/python/get_python.sh b/python/get_python.sh index 780f1bbdd8..9b774d91fc 100755 --- a/python/get_python.sh +++ b/python/get_python.sh @@ -42,31 +42,21 @@ then CMAKE_FOLDER_RELATIVE_TO_ROOT=CMake.app/Contents/bin else PAL=Linux - CMAKE_FOLDER_RELATIVE_TO_ROOT=bin + CMAKE_FOLDER_RELATIVE_TO_ROOT=bin fi if ! [ -x "$(command -v cmake)" ]; then - # Note that LY_3RDPARTY_PATH is only required here if you have no cmake in your PATH. if [ -z ${LY_CMAKE_PATH} ]; then - if [ -z ${LY_3RDPARTY_PATH} ]; then - echo "ERROR: Could not find cmake on the PATH and LY_3RDPARTY_PATH is not defined, cannot continue." - echo "Please add cmake to your PATH, or define $LY_3RDPARTY_PATH" - exit 1 - fi - LY_CMAKE_PATH=$LY_3RDPARTY_PATH/CMake/3.19.1/$PAL/$CMAKE_FOLDER_RELATIVE_TO_ROOT - # if you change the version number, change it also in: - # scripts/build/Platform/Mac/env_mac.sh - # and - # scripts/build/Platform/Linux/env_linux.sh + echo "ERROR: Could not find cmake on the PATH and LY_CMAKE_PATH is not defined, cannot continue." + echo "Please add cmake to your PATH, or define LY_CMAKE_PATH" + exit 1 fi - + export PATH=$LY_CMAKE_PATH:$PATH if ! [ -x "$(command -v cmake)" ]; then - echo "ERROR: Could not find cmake on the PATH or at the known location: $CMAKE_KNOWN_LOCATION" + echo "ERROR: Could not find cmake on the PATH or at the known location: $LY_CMAKE_PATH" echo "Please add cmake to the environment PATH or place it at the above known location." exit 1 - else - echo "CMake not found on path, but was found in the known 3rd Party location." fi fi diff --git a/scripts/build/Platform/Android/build_and_run_unit_tests.cmd b/scripts/build/Platform/Android/build_and_run_unit_tests.cmd index fbb31f95ec..5a51621f40 100644 --- a/scripts/build/Platform/Android/build_and_run_unit_tests.cmd +++ b/scripts/build/Platform/Android/build_and_run_unit_tests.cmd @@ -20,9 +20,6 @@ IF NOT EXIST "%LY_3RDPARTY_PATH%" ( GOTO :error ) -IF NOT EXIST "%LY_ANDROID_SDK%" ( - SET LY_ANDROID_SDK=!LY_3RDPARTY_PATH!/android-sdk/platform-29 -) IF NOT EXIST "%LY_ANDROID_SDK%" ( ECHO [ci_build] FAIL: LY_ANDROID_SDK=!LY_ANDROID_SDK! GOTO :error diff --git a/scripts/build/Platform/Linux/env_linux.sh b/scripts/build/Platform/Linux/env_linux.sh index 1d7324778c..85bdf0a745 100755 --- a/scripts/build/Platform/Linux/env_linux.sh +++ b/scripts/build/Platform/Linux/env_linux.sh @@ -13,27 +13,11 @@ set -o errexit # exit on the first failure encountered if ! command -v cmake &> /dev/null; then - if [[ -z $LY_CMAKE_PATH ]]; then LY_CMAKE_PATH=${LY_3RDPARTY_PATH}/CMake/3.19.1/Linux/bin; fi - if [[ ! -d $LY_CMAKE_PATH ]]; then - echo "[ci_build] CMake path not found" - exit 1 - fi - PATH=${LY_CMAKE_PATH}:${PATH} - if ! command -v cmake &> /dev/null; then - echo "[ci_build] CMake not found" - exit 1 - fi + echo "[ci_build] CMake not found" + exit 1 fi if ! command -v ninja &> /dev/null; then - if [[ -z $LY_NINJA_PATH ]]; then LY_NINJA_PATH=${LY_3RDPARTY_PATH}/ninja/1.10.1/Linux; fi - if [[ ! -d $LY_NINJA_PATH ]]; then - echo "[ci_build] Ninja path not found" - exit 1 - fi - PATH=${LY_NINJA_PATH}:${PATH} - if ! command -v ninja &> /dev/null; then - echo "[ci_build] Ninja not found" - exit 1 - fi + echo "[ci_build] Ninja not found" + exit 1 fi diff --git a/scripts/build/Platform/Mac/env_mac.sh b/scripts/build/Platform/Mac/env_mac.sh index 8f38d1d90b..917329b6af 100755 --- a/scripts/build/Platform/Mac/env_mac.sh +++ b/scripts/build/Platform/Mac/env_mac.sh @@ -13,14 +13,6 @@ set -o errexit # exit on the first failure encountered if ! command -v cmake &> /dev/null; then - if [[ -z $LY_CMAKE_PATH ]]; then LY_CMAKE_PATH=${LY_3RDPARTY_PATH}/CMake/3.19.1/Mac/CMake.app/Contents/bin; fi - if [[ ! -d $LY_CMAKE_PATH ]]; then - echo "[ci_build] CMake path not found" - exit 1 - fi - PATH=${LY_CMAKE_PATH}:${PATH} - if ! command -v cmake &> /dev/null; then - echo "[ci_build] CMake not found" - exit 1 - fi + echo "[ci_build] CMake not found" + exit 1 fi diff --git a/scripts/build/Platform/Windows/build_ninja_windows.cmd b/scripts/build/Platform/Windows/build_ninja_windows.cmd index b782cc2357..e1a802e254 100644 --- a/scripts/build/Platform/Windows/build_ninja_windows.cmd +++ b/scripts/build/Platform/Windows/build_ninja_windows.cmd @@ -12,19 +12,10 @@ REM SETLOCAL EnableDelayedExpansion -IF NOT EXIST "%LY_NINJA_PATH%" ( - SET LY_NINJA_PATH=%LY_3RDPARTY_PATH%/ninja/1.10.1/Windows -) -IF NOT EXIST "%LY_NINJA_PATH%" ( - ECHO [ci_build] FAIL: LY_NINJA_PATH=%LY_NINJA_PATH% - GOTO :error -) -PATH %LY_NINJA_PATH%;%PATH% - CALL "%~dp0build_windows.cmd" IF NOT %ERRORLEVEL%==0 GOTO :error EXIT /b 0 :error -EXIT /b 1 \ No newline at end of file +EXIT /b 1 diff --git a/scripts/build/Platform/Windows/env_windows.cmd b/scripts/build/Platform/Windows/env_windows.cmd index 592b2867cd..3ef161c2ef 100644 --- a/scripts/build/Platform/Windows/env_windows.cmd +++ b/scripts/build/Platform/Windows/env_windows.cmd @@ -12,17 +12,8 @@ REM where /Q cmake IF NOT %ERRORLEVEL%==0 ( - IF "%LY_CMAKE_PATH%"=="" (SET LY_CMAKE_PATH=%LY_3RDPARTY_PATH%/CMake/3.19.1/Windows/bin) - IF NOT EXIST !LY_CMAKE_PATH! ( - ECHO [ci_build] CMake path not found - GOTO :error - ) - PATH !LY_CMAKE_PATH!;!PATH! - where /Q cmake - IF NOT !ERRORLEVEL!==0 ( - ECHO [ci_build] CMake not found - GOTO :error - ) + ECHO [ci_build] CMake not found + GOTO :error ) EXIT /b 0 From 119bc95844e638838c6271db51c9abdc949db1f1 Mon Sep 17 00:00:00 2001 From: chcurran Date: Fri, 11 Jun 2021 10:01:11 -0700 Subject: [PATCH 049/116] Update graph to address SPEC-7168 --- .../Weapons/Revolver/Tracer_FX.scriptcanvas | 20687 ++++++++-------- 1 file changed, 9962 insertions(+), 10725 deletions(-) diff --git a/Gems/PhysXSamples/Assets/ScriptCanvas/Weapons/Revolver/Tracer_FX.scriptcanvas b/Gems/PhysXSamples/Assets/ScriptCanvas/Weapons/Revolver/Tracer_FX.scriptcanvas index eebc79585d..f0fff5e69f 100644 --- a/Gems/PhysXSamples/Assets/ScriptCanvas/Weapons/Revolver/Tracer_FX.scriptcanvas +++ b/Gems/PhysXSamples/Assets/ScriptCanvas/Weapons/Revolver/Tracer_FX.scriptcanvas @@ -3,12 +3,12 @@ - + - + - - + + @@ -16,496 +16,19 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + @@ -539,8 +62,11 @@ + - + + + @@ -574,8 +100,11 @@ + - + + + @@ -609,8 +138,11 @@ + - + + + @@ -644,8 +176,11 @@ + - + + + @@ -679,8 +214,11 @@ + - + + + @@ -714,11 +252,11 @@ + - - + @@ -760,1832 +298,26 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + + + - + @@ -2617,10 +349,13 @@ + - + + + - + @@ -2652,10 +387,13 @@ + - + + + - + @@ -2670,7 +408,7 @@ - + @@ -2692,10 +430,13 @@ + - + + + - + @@ -2705,10 +446,10 @@ - + - + @@ -2727,57 +468,403 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - + - + - - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + + + - + @@ -2809,10 +896,13 @@ + - + + + - + @@ -2844,10 +934,13 @@ + - + + + - + @@ -2879,10 +972,13 @@ + - + + + - + @@ -2914,10 +1010,13 @@ + - + + + - + @@ -2949,10 +1048,13 @@ + - + + + - + @@ -2984,22 +1086,22 @@ + - - + - + - + - + @@ -3009,7 +1111,7 @@ - + @@ -3019,7 +1121,7 @@ - + @@ -3030,986 +1132,24 @@ - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + @@ -4043,8 +1183,11 @@ + - + + + @@ -4078,8 +1221,11 @@ + - + + + @@ -4113,8 +1259,11 @@ + - + + + @@ -4148,8 +1297,11 @@ + - + + + @@ -4183,8 +1335,11 @@ + - + + + @@ -4218,11 +1373,11 @@ + - - + @@ -4264,24 +1419,26 @@ - + - + - + - + - + - + + + - + @@ -4318,10 +1475,13 @@ + - + + + - + @@ -4358,10 +1518,56 @@ + - + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -4393,10 +1599,13 @@ + - + + + - + @@ -4428,6 +1637,7 @@ + @@ -4453,42 +1663,366 @@ - + - + + + + + + + + + + + + + - - + - - + + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + + + @@ -4522,8 +2056,11 @@ + - + + + @@ -4557,8 +2094,11 @@ + - + + + @@ -4592,8 +2132,11 @@ + - + + + @@ -4627,8 +2170,11 @@ + - + + + @@ -4662,8 +2208,11 @@ + - + + + @@ -4714,8 +2263,11 @@ + - + + + @@ -4749,8 +2301,11 @@ + - + + + @@ -4775,7 +2330,7 @@ - + @@ -4784,8 +2339,11 @@ + - + + + @@ -4819,8 +2377,11 @@ + - + + + @@ -4845,7 +2406,7 @@ - + @@ -4854,6 +2415,7 @@ + @@ -4872,8 +2434,7 @@ - - + @@ -4932,151 +2493,26 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + + + - + @@ -5108,10 +2544,13 @@ + - + + + - + @@ -5143,10 +2582,13 @@ + - + + + - + @@ -5178,10 +2620,13 @@ + - + + + - + @@ -5213,10 +2658,13 @@ + - + + + - + @@ -5248,10 +2696,13 @@ + - + + + - + @@ -5283,22 +2734,22 @@ + - - + - + - + @@ -5308,7 +2759,7 @@ - + @@ -5318,7 +2769,7 @@ - + @@ -5329,22 +2780,590 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + @@ -5378,8 +3397,11 @@ + - + + + @@ -5413,8 +3435,11 @@ + - + + + @@ -5448,8 +3473,11 @@ + - + + + @@ -5483,8 +3511,11 @@ + - + + + @@ -5518,8 +3549,11 @@ + - + + + @@ -5553,11 +3587,11 @@ + - - + @@ -5599,868 +3633,24 @@ - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + @@ -6494,8 +3684,11 @@ + - + + + @@ -6529,8 +3722,11 @@ + - + + + @@ -6564,8 +3760,11 @@ + - + + + @@ -6599,8 +3798,11 @@ + - + + + @@ -6634,8 +3836,11 @@ + - + + + @@ -6669,11 +3874,11 @@ + - - + @@ -6715,24 +3920,1295 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + + + - + @@ -6764,10 +5240,13 @@ + - + + + - + @@ -6799,10 +5278,13 @@ + - + + + - + @@ -6834,10 +5316,13 @@ + - + + + - + @@ -6869,10 +5354,13 @@ + - + + + - + @@ -6904,10 +5392,13 @@ + - + + + - + @@ -6939,22 +5430,22 @@ + - - + - + - + - + @@ -6964,7 +5455,7 @@ - + @@ -6974,7 +5465,7 @@ - + @@ -6985,22 +5476,1868 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + @@ -7039,8 +7376,11 @@ + - + + + @@ -7086,8 +7426,11 @@ + - + + + @@ -7121,8 +7464,11 @@ + - + + + @@ -7156,6 +7502,7 @@ + @@ -7186,8 +7533,7 @@ - - + @@ -7201,24 +7547,26 @@ - + - + - + - - + + - + - + + + - + @@ -7229,7 +7577,7 @@ - + @@ -7250,10 +7598,13 @@ + - + + + - + @@ -7264,7 +7615,7 @@ - + @@ -7285,10 +7636,13 @@ + - + + + - + @@ -7297,23 +7651,18 @@ - - - - - - + - + - + @@ -7325,10 +7674,117 @@ + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -7360,10 +7816,13 @@ + - + + + - + @@ -7395,10 +7854,13 @@ + - + + + - + @@ -7430,10 +7892,13 @@ + - + + + - + @@ -7465,38 +7930,22 @@ + - - - - - - - - - - - - - - - - + + - - - - + - + - + @@ -7506,7 +7955,7 @@ - + @@ -7516,7 +7965,7 @@ - + @@ -7527,24 +7976,26 @@ - + - + - + - - + + - + - + + + - + @@ -7555,7 +8006,7 @@ - + @@ -7576,10 +8027,13 @@ + - + + + - + @@ -7590,7 +8044,7 @@ - + @@ -7611,50 +8065,13 @@ + - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -7686,10 +8103,13 @@ + - + + + - + @@ -7721,10 +8141,13 @@ + - + + + - + @@ -7756,10 +8179,13 @@ + - + + + - + @@ -7791,38 +8217,22 @@ + - - - - - - - - - - - - - - - - + + - - - - + - + - + @@ -7832,7 +8242,7 @@ - + @@ -7842,7 +8252,7 @@ - + @@ -7853,24 +8263,168 @@ - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + + + - + @@ -7907,10 +8461,13 @@ + - + + + - + @@ -7919,6 +8476,13 @@ + + + + + + + @@ -7947,50 +8511,13 @@ + - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -8022,10 +8549,13 @@ + - + + + - + @@ -8057,6 +8587,7 @@ + @@ -8084,235 +8615,13 @@ - - - - - - - - - - - - - + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -8323,24 +8632,802 @@ - + - + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -8372,165 +9459,58 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - - + - + + + + + + + + + + + + + - - + - - - - - - - - - - + - + - + - + - + + + @@ -8564,8 +9544,11 @@ + - + + + @@ -8599,8 +9582,11 @@ + - + + + @@ -8634,8 +9620,11 @@ + - + + + @@ -8669,8 +9658,11 @@ + - + + + @@ -8704,8 +9696,11 @@ + - + + + @@ -8739,11 +9734,11 @@ + - - + @@ -8785,24 +9780,337 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + + + - + @@ -8834,10 +10142,13 @@ + - + + + - + @@ -8869,10 +10180,13 @@ + - + + + - + @@ -8887,7 +10201,7 @@ - + @@ -8909,10 +10223,13 @@ + - + + + - + @@ -8922,10 +10239,10 @@ - + - + @@ -8944,53 +10261,546 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + @@ -9029,8 +10839,11 @@ + - + + + @@ -9069,8 +10882,11 @@ + - + + + @@ -9104,8 +10920,11 @@ + - + + + @@ -9139,6 +10958,7 @@ + @@ -9164,13 +10984,12 @@ - + - - + @@ -9184,196 +11003,686 @@ - + - + - + - - - - - - - - - + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -9381,210 +11690,20 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - + + + - + + + @@ -9618,8 +11737,11 @@ + - + + + @@ -9653,8 +11775,11 @@ + - + + + @@ -9688,8 +11813,11 @@ + - + + + @@ -9723,8 +11851,11 @@ + - + + + @@ -9758,8 +11889,11 @@ + - + + + @@ -9793,8 +11927,11 @@ + - + + + @@ -9819,7 +11956,7 @@ - + @@ -9828,8 +11965,11 @@ + - + + + @@ -9863,8 +12003,11 @@ + - + + + @@ -9889,7 +12032,7 @@ - + @@ -9898,8 +12041,11 @@ + - + + + @@ -9933,8 +12079,11 @@ + - + + + @@ -9968,8 +12117,11 @@ + - + + + @@ -10003,8 +12155,11 @@ + - + + + @@ -10038,8 +12193,11 @@ + - + + + @@ -10073,8 +12231,11 @@ + - + + + @@ -10108,8 +12269,11 @@ + - + + + @@ -10143,8 +12307,11 @@ + - + + + @@ -10169,7 +12336,7 @@ - + @@ -10178,11 +12345,11 @@ + - - + @@ -10282,33 +12449,15 @@ - + - + - + - - - - - - - - - - - - - - - - - - - + @@ -10342,15 +12491,33 @@ - + - + - + - + + + + + + + + + + + + + + + + + + + @@ -10358,32 +12525,34 @@ - + - + - + - + - + - - + + - + - + + + - + @@ -10393,45 +12562,10 @@ - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -10439,21 +12573,24 @@ - + - + + - + + + - + @@ -10468,7 +12605,7 @@ - + @@ -10490,10 +12627,13 @@ + - + + + - + @@ -10503,32 +12643,35 @@ - + - + - - + + - + + - + + + - + @@ -10538,10 +12681,10 @@ - + - + @@ -10549,165 +12692,68 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - + + + - + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + - + - + - + - + + + @@ -10741,8 +12787,11 @@ + - + + + @@ -10776,8 +12825,11 @@ + - + + + @@ -10811,11 +12863,11 @@ + - - + @@ -10826,2326 +12878,24 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + + + @@ -13179,8 +12929,11 @@ + - + + + @@ -13214,8 +12967,11 @@ + - + + + @@ -13249,11 +13005,11 @@ + - - + @@ -13264,24 +13020,24 @@ - + - + - + - + @@ -13289,7 +13045,7 @@ - + @@ -13302,17 +13058,17 @@ - + - + - + @@ -13320,7 +13076,7 @@ - + @@ -13333,17 +13089,17 @@ - + - + - + @@ -13351,7 +13107,7 @@ - + @@ -13364,17 +13120,17 @@ - + - + - + @@ -13382,7 +13138,7 @@ - + @@ -13395,17 +13151,17 @@ - + - + - + @@ -13413,7 +13169,7 @@ - + @@ -13426,17 +13182,17 @@ - + - + - + @@ -13444,7 +13200,7 @@ - + @@ -13457,17 +13213,17 @@ - + - + - + @@ -13475,7 +13231,7 @@ - + @@ -13488,17 +13244,17 @@ - + - + - + @@ -13506,7 +13262,7 @@ - + @@ -13519,17 +13275,17 @@ - + - + - + @@ -13537,7 +13293,7 @@ - + @@ -13550,17 +13306,17 @@ - + - + - + @@ -13568,7 +13324,7 @@ - + @@ -13581,17 +13337,17 @@ - + - + - + @@ -13599,7 +13355,7 @@ - + @@ -13612,17 +13368,17 @@ - + - + - + @@ -13630,7 +13386,7 @@ - + @@ -13643,17 +13399,17 @@ - + - + - + @@ -13661,7 +13417,7 @@ - + @@ -13674,17 +13430,17 @@ - + - + - + @@ -13692,7 +13448,7 @@ - + @@ -13705,17 +13461,17 @@ - + - + - + @@ -13723,7 +13479,7 @@ - + @@ -13736,17 +13492,17 @@ - + - + - + @@ -13754,7 +13510,7 @@ - + @@ -13767,17 +13523,17 @@ - + - + - + @@ -13785,7 +13541,7 @@ - + @@ -13798,17 +13554,17 @@ - + - + - + @@ -13816,7 +13572,7 @@ - + @@ -13829,17 +13585,17 @@ - + - + - + @@ -13847,7 +13603,7 @@ - + @@ -13860,48 +13616,17 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + @@ -13909,7 +13634,7 @@ - + @@ -13922,110 +13647,17 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + @@ -14033,7 +13665,7 @@ - + @@ -14046,110 +13678,17 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + @@ -14157,7 +13696,7 @@ - + @@ -14170,17 +13709,17 @@ - + - + - + @@ -14188,7 +13727,7 @@ - + @@ -14201,48 +13740,17 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + @@ -14250,7 +13758,7 @@ - + @@ -14263,48 +13771,17 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + @@ -14312,7 +13789,7 @@ - + @@ -14325,17 +13802,17 @@ - + - + - + @@ -14343,7 +13820,7 @@ - + @@ -14356,17 +13833,17 @@ - + - + - + @@ -14374,7 +13851,7 @@ - + @@ -14387,17 +13864,17 @@ - + - + - + @@ -14405,7 +13882,7 @@ - + @@ -14418,172 +13895,17 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + @@ -14591,7 +13913,7 @@ - + @@ -14604,17 +13926,17 @@ - + - + - + @@ -14622,7 +13944,7 @@ - + @@ -14635,17 +13957,17 @@ - + - + - + @@ -14653,7 +13975,7 @@ - + @@ -14666,17 +13988,17 @@ - + - + - + @@ -14684,7 +14006,7 @@ - + @@ -14697,17 +14019,17 @@ - + - + - + @@ -14715,7 +14037,7 @@ - + @@ -14728,17 +14050,17 @@ - + - + - + @@ -14746,7 +14068,7 @@ - + @@ -14759,79 +14081,17 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + @@ -14839,7 +14099,7 @@ - + @@ -14852,17 +14112,17 @@ - + - + - + @@ -14870,7 +14130,7 @@ - + @@ -14883,17 +14143,17 @@ - + - + - + @@ -14901,7 +14161,7 @@ - + @@ -14914,79 +14174,17 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + @@ -14994,7 +14192,7 @@ - + @@ -15007,79 +14205,17 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + @@ -15087,7 +14223,7 @@ - + @@ -15100,17 +14236,17 @@ - + - + - + @@ -15118,7 +14254,7 @@ - + @@ -15131,17 +14267,17 @@ - + - + - + @@ -15149,7 +14285,7 @@ - + @@ -15162,17 +14298,17 @@ - + - + - + @@ -15180,7 +14316,7 @@ - + @@ -15193,17 +14329,17 @@ - + - + - + @@ -15211,7 +14347,7 @@ - + @@ -15224,17 +14360,17 @@ - + - + - + @@ -15242,7 +14378,7 @@ - + @@ -15255,17 +14391,17 @@ - + - + - + @@ -15273,7 +14409,7 @@ - + @@ -15286,17 +14422,17 @@ - + - + - + @@ -15304,7 +14440,7 @@ - + @@ -15317,17 +14453,17 @@ - + - + - + @@ -15335,7 +14471,7 @@ - + @@ -15348,17 +14484,17 @@ - + - + - + @@ -15366,7 +14502,7 @@ - + @@ -15379,17 +14515,17 @@ - + - + - + @@ -15397,7 +14533,7 @@ - + @@ -15410,17 +14546,17 @@ - + - + - + @@ -15428,7 +14564,7 @@ - + @@ -15441,17 +14577,17 @@ - + - + - + @@ -15459,7 +14595,7 @@ - + @@ -15472,17 +14608,17 @@ - + - + - + @@ -15490,7 +14626,7 @@ - + @@ -15503,17 +14639,17 @@ - + - + - + @@ -15521,7 +14657,7 @@ - + @@ -15534,17 +14670,17 @@ - + - + - + @@ -15552,7 +14688,7 @@ - + @@ -15565,48 +14701,17 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + @@ -15614,7 +14719,7 @@ - + @@ -15627,17 +14732,17 @@ - + - + - + @@ -15645,7 +14750,7 @@ - + @@ -15658,141 +14763,17 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + @@ -15800,7 +14781,7 @@ - + @@ -15813,17 +14794,17 @@ - + - + - + @@ -15831,7 +14812,7 @@ - + @@ -15842,24 +14823,495 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + - + @@ -15867,7 +15319,7 @@ - + @@ -15887,57 +15339,21 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -15945,7 +15361,7 @@ - + @@ -15965,7 +15381,13 @@ - + + + + + + + @@ -15973,7 +15395,93 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -16009,91 +15517,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -16101,1004 +15525,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -17109,10 +15536,22 @@ - - + + - + + + + + + + + + + + + + @@ -17120,7 +15559,7 @@ - + @@ -17128,7 +15567,7 @@ - + @@ -17148,7 +15587,7 @@ - + @@ -17156,7 +15595,7 @@ - + @@ -17168,6 +15607,13 @@ + + + + + + + @@ -17209,9 +15655,9 @@ - - - + + + @@ -17221,49 +15667,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -17271,91 +15675,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -17366,10 +15686,16 @@ - - + + - + + + + + + + @@ -17377,125 +15703,83 @@ - + - - - - - - - - - - - - - - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - - - + + + - - - - - - - - - - - - - - - - + + + + + + + + + - - - - - - - - + + - + - + - - + + - + + + + + + + + + + + + + @@ -17503,7 +15787,121 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -17539,7 +15937,7 @@ - + @@ -17547,77 +15945,41 @@ - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -17625,7 +15987,127 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -17645,7 +16127,7 @@ - + @@ -17653,7 +16135,475 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -17689,27 +16639,15 @@ - + - - - - - - - - - - - - - - + + - + @@ -17720,10 +16658,16 @@ - - + + - + + + + + + + @@ -17731,7 +16675,372 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -17767,49 +17076,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -17817,63 +17084,27 @@ - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -17894,19 +17125,15 @@ - + + + + + - - - - - - - - - + @@ -17914,23 +17141,47 @@ - + - + + + + + - + + + + + - - + + - + + + + + + + + + + + + + + + + + @@ -17941,30 +17192,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - @@ -17974,19 +17201,23 @@ - + - + - + - + + + + + @@ -17994,39 +17225,27 @@ - + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + @@ -18042,20 +17261,240 @@ - + - - - - + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -18068,25 +17507,27 @@ + + + + + + + + + + + + + - - - - - - - - - - - - + @@ -18101,224 +17542,20 @@ + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + From 6584e1290be6c5c8adbb889da4f780b63ef4e294 Mon Sep 17 00:00:00 2001 From: michabr <82236305+michabr@users.noreply.github.com> Date: Fri, 11 Jun 2021 10:03:06 -0700 Subject: [PATCH 050/116] Reenable LyShine mask support now using Atom (#1218) * Add option to set stencil ref in Dynamic Draw Context * Add depth/stencil attachment slot to UI pass * Rework mask rendering to use Atom * Add missing circle mask image --- .../Common/Assets/Passes/LowEndPipeline.pass | 9 +- .../Common/Assets/Passes/MainPipeline.pass | 7 ++ .../Atom/Feature/Common/Assets/Passes/UI.pass | 17 +++ .../Common/Assets/Passes/UIParent.pass | 12 ++ .../DynamicDraw/DynamicDrawContext.h | 11 +- .../DynamicDraw/DynamicDrawContext.cpp | 13 +++ .../Shaders/LyShineUI.shadervariantlist | 4 +- Gems/LyShine/Code/Source/RenderGraph.cpp | 109 ++++++++---------- Gems/LyShine/Code/Source/RenderGraph.h | 7 +- Gems/LyShine/Code/Source/UiRenderer.cpp | 56 +++++---- Gems/LyShine/Code/Source/UiRenderer.h | 42 ++++++- .../Textures/LyShineExamples/CircleMask.tif | 3 + 12 files changed, 196 insertions(+), 94 deletions(-) create mode 100644 Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/CircleMask.tif diff --git a/Gems/Atom/Feature/Common/Assets/Passes/LowEndPipeline.pass b/Gems/Atom/Feature/Common/Assets/Passes/LowEndPipeline.pass index 38a4524aa2..849094dd69 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/LowEndPipeline.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/LowEndPipeline.pass @@ -322,7 +322,14 @@ "Pass": "AuxGeomPass", "Attachment": "ColorInputOutput" } - } + }, + { + "LocalSlot": "DepthInputOutput", + "AttachmentRef": { + "Pass": "DepthPrePass", + "Attachment": "Depth" + } + } ] }, { diff --git a/Gems/Atom/Feature/Common/Assets/Passes/MainPipeline.pass b/Gems/Atom/Feature/Common/Assets/Passes/MainPipeline.pass index b2e0cf088e..314d999e4d 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/MainPipeline.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/MainPipeline.pass @@ -427,6 +427,13 @@ "Pass": "DebugOverlayPass", "Attachment": "InputOutput" } + }, + { + "LocalSlot": "DepthInputOutput", + "AttachmentRef": { + "Pass": "DepthPrePass", + "Attachment": "Depth" + } } ] }, diff --git a/Gems/Atom/Feature/Common/Assets/Passes/UI.pass b/Gems/Atom/Feature/Common/Assets/Passes/UI.pass index 569fe1d722..ac43f17c11 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/UI.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/UI.pass @@ -7,6 +7,23 @@ "Name": "UIPassTemplate", "PassClass": "RasterPass", "Slots": [ + { + "Name": "DepthInputOutput", + "SlotType": "InputOutput", + "ScopeAttachmentUsage": "DepthStencil", + "LoadStoreAction": { + "ClearValue": { + "Type": "DepthStencil", + "Value": [ + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "LoadActionStencil": "Clear" + } + }, { "Name": "InputOutput", "SlotType": "InputOutput", diff --git a/Gems/Atom/Feature/Common/Assets/Passes/UIParent.pass b/Gems/Atom/Feature/Common/Assets/Passes/UIParent.pass index 0069e89401..4ae67b9b09 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/UIParent.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/UIParent.pass @@ -10,6 +10,11 @@ { "Name": "InputOutput", "SlotType": "InputOutput" + }, + { + "Name": "DepthInputOutput", + "SlotType": "InputOutput", + "ScopeAttachmentUsage": "DepthStencil" } ], "PassRequests": [ @@ -24,6 +29,13 @@ "Pass": "Parent", "Attachment": "InputOutput" } + }, + { + "LocalSlot": "DepthInputOutput", + "AttachmentRef": { + "Pass": "Parent", + "Attachment": "DepthInputOutput" + } } ], "PassData": { diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawContext.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawContext.h index 81b23068a1..94fd20f828 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawContext.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawContext.h @@ -138,6 +138,12 @@ namespace AZ //! Without per draw viewport, the viewport setup in pass is usually used. void UnsetViewport(); + //! Set stencil reference for following draws which are added to this DynamicDrawContext + void SetStencilReference(uint8_t stencilRef); + + //! Get the current stencil reference. + uint8_t GetStencilReference() const; + //! Draw Indexed primitives with vertex and index data and per draw srg //! The per draw srg need to be provided if it's required by shader. void DrawIndexed(void* vertexData, uint32_t vertexCount, void* indexData, uint32_t indexCount, RHI::IndexFormat indexFormat, Data::Instance < ShaderResourceGroup> drawSrg = nullptr); @@ -204,10 +210,13 @@ namespace AZ bool m_useScissor = false; RHI::Scissor m_scissor; - // current scissor + // current viewport bool m_useViewport = false; RHI::Viewport m_viewport; + // Current stencil reference value + uint8_t m_stencilRef = 0; + // Cached RHI pipeline states for different combination of render states AZStd::unordered_map m_cachedRhiPipelineStates; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicDrawContext.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicDrawContext.cpp index 00c2122825..09e3499820 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicDrawContext.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicDrawContext.cpp @@ -382,6 +382,16 @@ namespace AZ m_useViewport = false; } + void DynamicDrawContext::SetStencilReference(uint8_t stencilRef) + { + m_stencilRef = stencilRef; + } + + uint8_t DynamicDrawContext::GetStencilReference() const + { + return m_stencilRef; + } + void DynamicDrawContext::SetShaderVariant(ShaderVariantId shaderVariantId) { AZ_Assert( m_initialized && m_supportShaderVariants, "DynamicDrawContext is not initialized or unable to support shader variants. " @@ -475,6 +485,9 @@ namespace AZ drawItem.m_viewports = &m_viewport; } + // Set stencil reference. Used when stencil is enabled. + drawItem.m_stencilRef = m_stencilRef; + drawItemInfo.m_sortKey = m_sortKey++; m_cachedDrawItems.emplace_back(drawItemInfo); } diff --git a/Gems/AtomLyIntegration/AtomBridge/Assets/Shaders/LyShineUI.shadervariantlist b/Gems/AtomLyIntegration/AtomBridge/Assets/Shaders/LyShineUI.shadervariantlist index 79bb726c9f..c7eddb10f2 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Assets/Shaders/LyShineUI.shadervariantlist +++ b/Gems/AtomLyIntegration/AtomBridge/Assets/Shaders/LyShineUI.shadervariantlist @@ -4,7 +4,7 @@ { "StableId": 1, "Options": { - "o_preMultiplyAlpha": "true", + "o_preMultiplyAlpha": "false", "o_alphaTest": "false", "o_srgbWrite": "true", "o_modulate": "Modulate::None" @@ -14,7 +14,7 @@ "StableId": 2, "Options": { "o_preMultiplyAlpha": "false", - "o_alphaTest": "false", + "o_alphaTest": "true", "o_srgbWrite": "true", "o_modulate": "Modulate::None" } diff --git a/Gems/LyShine/Code/Source/RenderGraph.cpp b/Gems/LyShine/Code/Source/RenderGraph.cpp index d5a1df7b15..ad2c46f8e6 100644 --- a/Gems/LyShine/Code/Source/RenderGraph.cpp +++ b/Gems/LyShine/Code/Source/RenderGraph.cpp @@ -137,7 +137,11 @@ namespace LyShine AZ::RHI::Ptr dynamicDraw = uiRenderer->GetDynamicDrawContext(); const UiRenderer::UiShaderData& uiShaderData = uiRenderer->GetUiShaderData(); - dynamicDraw->SetShaderVariant(uiShaderData.m_shaderVariantDefault); + // Set render state + dynamicDraw->SetStencilState(uiRenderer->GetBaseState().m_stencilState); + dynamicDraw->SetTarget0BlendState(uiRenderer->GetBaseState().m_blendState); + + dynamicDraw->SetShaderVariant(uiRenderer->GetCurrentShaderVariant()); // Set up per draw SRG AZ::Data::Instance drawSrg = dynamicDraw->NewDrawSrg(); @@ -307,7 +311,7 @@ namespace LyShine //////////////////////////////////////////////////////////////////////////////////////////////////// void MaskRenderNode::Render(UiRenderer* uiRenderer) { - int priorBaseState = uiRenderer->GetBaseState(); + UiRenderer::BaseState priorBaseState = uiRenderer->GetBaseState(); if (m_isMaskingEnabled || m_drawBehind) { @@ -369,68 +373,61 @@ namespace LyShine #endif //////////////////////////////////////////////////////////////////////////////////////////////////// - void MaskRenderNode::SetupBeforeRenderingMask(UiRenderer* uiRenderer, bool firstPass, int priorBaseState) + void MaskRenderNode::SetupBeforeRenderingMask(UiRenderer* uiRenderer, bool firstPass, UiRenderer::BaseState priorBaseState) { + UiRenderer::BaseState curBaseState = priorBaseState; + // If using alpha test for drawing the renderable components on this element then we turn on // alpha test as a pre-render step - int alphaTest = 0; - if (m_useAlphaTest) - { - alphaTest = GS_ALPHATEST_GREATER; - } + curBaseState.m_useAlphaTest = m_useAlphaTest; // if either of the draw flags are checked then we may want to draw the renderable component(s) // on this element, otherwise use the color mask to stop them rendering - int colorMask = GS_COLMASK_NONE; + curBaseState.m_blendState.m_enable = false; + curBaseState.m_blendState.m_writeMask = 0x0; if ((m_drawBehind && firstPass) || (m_drawInFront && !firstPass)) { - colorMask = 0; // mask everything, don't write color or alpha, we just write to stencil buffer + curBaseState.m_blendState.m_enable = true; + curBaseState.m_blendState.m_writeMask = 0xF; } - if (m_isMaskingEnabled) + if (m_isMaskingEnabled) { + AZ::RHI::StencilOpState stencilOpState; + stencilOpState.m_func = AZ::RHI::ComparisonFunc::Equal; + // masking is enabled so we want to setup to increment (first pass) or decrement (second pass) // the stencil buff when rendering the renderable component(s) on this element - int passOp = 0; if (firstPass) { - passOp = STENCOP_PASS(FSS_STENCOP_INCR); - gEnv->pRenderer->PushProfileMarker(s_maskIncrProfileMarker); + stencilOpState.m_passOp = AZ::RHI::StencilOp::Increment; } else { - passOp = STENCOP_PASS(FSS_STENCOP_DECR); - gEnv->pRenderer->PushProfileMarker(s_maskDecrProfileMarker); + stencilOpState.m_passOp = AZ::RHI::StencilOp::Decrement; } - // set up for stencil write - const uint32 stencilRef = uiRenderer->GetStencilRef(); - const uint32 stencilMask = 0xFF; - const uint32 stencilWriteMask = 0xFF; - const int32 stencilState = STENC_FUNC(FSS_STENCFUNC_EQUAL) - | STENCOP_FAIL(FSS_STENCOP_KEEP) | STENCOP_ZFAIL(FSS_STENCOP_KEEP) | passOp; - gEnv->pRenderer->SetStencilState(stencilState, stencilRef, stencilMask, stencilWriteMask); + curBaseState.m_stencilState.m_frontFace = stencilOpState; + curBaseState.m_stencilState.m_backFace = stencilOpState; - // Set the base state that should be used when rendering the renderable component(s) on this - // element - uiRenderer->SetBaseState(priorBaseState | GS_STENCIL | alphaTest | colorMask); + // set up for stencil write + AZ::RHI::Ptr dynamicDraw = uiRenderer->GetDynamicDrawContext(); + dynamicDraw->SetStencilReference(uiRenderer->GetStencilRef()); + curBaseState.m_stencilState.m_enable = true; + curBaseState.m_stencilState.m_writeMask = 0xFF; } else { // masking is not enabled - - // Even if not masking we still use alpha test (if checked). This is primarily to help the user to - // visualize what their alpha tested mask looks like. - if (colorMask || alphaTest) - { - uiRenderer->SetBaseState(priorBaseState | colorMask | alphaTest); - } + curBaseState.m_stencilState.m_enable = false; } + + uiRenderer->SetBaseState(curBaseState); } //////////////////////////////////////////////////////////////////////////////////////////////////// - void MaskRenderNode::SetupAfterRenderingMask(UiRenderer* uiRenderer, bool firstPass, int priorBaseState) + void MaskRenderNode::SetupAfterRenderingMask(UiRenderer* uiRenderer, bool firstPass, UiRenderer::BaseState priorBaseState) { if (m_isMaskingEnabled) { @@ -442,26 +439,29 @@ namespace LyShine if (firstPass) { uiRenderer->IncrementStencilRef(); - gEnv->pRenderer->PopProfileMarker(s_maskIncrProfileMarker); } else { uiRenderer->DecrementStencilRef(); - gEnv->pRenderer->PopProfileMarker(s_maskDecrProfileMarker); } - // turn off stencil write and turn on stencil test - const uint32 stencilRef = uiRenderer->GetStencilRef(); - const uint32 stencilMask = 0xFF; - const uint32 stencilWriteMask = 0x00; - const int32 stencilState = STENC_FUNC(FSS_STENCFUNC_EQUAL) - | STENCOP_FAIL(FSS_STENCOP_KEEP) | STENCOP_ZFAIL(FSS_STENCOP_KEEP) | STENCOP_PASS(FSS_STENCOP_KEEP); - gEnv->pRenderer->SetStencilState(stencilState, stencilRef, stencilMask, stencilWriteMask); + AZ::RHI::Ptr dynamicDraw = uiRenderer->GetDynamicDrawContext(); + dynamicDraw->SetStencilReference(uiRenderer->GetStencilRef()); if (firstPass) { - // first pass, turn on stencil test for drawing children - uiRenderer->SetBaseState(priorBaseState | GS_STENCIL); + UiRenderer::BaseState curBaseState = priorBaseState; + + // turn off stencil write and turn on stencil test + curBaseState.m_stencilState.m_enable = true; + curBaseState.m_stencilState.m_writeMask = 0x00; + + AZ::RHI::StencilOpState stencilOpState; + stencilOpState.m_func = AZ::RHI::ComparisonFunc::Equal; + curBaseState.m_stencilState.m_frontFace = stencilOpState; + curBaseState.m_stencilState.m_backFace = stencilOpState; + + uiRenderer->SetBaseState(curBaseState); } else { @@ -475,7 +475,6 @@ namespace LyShine // remove any color mask or alpha test that we set in pre-render uiRenderer->SetBaseState(priorBaseState); } - } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -637,35 +636,24 @@ namespace LyShine //////////////////////////////////////////////////////////////////////////////////////////////////// void RenderGraph::BeginMask(bool isMaskingEnabled, bool useAlphaTest, bool drawBehind, bool drawInFront) { -#ifdef LYSHINE_ATOM_TODO // keeping this code for future phase (masks and render targets) - // this uses pool allocator MaskRenderNode* maskRenderNode = new MaskRenderNode(m_currentMask, isMaskingEnabled, useAlphaTest, drawBehind, drawInFront); m_currentMask = maskRenderNode; m_renderNodeListStack.push(&maskRenderNode->GetMaskRenderNodeList()); -#else - AZ_UNUSED(drawInFront); - AZ_UNUSED(drawBehind); - AZ_UNUSED(useAlphaTest); - AZ_UNUSED(isMaskingEnabled); -#endif } //////////////////////////////////////////////////////////////////////////////////////////////////// void RenderGraph::StartChildrenForMask() { -#ifdef LYSHINE_ATOM_TODO // keeping this code for future phase (masks and render targets) AZ_Assert(m_currentMask, "Calling StartChildrenForMask while not defining a mask"); m_renderNodeListStack.pop(); m_renderNodeListStack.push(&m_currentMask->GetContentRenderNodeList()); -#endif } //////////////////////////////////////////////////////////////////////////////////////////////////// void RenderGraph::EndMask() { -#ifdef LYSHINE_ATOM_TODO // keeping this code for future phase (masks and render targets) AZ_Assert(m_currentMask, "Calling EndMask while not defining a mask"); if (m_currentMask) { @@ -686,7 +674,6 @@ namespace LyShine m_renderNodeListStack.top()->push_back(newMaskRenderNode); } } -#endif } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -996,6 +983,12 @@ namespace LyShine // LYSHINE_ATOM_TODO - will probably need to support this when converting UI Editor to use Atom AZ_UNUSED(viewportSize); + AZ::RHI::Ptr dynamicDraw = uiRenderer->GetDynamicDrawContext(); + + // Disable stencil and enable blend/color write + dynamicDraw->SetStencilState(uiRenderer->GetBaseState().m_stencilState); + dynamicDraw->SetTarget0BlendState(uiRenderer->GetBaseState().m_blendState); + // First render the render targets, they are sorted so that more deeply nested ones are rendered first. #ifdef LYSHINE_ATOM_TODO // keeping this code for reference for future phase (render targets) diff --git a/Gems/LyShine/Code/Source/RenderGraph.h b/Gems/LyShine/Code/Source/RenderGraph.h index 2f1586e857..355616a29a 100644 --- a/Gems/LyShine/Code/Source/RenderGraph.h +++ b/Gems/LyShine/Code/Source/RenderGraph.h @@ -22,12 +22,11 @@ #include #include +#include "UiRenderer.h" #ifndef _RELEASE #include "LyShineDebug.h" #endif -class UiRenderer; - namespace LyShine { enum RenderNodeType @@ -157,8 +156,8 @@ namespace LyShine #endif private: // functions - void SetupBeforeRenderingMask(UiRenderer* uiRenderer, bool firstPass, int priorBaseState); - void SetupAfterRenderingMask(UiRenderer* uiRenderer, bool firstPass, int priorBaseState); + void SetupBeforeRenderingMask(UiRenderer* uiRenderer, bool firstPass, UiRenderer::BaseState priorBaseState); + void SetupAfterRenderingMask(UiRenderer* uiRenderer, bool firstPass, UiRenderer::BaseState priorBaseState); private: // data AZStd::vector m_maskRenderNodes; //!< The render nodes used to render the mask shape diff --git a/Gems/LyShine/Code/Source/UiRenderer.cpp b/Gems/LyShine/Code/Source/UiRenderer.cpp index 57acbed5d5..e3ded694b5 100644 --- a/Gems/LyShine/Code/Source/UiRenderer.cpp +++ b/Gems/LyShine/Code/Source/UiRenderer.cpp @@ -20,7 +20,6 @@ #include #include #include -#include // LYSHINE_ATOM_TODO - remove when GS_DEPTHFUNC_LEQUAL reference is removed with LyShine render target Atom conversion #include #include @@ -33,9 +32,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// UiRenderer::UiRenderer(AZ::RPI::ViewportContextPtr viewportContext) - : m_baseState(GS_DEPTHFUNC_LEQUAL) - , m_stencilRef(0) - , m_viewportContext(viewportContext) + : m_viewportContext(viewportContext) { // Use bootstrap scene event to indicate when the RPI has fully // initialized with all assets loaded and is ready to be used @@ -127,6 +124,8 @@ void UiRenderer::CreateDynamicDrawContext(AZ::RPI::ScenePtr scene, AZ::Data::Ins { "TEXCOORD", AZ::RHI::Format::R32G32_FLOAT }, { "BLENDINDICES", AZ::RHI::Format::R16G16_UINT } } ); + m_dynamicDraw->AddDrawStateOptions(AZ::RPI::DynamicDrawContext::DrawStateOptions::StencilState + | AZ::RPI::DynamicDrawContext::DrawStateOptions::BlendMode); m_dynamicDraw->EndInit(); } @@ -170,25 +169,24 @@ void UiRenderer::CacheShaderData(const AZ::RHI::Ptr shaderOptionsDefault.push_back(AZ::RPI::ShaderOption(AZ::Name("o_srgbWrite"), AZ::Name("true"))); shaderOptionsDefault.push_back(AZ::RPI::ShaderOption(AZ::Name("o_modulate"), AZ::Name("Modulate::None"))); m_uiShaderData.m_shaderVariantDefault = dynamicDraw->UseShaderVariant(shaderOptionsDefault); + AZ::RPI::ShaderOptionList shaderOptionsAlphaTest; + shaderOptionsAlphaTest.push_back(AZ::RPI::ShaderOption(AZ::Name("o_preMultiplyAlpha"), AZ::Name("false"))); + shaderOptionsAlphaTest.push_back(AZ::RPI::ShaderOption(AZ::Name("o_alphaTest"), AZ::Name("true"))); + shaderOptionsAlphaTest.push_back(AZ::RPI::ShaderOption(AZ::Name("o_srgbWrite"), AZ::Name("true"))); + shaderOptionsAlphaTest.push_back(AZ::RPI::ShaderOption(AZ::Name("o_modulate"), AZ::Name("Modulate::None"))); + m_uiShaderData.m_shaderVariantAlphaTest = dynamicDraw->UseShaderVariant(shaderOptionsAlphaTest); } //////////////////////////////////////////////////////////////////////////////////////////////////// void UiRenderer::BeginUiFrameRender() { -#ifdef LYSHINE_ATOM_TODO - m_renderer = gEnv->pRenderer; - - // we are rendering at the end of the frame, after tone mapping, so we should be writing sRGB values - m_renderer->SetSrgbWrite(true); - #ifndef _RELEASE if (m_debugTextureDataRecordLevel > 0) { m_texturesUsedInFrame.clear(); } #endif -#endif - + // Various platform drivers expect all texture slots used in the shader to be bound BindNullTexture(); } @@ -204,18 +202,10 @@ void UiRenderer::EndUiFrameRender() //////////////////////////////////////////////////////////////////////////////////////////////////// void UiRenderer::BeginCanvasRender() { -#ifdef LYSHINE_ATOM_TODO - m_baseState = GS_NODEPTHTEST; - m_stencilRef = 0; - // Set default starting state - IRenderer* renderer = gEnv->pRenderer; - - renderer->SetCullMode(R_CULL_DISABLE); - renderer->SetColorOp(eCO_MODULATE, eCO_MODULATE, DEF_TEXARG0, DEF_TEXARG0); - renderer->SetState(GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA | GS_NODEPTHTEST); -#endif + // Set base state + m_baseState.ResetToDefault(); } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -229,11 +219,13 @@ AZ::RHI::Ptr UiRenderer::GetDynamicDrawContext() return m_dynamicDraw; } +//////////////////////////////////////////////////////////////////////////////////////////////////// const UiRenderer::UiShaderData& UiRenderer::GetUiShaderData() { return m_uiShaderData; } +//////////////////////////////////////////////////////////////////////////////////////////////////// AZ::Matrix4x4 UiRenderer::GetModelViewProjectionMatrix() { auto viewportContext = GetViewportContext(); @@ -253,6 +245,7 @@ AZ::Matrix4x4 UiRenderer::GetModelViewProjectionMatrix() return modelViewProjMat; } +//////////////////////////////////////////////////////////////////////////////////////////////////// AZ::Vector2 UiRenderer::GetViewportSize() { auto viewportContext = GetViewportContext(); @@ -267,17 +260,30 @@ AZ::Vector2 UiRenderer::GetViewportSize() } //////////////////////////////////////////////////////////////////////////////////////////////////// -int UiRenderer::GetBaseState() +UiRenderer::BaseState UiRenderer::GetBaseState() { return m_baseState; } //////////////////////////////////////////////////////////////////////////////////////////////////// -void UiRenderer::SetBaseState(int state) +void UiRenderer::SetBaseState(BaseState state) { m_baseState = state; } +//////////////////////////////////////////////////////////////////////////////////////////////////// +AZ::RPI::ShaderVariantId UiRenderer::GetCurrentShaderVariant() +{ + AZ::RPI::ShaderVariantId variantId = m_uiShaderData.m_shaderVariantDefault; + + if (m_baseState.m_useAlphaTest) + { + variantId = m_uiShaderData.m_shaderVariantAlphaTest; + } + + return variantId; +} + //////////////////////////////////////////////////////////////////////////////////////////////////// uint32 UiRenderer::GetStencilRef() { @@ -354,6 +360,7 @@ void UiRenderer::DebugDisplayTextureData(int recordingOption) { if (recordingOption > 0) { +#ifdef LYSHINE_ATOM_TODO // Convert debug to use Atom images // compute the total area of all the textures, also create a vector that we can sort by area AZStd::vector textures; int totalArea = 0; @@ -431,6 +438,7 @@ void UiRenderer::DebugDisplayTextureData(int recordingOption) texture->GetWidth(), texture->GetHeight(), texture->GetDataSize(), texture->GetFormatName(), texture->GetName()); WriteLine(buffer, white); } +#endif } } diff --git a/Gems/LyShine/Code/Source/UiRenderer.h b/Gems/LyShine/Code/Source/UiRenderer.h index 888c88586a..413e8c45cf 100644 --- a/Gems/LyShine/Code/Source/UiRenderer.h +++ b/Gems/LyShine/Code/Source/UiRenderer.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #ifndef _RELEASE @@ -38,6 +39,36 @@ public: // types AZ::RHI::ShaderInputConstantIndex m_isClampInputIndex; AZ::RPI::ShaderVariantId m_shaderVariantDefault; + AZ::RPI::ShaderVariantId m_shaderVariantAlphaTest; + }; + + // Base state + struct BaseState + { + BaseState() + { + ResetToDefault(); + } + + void ResetToDefault() + { + // Enable blend/color write + m_blendState.m_enable = true; + m_blendState.m_writeMask = 0xF; + m_blendState.m_blendSource = AZ::RHI::BlendFactor::AlphaSource; + m_blendState.m_blendDest = AZ::RHI::BlendFactor::AlphaSourceInverse; + m_blendState.m_blendOp = AZ::RHI::BlendOp::Add; + + // Disable stencil + m_stencilState = AZ::RHI::StencilState(); + m_stencilState.m_enable = 0; + + m_useAlphaTest = false; + } + + AZ::RHI::TargetBlendState m_blendState; + AZ::RHI::StencilState m_stencilState; + bool m_useAlphaTest = false; }; public: // member functions @@ -74,10 +105,13 @@ public: // member functions AZ::Vector2 GetViewportSize(); //! Get the current base state - int GetBaseState(); + BaseState GetBaseState(); //! Set the base state - void SetBaseState(int state); + void SetBaseState(BaseState state); + + //! Get the shader variant based on current render properties + AZ::RPI::ShaderVariantId GetCurrentShaderVariant(); //! Get the current stencil test reference value uint32 GetStencilRef(); @@ -126,8 +160,8 @@ protected: // attributes static constexpr char LogName[] = "UiRenderer"; - int m_baseState; - uint32 m_stencilRef; + BaseState m_baseState; + uint32 m_stencilRef = 0; UiShaderData m_uiShaderData; AZ::RHI::Ptr m_dynamicDraw; diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/CircleMask.tif b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/CircleMask.tif new file mode 100644 index 0000000000..fd29516609 --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/CircleMask.tif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8474b897fe02f70ed8d0e5c47cae8c816c832a7a5739b8c32317737fd275774f +size 1069752 From bf1b8001361923548feb06ea077ce4fcf61bc8fc Mon Sep 17 00:00:00 2001 From: srikappa-amzn Date: Fri, 11 Jun 2021 10:25:28 -0700 Subject: [PATCH 051/116] minor change to order of if and foreach --- scripts/ctest/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/ctest/CMakeLists.txt b/scripts/ctest/CMakeLists.txt index c4f86087b1..c07aaf4bff 100644 --- a/scripts/ctest/CMakeLists.txt +++ b/scripts/ctest/CMakeLists.txt @@ -20,8 +20,8 @@ endif() # Tests ################################################################################ -foreach(suite_name ${LY_TEST_GLOBAL_KNOWN_SUITE_NAMES}) - if(PAL_TRAIT_TEST_LYTESTTOOLS_SUPPORTED) +if(PAL_TRAIT_TEST_LYTESTTOOLS_SUPPORTED) + foreach(suite_name ${LY_TEST_GLOBAL_KNOWN_SUITE_NAMES}) ly_add_pytest( NAME pytest_sanity_${suite_name}_no_gpu PATH ${CMAKE_CURRENT_LIST_DIR}/sanity_test.py @@ -34,8 +34,8 @@ foreach(suite_name ${LY_TEST_GLOBAL_KNOWN_SUITE_NAMES}) TEST_SUITE ${suite_name} TEST_REQUIRES gpu ) - endif() -endforeach() + endforeach() +endif() # EPB Sanity test is being registered here to validate that the ly_add_editor_python_test function works. #if(PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_BUILD_TESTS_SUPPORTED AND AutomatedTesting IN_LIST LY_PROJECTS_TARGET_NAME) From 4818d1ce809436efd72b4fa51064e60fae565640 Mon Sep 17 00:00:00 2001 From: jackalbe <23512001+jackalbe@users.noreply.github.com> Date: Fri, 11 Jun 2021 12:25:45 -0500 Subject: [PATCH 052/116] {LYN-4224} Fix for the file scan slowdown (#1252) * {LYN-4224} Fix for the file scan slowdown (#1183) * {LYN-4224} Fix for the file scan slowdown * Fixed a slowdown in the file scanning logic * Improved the file scanning logic from previous code by 40% Tests: Using Testing\Pytest\AutomatedTesting_BlastTest old code: === 7 passed in 96.13s (0:01:36) === current code: === 7 passed in 160.45s (0:02:40) ==== newest code: === 7 passed in 52.91s === * fixing a unit test compile error * unit test fixes * another file improvement * fix for legacy level loading taking too long * making an enum for the search types * switched the enum to "allow" types to make the input more clear * got rid of orphaned const variables --- Code/CryEngine/CryCommon/Mocks/ICryPakMock.h | 2 +- .../CrySystem/LevelSystem/LevelSystem.cpp | 11 ++-- .../AzFramework/Archive/Archive.cpp | 24 +++++++- .../AzFramework/AzFramework/Archive/Archive.h | 2 +- .../AzFramework/Archive/ArchiveFindData.cpp | 60 ++++++++++--------- .../AzFramework/Archive/ArchiveFindData.h | 7 +-- .../AzFramework/Archive/IArchive.h | 9 ++- Code/Sandbox/Editor/CryEditDoc.cpp | 2 +- .../Code/Tests/AudioSystemEditorTest.cpp | 13 ++-- 9 files changed, 79 insertions(+), 51 deletions(-) diff --git a/Code/CryEngine/CryCommon/Mocks/ICryPakMock.h b/Code/CryEngine/CryCommon/Mocks/ICryPakMock.h index 2d451793bc..072a798985 100644 --- a/Code/CryEngine/CryCommon/Mocks/ICryPakMock.h +++ b/Code/CryEngine/CryCommon/Mocks/ICryPakMock.h @@ -67,7 +67,7 @@ struct CryPakMock MOCK_METHOD1(PoolMalloc, void*(size_t size)); MOCK_METHOD1(PoolFree, void(void* p)); MOCK_METHOD3(PoolAllocMemoryBlock, AZStd::intrusive_ptr (size_t nSize, const char* sUsage, size_t nAlign)); - MOCK_METHOD3(FindFirst, AZ::IO::ArchiveFileIterator(AZStd::string_view pDir, uint32_t nFlags, bool bAllOwUseFileSystem)); + MOCK_METHOD2(FindFirst, AZ::IO::ArchiveFileIterator(AZStd::string_view pDir, AZ::IO::IArchive::EFileSearchType)); MOCK_METHOD1(FindNext, AZ::IO::ArchiveFileIterator(AZ::IO::ArchiveFileIterator handle)); MOCK_METHOD1(FindClose, bool(AZ::IO::ArchiveFileIterator)); MOCK_METHOD1(GetModificationTime, AZ::IO::IArchive::FileTime(AZ::IO::HandleType f)); diff --git a/Code/CryEngine/CrySystem/LevelSystem/LevelSystem.cpp b/Code/CryEngine/CrySystem/LevelSystem/LevelSystem.cpp index c36b9bcee7..08caeeeb70 100644 --- a/Code/CryEngine/CrySystem/LevelSystem/LevelSystem.cpp +++ b/Code/CryEngine/CrySystem/LevelSystem/LevelSystem.cpp @@ -306,8 +306,7 @@ void CLevelSystem::ScanFolder(const char* subfolder, bool modFolder) AZStd::unordered_set pakList; - bool allowFileSystem = true; - AZ::IO::ArchiveFileIterator handle = pPak->FindFirst(search.c_str(), 0, allowFileSystem); + AZ::IO::ArchiveFileIterator handle = pPak->FindFirst(search.c_str(), AZ::IO::IArchive::eFileSearchType_AllowOnDiskOnly); if (handle) { @@ -320,7 +319,7 @@ void CLevelSystem::ScanFolder(const char* subfolder, bool modFolder) { if (AZ::StringFunc::Equal(handle.m_filename.data(), LevelPakName)) { - // level folder contain pak files like 'level.pak' + // level folder contain pak files like 'level.pak' // which we only want to load during level loading. continue; } @@ -351,7 +350,7 @@ void CLevelSystem::ScanFolder(const char* subfolder, bool modFolder) PopulateLevels(search, folder, pPak, modFolder, false); // Load levels outside of the bundles to maintain backward compatibility. PopulateLevels(search, folder, pPak, modFolder, true); - + } void CLevelSystem::PopulateLevels( @@ -360,7 +359,7 @@ void CLevelSystem::PopulateLevels( { // allow this find first to actually touch the file system // (causes small overhead but with minimal amount of levels this should only be around 150ms on actual DVD Emu) - AZ::IO::ArchiveFileIterator handle = pPak->FindFirst(searchPattern.c_str(), 0, fromFileSystemOnly); + AZ::IO::ArchiveFileIterator handle = pPak->FindFirst(searchPattern.c_str(), AZ::IO::IArchive::eFileSearchType_AllowOnDiskOnly); if (handle) { @@ -973,7 +972,7 @@ void CLevelSystem::UnloadLevel() m_lastLevelName.clear(); SAFE_RELEASE(m_pCurrentLevel); - + // Force Lua garbage collection (may no longer be needed now the legacy renderer has been removed). // Normally the GC step is triggered at the end of this method (by the ESYSTEM_EVENT_LEVEL_POST_UNLOAD event). EBUS_EVENT(AZ::ScriptSystemRequestBus, GarbageCollect); diff --git a/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp b/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp index 04573eb2e5..5cb2006447 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp +++ b/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp @@ -1290,7 +1290,7 @@ namespace AZ::IO ////////////////////////////////////////////////////////////////////////// - AZ::IO::ArchiveFileIterator Archive::FindFirst(AZStd::string_view pDir, [[maybe_unused]] uint32_t nPathFlags, bool bAllowUseFileSystem) + AZ::IO::ArchiveFileIterator Archive::FindFirst(AZStd::string_view pDir, EFileSearchType searchType) { auto szFullPath = AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(pDir); if (!szFullPath) @@ -1299,8 +1299,26 @@ namespace AZ::IO return {}; } + bool bScanZips{}; + bool bAllowUseFileSystem{}; + switch (searchType) + { + case IArchive::eFileSearchType_AllowInZipsOnly: + bAllowUseFileSystem = false; + bScanZips = true; + break; + case IArchive::eFileSearchType_AllowOnDiskAndInZips: + bAllowUseFileSystem = true; + bScanZips = true; + break; + case IArchive::eFileSearchType_AllowOnDiskOnly: + bAllowUseFileSystem = true; + bScanZips = false; + break; + } + AZStd::intrusive_ptr pFindData = new AZ::IO::FindData(); - pFindData->Scan(this, szFullPath->Native(), bAllowUseFileSystem); + pFindData->Scan(this, szFullPath->Native(), bAllowUseFileSystem, bScanZips); return pFindData->Fetch(); } @@ -1676,7 +1694,7 @@ namespace AZ::IO return true; } - if (AZ::IO::ArchiveFileIterator fileIterator = FindFirst(pWildcardIn, 0, true); fileIterator) + if (AZ::IO::ArchiveFileIterator fileIterator = FindFirst(pWildcardIn, IArchive::eFileSearchType_AllowOnDiskOnly); fileIterator) { AZStd::vector files; do diff --git a/Code/Framework/AzFramework/AzFramework/Archive/Archive.h b/Code/Framework/AzFramework/AzFramework/Archive/Archive.h index 997b3e3d2c..329beb4291 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/Archive.h +++ b/Code/Framework/AzFramework/AzFramework/Archive/Archive.h @@ -234,7 +234,7 @@ namespace AZ::IO uint64_t FTell(AZ::IO::HandleType handle) override; int FFlush(AZ::IO::HandleType handle) override; int FClose(AZ::IO::HandleType handle) override; - AZ::IO::ArchiveFileIterator FindFirst(AZStd::string_view pDir, uint32_t nPathFlags = 0, bool bAllOwUseFileSystem = false) override; + AZ::IO::ArchiveFileIterator FindFirst(AZStd::string_view pDir, EFileSearchType searchType = eFileSearchType_AllowInZipsOnly) override; AZ::IO::ArchiveFileIterator FindNext(AZ::IO::ArchiveFileIterator fileIterator) override; bool FindClose(AZ::IO::ArchiveFileIterator fileIterator) override; int FEof(AZ::IO::HandleType handle) override; diff --git a/Code/Framework/AzFramework/AzFramework/Archive/ArchiveFindData.cpp b/Code/Framework/AzFramework/AzFramework/Archive/ArchiveFindData.cpp index 1794ae90e7..05da5f16eb 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/ArchiveFindData.cpp +++ b/Code/Framework/AzFramework/AzFramework/Archive/ArchiveFindData.cpp @@ -77,7 +77,7 @@ namespace AZ::IO return m_findData && m_lastFetchValid; } - void FindData::Scan(IArchive* archive, AZStd::string_view szDir, bool bAllowUseFS) + void FindData::Scan(IArchive* archive, AZStd::string_view szDir, bool bAllowUseFS, bool bScanZips) { // get the priority into local variable to avoid it changing in the course of // this function execution @@ -87,12 +87,18 @@ namespace AZ::IO { // first, find the file system files ScanFS(archive, szDir); - ScanZips(archive, szDir); + if (bScanZips) + { + ScanZips(archive, szDir); + } } else { // first, find the zip files - ScanZips(archive, szDir); + if (bScanZips) + { + ScanZips(archive, szDir); + } if (bAllowUseFS || nVarPakPriority != ArchiveLocationPriority::ePakPriorityPakOnly) { ScanFS(archive, szDir); @@ -111,30 +117,31 @@ namespace AZ::IO } AZ::IO::FileIOBase::GetDirectInstance()->FindFiles(searchDirectory.c_str(), pattern.c_str(), [&](const char* filePath) -> bool { - AZ::IO::FileDesc fileDesc; - AZStd::string filePathEntry{filePath}; + AZ::IO::ArchiveFileIterator fileIterator; + fileIterator.m_filename = AZ::IO::PathView(filePath).Filename().Native(); + fileIterator.m_fileDesc.nAttrib = {}; if (AZ::IO::FileIOBase::GetDirectInstance()->IsDirectory(filePath)) { - fileDesc.nAttrib = fileDesc.nAttrib | AZ::IO::FileDesc::Attribute::Subdirectory; + fileIterator.m_fileDesc.nAttrib = fileIterator.m_fileDesc.nAttrib | AZ::IO::FileDesc::Attribute::Subdirectory; + m_fileStack.emplace_back(AZStd::move(fileIterator)); } else { if (AZ::IO::FileIOBase::GetDirectInstance()->IsReadOnly(filePath)) { - fileDesc.nAttrib = fileDesc.nAttrib | AZ::IO::FileDesc::Attribute::ReadOnly; + fileIterator.m_fileDesc.nAttrib = fileIterator.m_fileDesc.nAttrib | AZ::IO::FileDesc::Attribute::ReadOnly; } AZ::u64 fileSize = 0; AZ::IO::FileIOBase::GetDirectInstance()->Size(filePath, fileSize); - fileDesc.nSize = fileSize; - fileDesc.tWrite = AZ::IO::FileIOBase::GetDirectInstance()->ModificationTime(filePath); + fileIterator.m_fileDesc.nSize = fileSize; + fileIterator.m_fileDesc.tWrite = AZ::IO::FileIOBase::GetDirectInstance()->ModificationTime(filePath); // These times are not supported by our file interface - fileDesc.tAccess = fileDesc.tWrite; - fileDesc.tCreate = fileDesc.tWrite; + fileIterator.m_fileDesc.tAccess = fileIterator.m_fileDesc.tWrite; + fileIterator.m_fileDesc.tCreate = fileIterator.m_fileDesc.tWrite; + m_fileStack.emplace_back(AZStd::move(fileIterator)); } - [[maybe_unused]] auto result = m_mapFiles.emplace(AZStd::move(filePathEntry), fileDesc); - AZ_Assert(result.second, "Failed to insert FindData entry for filePath %s", filePath); return true; }); } @@ -164,7 +171,7 @@ namespace AZ::IO fileDesc.nAttrib = AZ::IO::FileDesc::Attribute::ReadOnly | AZ::IO::FileDesc::Attribute::Archive; fileDesc.nSize = fileEntry->desc.lSizeUncompressed; fileDesc.tWrite = fileEntry->GetModificationTime(); - m_mapFiles.emplace(fname, fileDesc); + m_fileStack.emplace_back(AZ::IO::ArchiveFileIterator{ this, fname, fileDesc }); } ZipDir::FindDir findDirectoryEntry(zipCache); @@ -177,7 +184,7 @@ namespace AZ::IO } AZ::IO::FileDesc fileDesc; fileDesc.nAttrib = AZ::IO::FileDesc::Attribute::ReadOnly | AZ::IO::FileDesc::Attribute::Archive | AZ::IO::FileDesc::Attribute::Subdirectory; - m_mapFiles.emplace(fname, fileDesc); + m_fileStack.emplace_back(AZ::IO::ArchiveFileIterator{ this, fname, fileDesc }); } }; @@ -246,7 +253,7 @@ namespace AZ::IO if (!bindRootIter->empty() && AZStd::wildcard_match(sourcePathRemainder.Native(), bindRootIter->Native())) { AZ::IO::FileDesc fileDesc{ AZ::IO::FileDesc::Attribute::ReadOnly | AZ::IO::FileDesc::Attribute::Archive | AZ::IO::FileDesc::Attribute::Subdirectory }; - m_mapFiles.emplace(bindRootIter->Native(), fileDesc); + m_fileStack.emplace_back(AZ::IO::ArchiveFileIterator{ this, bindRootIter->Native(), fileDesc }); } } else @@ -262,22 +269,19 @@ namespace AZ::IO AZ::IO::ArchiveFileIterator FindData::Fetch() { - AZ::IO::ArchiveFileIterator fileIterator; - fileIterator.m_findData = this; - if (m_mapFiles.empty()) + if (m_fileStack.empty()) { - return fileIterator; + AZ::IO::ArchiveFileIterator emptyFileIterator; + emptyFileIterator.m_lastFetchValid = false; + emptyFileIterator.m_findData = this; + return emptyFileIterator; } - auto pakFileIter = m_mapFiles.begin(); - AZStd::string fullFilePath; - AZ::StringFunc::Path::GetFullFileName(pakFileIter->first.c_str(), fullFilePath); - fileIterator.m_filename = AZStd::move(fullFilePath); - fileIterator.m_fileDesc = pakFileIter->second; - fileIterator.m_lastFetchValid = true; - // Remove Fetched item from the FindData map so that the iteration continues - m_mapFiles.erase(pakFileIter); + AZ::IO::ArchiveFileIterator fileIterator{ m_fileStack.back() }; + fileIterator.m_lastFetchValid = true; + fileIterator.m_findData = this; + m_fileStack.pop_back(); return fileIterator; } } diff --git a/Code/Framework/AzFramework/AzFramework/Archive/ArchiveFindData.h b/Code/Framework/AzFramework/AzFramework/Archive/ArchiveFindData.h index d5e23779fc..a07e98c81f 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/ArchiveFindData.h +++ b/Code/Framework/AzFramework/AzFramework/Archive/ArchiveFindData.h @@ -15,7 +15,6 @@ #include #include - namespace AZ::IO { struct IArchive; @@ -74,13 +73,13 @@ namespace AZ::IO AZ_CLASS_ALLOCATOR(FindData, AZ::SystemAllocator, 0); FindData() = default; AZ::IO::ArchiveFileIterator Fetch(); - void Scan(IArchive* archive, AZStd::string_view path, bool bAllowUseFS = false); + void Scan(IArchive* archive, AZStd::string_view path, bool bAllowUseFS = false, bool bScanZips = true); protected: void ScanFS(IArchive* archive, AZStd::string_view path); void ScanZips(IArchive* archive, AZStd::string_view path); - using FileMap = AZStd::map; - FileMap m_mapFiles; + using FileStack = AZStd::vector; + FileStack m_fileStack; }; } diff --git a/Code/Framework/AzFramework/AzFramework/Archive/IArchive.h b/Code/Framework/AzFramework/AzFramework/Archive/IArchive.h index ce8403b033..08bd87c334 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/IArchive.h +++ b/Code/Framework/AzFramework/AzFramework/Archive/IArchive.h @@ -197,6 +197,13 @@ namespace AZ::IO eInMemoryPakLocale_PAK, }; + enum EFileSearchType + { + eFileSearchType_AllowInZipsOnly = 0, + eFileSearchType_AllowOnDiskAndInZips, + eFileSearchType_AllowOnDiskOnly + }; + using SignedFileSize = int64_t; virtual ~IArchive() = default; @@ -315,7 +322,7 @@ namespace AZ::IO // Arguments: // nFlags is a combination of EPathResolutionRules flags. - virtual ArchiveFileIterator FindFirst(AZStd::string_view pDir, uint32_t nFlags = 0, bool bAllowUseFileSystem = false) = 0; + virtual ArchiveFileIterator FindFirst(AZStd::string_view pDir, EFileSearchType searchType = eFileSearchType_AllowInZipsOnly) = 0; virtual ArchiveFileIterator FindNext(AZ::IO::ArchiveFileIterator handle) = 0; virtual bool FindClose(AZ::IO::ArchiveFileIterator handle) = 0; //returns file modification time diff --git a/Code/Sandbox/Editor/CryEditDoc.cpp b/Code/Sandbox/Editor/CryEditDoc.cpp index 5b2a4b9a83..77d5794ab3 100644 --- a/Code/Sandbox/Editor/CryEditDoc.cpp +++ b/Code/Sandbox/Editor/CryEditDoc.cpp @@ -1139,7 +1139,7 @@ bool CCryEditDoc::SaveLevel(const QString& filename) const QString oldLevelPattern = QDir(oldLevelFolder).absoluteFilePath("*.*"); const QString oldLevelName = Path::GetFile(GetLevelPathName()); const QString oldLevelXml = Path::ReplaceExtension(oldLevelName, "xml"); - AZ::IO::ArchiveFileIterator findHandle = pIPak->FindFirst(oldLevelPattern.toUtf8().data(), 0, true); + AZ::IO::ArchiveFileIterator findHandle = pIPak->FindFirst(oldLevelPattern.toUtf8().data(), AZ::IO::IArchive::eFileSearchType_AllowOnDiskAndInZips); if (findHandle) { do diff --git a/Gems/AudioSystem/Code/Tests/AudioSystemEditorTest.cpp b/Gems/AudioSystem/Code/Tests/AudioSystemEditorTest.cpp index e086246e29..d7f9b31e25 100644 --- a/Gems/AudioSystem/Code/Tests/AudioSystemEditorTest.cpp +++ b/Gems/AudioSystem/Code/Tests/AudioSystemEditorTest.cpp @@ -36,14 +36,14 @@ namespace CustomMocks : m_levelName(levelName) {} - AZ::IO::ArchiveFileIterator FindFirst([[maybe_unused]] AZStd::string_view dir, [[maybe_unused]] unsigned int flags, [[maybe_unused]] bool allowUseFileSystem) override + AZ::IO::ArchiveFileIterator FindFirst([[maybe_unused]] AZStd::string_view dir, AZ::IO::IArchive::EFileSearchType) override { AZ::IO::FileDesc fileDesc; fileDesc.nSize = sizeof(AZ::IO::FileDesc); // Add a filename and file description reference to the TestFindData map to make sure the file iterator is valid - AZStd::intrusive_ptr findData = new TestFindData{}; - findData->m_mapFiles.emplace(m_levelName, fileDesc); - return findData->Fetch(); + m_findData = new TestFindData(); + m_findData->m_fileStack.emplace_back(AZ::IO::ArchiveFileIterator{ static_cast(m_findData.get()), m_levelName, fileDesc }); + return m_findData->Fetch(); } AZ::IO::ArchiveFileIterator FindNext(AZ::IO::ArchiveFileIterator iter) override @@ -54,13 +54,14 @@ namespace CustomMocks // public: for easy resetting... AZStd::string m_levelName; - // Add an inherited FindData class to control the adding of a mapfile which indicates that a FileIterator is valid struct TestFindData : AZ::IO::FindData { - using AZ::IO::FindData::m_mapFiles; + using AZ::IO::FindData::m_fileStack; }; + + AZStd::intrusive_ptr m_findData; }; } // namespace CustomMocks From 9bb34a61219ea8b8487cedb71323bdd11dbdf0d1 Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Fri, 11 Jun 2021 11:48:59 -0700 Subject: [PATCH 053/116] Remove references to Wireframe menu item that was removed in a previous PR (#1263) --- Code/Sandbox/Editor/Core/LevelEditorMenuHandler.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/Sandbox/Editor/Core/LevelEditorMenuHandler.cpp b/Code/Sandbox/Editor/Core/LevelEditorMenuHandler.cpp index ebc688f9da..0dec8e3af6 100644 --- a/Code/Sandbox/Editor/Core/LevelEditorMenuHandler.cpp +++ b/Code/Sandbox/Editor/Core/LevelEditorMenuHandler.cpp @@ -715,11 +715,11 @@ QMenu* LevelEditorMenuHandler::CreateViewMenu() { return view.IsViewportPane(); }); -#endif - viewportViewsMenuWrapper.AddAction(ID_WIREFRAME); viewportViewsMenuWrapper.AddSeparator(); +#endif + if (CViewManager::IsMultiViewportEnabled()) { viewportViewsMenuWrapper.AddAction(ID_VIEW_CONFIGURELAYOUT); From 01f80c7b408f0659d5360ff1a435923f057f34e2 Mon Sep 17 00:00:00 2001 From: Ken Pruiksma Date: Fri, 11 Jun 2021 14:39:53 -0500 Subject: [PATCH 054/116] Changing the default level to use 1024 shadowmaps instead of 2048, pcf instead of esm+pcf, and bifubic filtering instead of boundary search. This should make the default level more perfomant and it actuallly looks a little better. (#1273) --- .../CommonFeatures/Assets/LevelAssets/default.slice | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Assets/LevelAssets/default.slice b/Gems/AtomLyIntegration/CommonFeatures/Assets/LevelAssets/default.slice index c20c6cde0b..b4c9eac10f 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Assets/LevelAssets/default.slice +++ b/Gems/AtomLyIntegration/CommonFeatures/Assets/LevelAssets/default.slice @@ -960,7 +960,7 @@ - + @@ -968,10 +968,11 @@ - + + @@ -1109,4 +1110,3 @@ - From 015f85db20ee0067084589d8e71cf6d598953eac Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Fri, 11 Jun 2021 15:15:45 -0500 Subject: [PATCH 055/116] [LYN-4160] Fixed intermittent crash by changing instantiate prefab dialog to use the AzToolsFramework::GetActiveWindow() helper which always gives a valid active window. --- .../UI/Prefab/PrefabIntegrationManager.cpp | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp index 77918565e4..54ad96535f 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -588,15 +589,6 @@ namespace AzToolsFramework bool PrefabIntegrationManager::QueryUserForPrefabFilePath(AZStd::string& outPrefabFilePath) { - QWidget* mainWindow = nullptr; - EditorRequests::Bus::BroadcastResult(mainWindow, &EditorRequests::Bus::Events::GetMainWindow); - - if (mainWindow == nullptr) - { - AZ_Assert(false, "Prefab - Could not detect Editor main window to generate the asset picker."); - return false; - } - AssetSelectionModel selection; // Note, stringfilter will match every source file CONTAINING ".prefab". @@ -624,7 +616,7 @@ namespace AzToolsFramework selection.SetDisplayFilter(compositeFilterPtr); selection.SetSelectionFilter(compositeFilterPtr); - AssetBrowserComponentRequestBus::Broadcast(&AssetBrowserComponentRequests::PickAssets, selection, mainWindow); + AssetBrowserComponentRequestBus::Broadcast(&AssetBrowserComponentRequests::PickAssets, selection, AzToolsFramework::GetActiveWindow()); if (!selection.IsValid()) { @@ -983,12 +975,7 @@ namespace AzToolsFramework includedEntities.c_str(), referencedEntities.c_str()); - QWidget* mainWindow = nullptr; - AzToolsFramework::EditorRequests::Bus::BroadcastResult( - mainWindow, - &AzToolsFramework::EditorRequests::Bus::Events::GetMainWindow); - - QMessageBox msgBox(mainWindow); + QMessageBox msgBox(AzToolsFramework::GetActiveWindow()); msgBox.setWindowTitle("External Entity References"); msgBox.setText("The prefab contains references to external entities that are not selected."); msgBox.setInformativeText("You can move the referenced entities into this prefab or retain the external references."); From 3895c93e04a3fe33c458c0a5eb7ccb6768d956ce Mon Sep 17 00:00:00 2001 From: greerdv Date: Fri, 11 Jun 2021 22:05:37 +0100 Subject: [PATCH 056/116] avoid some divisions by zero in simd math types --- .../AzCore/Math/Internal/SimdMathCommon_simd.inl | 13 +++++++++++-- .../AzCore/Math/Internal/SimdMathVec2_sse.inl | 2 ++ .../AzCore/Math/Internal/SimdMathVec3_sse.inl | 2 ++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Math/Internal/SimdMathCommon_simd.inl b/Code/Framework/AzCore/AzCore/Math/Internal/SimdMathCommon_simd.inl index 770a8fa104..d06372256d 100644 --- a/Code/Framework/AzCore/AzCore/Math/Internal/SimdMathCommon_simd.inl +++ b/Code/Framework/AzCore/AzCore/Math/Internal/SimdMathCommon_simd.inl @@ -292,8 +292,13 @@ namespace AZ const typename VecType::FloatType cmp2 = VecType::AndNot(cmp0, cmp1); // -1/x + // this step is calculated for all values of x, but only used if x > Sqrt(2) + 1 + // in order to avoid a division by zero, detect if xabs is zero here and replace it with an arbitrary value + // if xabs does equal zero, the value here doesn't matter because the result will be thrown away + typename VecType::FloatType xabsSafe = + VecType::Add(xabs, VecType::And(VecType::CmpEq(xabs, VecType::ZeroFloat()), FastLoadConstant(Simd::g_vec1111))); const typename VecType::FloatType y0 = VecType::And(cmp0, FastLoadConstant(Simd::g_HalfPi)); - typename VecType::FloatType x0 = VecType::Div(FastLoadConstant(Simd::g_vec1111), xabs); + typename VecType::FloatType x0 = VecType::Div(FastLoadConstant(Simd::g_vec1111), xabsSafe); x0 = VecType::Xor(x0, VecType::CastToFloat(FastLoadConstant(Simd::g_negateMask))); const typename VecType::FloatType y1 = VecType::And(cmp2, FastLoadConstant(Simd::g_QuarterPi)); @@ -368,8 +373,12 @@ namespace AZ typename VecType::FloatType offset = VecType::And(x_lt_0, offset1); + // the result of this part of the computation is thrown away if x equals 0, + // but if x does equal 0, it will cause a division by zero + // so replace zero by an arbitrary value here in that case + typename VecType::FloatType xSafe = VecType::Add(x, VecType::And(x_eq_0, FastLoadConstant(Simd::g_vec1111))); const typename VecType::FloatType atan_mask = VecType::Not(VecType::Or(x_eq_0, y_eq_0)); - const typename VecType::FloatType atan_arg = VecType::Div(y, x); + const typename VecType::FloatType atan_arg = VecType::Div(y, xSafe); typename VecType::FloatType atan_result = VecType::Atan(atan_arg); atan_result = VecType::Add(atan_result, offset); atan_result = VecType::AndNot(pio2_mask, atan_result); diff --git a/Code/Framework/AzCore/AzCore/Math/Internal/SimdMathVec2_sse.inl b/Code/Framework/AzCore/AzCore/Math/Internal/SimdMathVec2_sse.inl index 8f35af258c..63e2dca8fd 100644 --- a/Code/Framework/AzCore/AzCore/Math/Internal/SimdMathVec2_sse.inl +++ b/Code/Framework/AzCore/AzCore/Math/Internal/SimdMathVec2_sse.inl @@ -471,6 +471,7 @@ namespace AZ AZ_MATH_INLINE Vec2::FloatType Vec2::Reciprocal(FloatArgType value) { + value = Sse::ReplaceFourth(Sse::ReplaceThird(value, 1.0f), 1.0f); return Sse::Reciprocal(value); } @@ -513,6 +514,7 @@ namespace AZ AZ_MATH_INLINE Vec2::FloatType Vec2::SqrtInv(FloatArgType value) { + value = Sse::ReplaceFourth(Sse::ReplaceThird(value, 1.0f), 1.0f); return Sse::SqrtInv(value); } diff --git a/Code/Framework/AzCore/AzCore/Math/Internal/SimdMathVec3_sse.inl b/Code/Framework/AzCore/AzCore/Math/Internal/SimdMathVec3_sse.inl index 78a0d5db66..75ee2ab7c5 100644 --- a/Code/Framework/AzCore/AzCore/Math/Internal/SimdMathVec3_sse.inl +++ b/Code/Framework/AzCore/AzCore/Math/Internal/SimdMathVec3_sse.inl @@ -507,6 +507,7 @@ namespace AZ AZ_MATH_INLINE Vec3::FloatType Vec3::Reciprocal(FloatArgType value) { + value = Sse::ReplaceFourth(value, 1.0f); return Sse::Reciprocal(value); } @@ -549,6 +550,7 @@ namespace AZ AZ_MATH_INLINE Vec3::FloatType Vec3::SqrtInv(FloatArgType value) { + value = Sse::ReplaceFourth(value, 1.0f); return Sse::SqrtInv(value); } From e6b8dc2ce1cb8571e9197cfec15b73ac795e7166 Mon Sep 17 00:00:00 2001 From: amzn-sj Date: Fri, 11 Jun 2021 14:37:12 -0700 Subject: [PATCH 057/116] Disable AzTest and AzTestRunner in monolithic builds --- Code/Framework/AzTest/CMakeLists.txt | 42 ++++++++++++++------------ Code/Tools/AzTestRunner/CMakeLists.txt | 2 +- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/Code/Framework/AzTest/CMakeLists.txt b/Code/Framework/AzTest/CMakeLists.txt index fe5ec2d0ff..d7b8813639 100644 --- a/Code/Framework/AzTest/CMakeLists.txt +++ b/Code/Framework/AzTest/CMakeLists.txt @@ -8,25 +8,27 @@ # 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. # - -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/AzTest/Platform/${PAL_PLATFORM_NAME}) -ly_add_target( - NAME AzTest STATIC - NAMESPACE AZ - FILES_CMAKE - AzTest/aztest_files.cmake - ${pal_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake - INCLUDE_DIRECTORIES - PUBLIC - . - ${pal_dir} - BUILD_DEPENDENCIES - PUBLIC - 3rdParty::googletest::GMock - 3rdParty::googletest::GTest - 3rdParty::GoogleBenchmark - AZ::AzCore - PLATFORM_INCLUDE_FILES +if(NOT LY_MONOLITHIC_GAME) + ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/AzTest/Platform/${PAL_PLATFORM_NAME}) + + ly_add_target( + NAME AzTest STATIC + NAMESPACE AZ + FILES_CMAKE + AzTest/aztest_files.cmake + ${pal_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake + INCLUDE_DIRECTORIES + PUBLIC + . + ${pal_dir} + BUILD_DEPENDENCIES + PUBLIC + 3rdParty::googletest::GMock + 3rdParty::googletest::GTest + 3rdParty::GoogleBenchmark + AZ::AzCore + PLATFORM_INCLUDE_FILES ${pal_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}.cmake -) + ) +endif() diff --git a/Code/Tools/AzTestRunner/CMakeLists.txt b/Code/Tools/AzTestRunner/CMakeLists.txt index e6dd09e15b..fcff173b01 100644 --- a/Code/Tools/AzTestRunner/CMakeLists.txt +++ b/Code/Tools/AzTestRunner/CMakeLists.txt @@ -13,7 +13,7 @@ ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${P include(${pal_dir}/platform_traits_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) -if(PAL_TRAIT_AZTESTRUNNER_SUPPORTED) +if(PAL_TRAIT_AZTESTRUNNER_SUPPORTED AND NOT LY_MONOLITHIC_GAME) ly_add_target( NAME AzTestRunner ${PAL_TRAIT_AZTESTRUNNER_LAUNCHER_TYPE} From 21f209311cd50ec2e4cb989bac4333d390cd1b3c Mon Sep 17 00:00:00 2001 From: amzn-sj Date: Fri, 11 Jun 2021 14:54:24 -0700 Subject: [PATCH 058/116] Parameter may be unused --- Code/LauncherUnified/StaticModules.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/LauncherUnified/StaticModules.in b/Code/LauncherUnified/StaticModules.in index 03b22b076a..5f2c9d7526 100644 --- a/Code/LauncherUnified/StaticModules.in +++ b/Code/LauncherUnified/StaticModules.in @@ -27,7 +27,7 @@ namespace AZ ${extern_module_declarations} -extern "C" void CreateStaticModules(AZStd::vector& modulesOut) +extern "C" void CreateStaticModules([[maybe_unused]] AZStd::vector& modulesOut) { ${module_invocations} } From ac5196dbf531c66c076f7ffda243a235013d3fda Mon Sep 17 00:00:00 2001 From: amzn-sj Date: Fri, 11 Jun 2021 15:19:28 -0700 Subject: [PATCH 059/116] Revert previous change --- Code/LauncherUnified/StaticModules.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/LauncherUnified/StaticModules.in b/Code/LauncherUnified/StaticModules.in index 5f2c9d7526..03b22b076a 100644 --- a/Code/LauncherUnified/StaticModules.in +++ b/Code/LauncherUnified/StaticModules.in @@ -27,7 +27,7 @@ namespace AZ ${extern_module_declarations} -extern "C" void CreateStaticModules([[maybe_unused]] AZStd::vector& modulesOut) +extern "C" void CreateStaticModules(AZStd::vector& modulesOut) { ${module_invocations} } From f6a6614e4b68d3a5dfcdd979e61a619a95d60931 Mon Sep 17 00:00:00 2001 From: amzn-sj Date: Fri, 11 Jun 2021 15:29:46 -0700 Subject: [PATCH 060/116] StaticModules.in must be generated after the gems are enabled --- CMakeLists.txt | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0585089325..4a12e0c50a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,24 +105,25 @@ endforeach() # Post-processing ################################################################################ # The following steps have to be done after all targets are registered: -# Defer generation of the StaticModules.inl file which is needed to create the AZ::Module derived class in monolithic -# builds until after all the targets are known -ly_delayed_generate_static_modules_inl() # 1. Add any dependencies registered via ly_enable_gems ly_enable_gems_delayed() -# 2. generate a settings registry .setreg file for all ly_add_project_dependencies() and ly_add_target_dependencies() calls +# 2. Defer generation of the StaticModules.inl file which is needed to create the AZ::Module derived class in monolithic +# builds until after all the targets are known and all the gems are enabled +ly_delayed_generate_static_modules_inl() + +# 3. generate a settings registry .setreg file for all ly_add_project_dependencies() and ly_add_target_dependencies() calls # to provide applications with the filenames of gem modules to load # This must be done before ly_delayed_target_link_libraries() as that inserts BUILD_DEPENDENCIES as MANUALLY_ADDED_DEPENDENCIES # if the build dependency is a MODULE_LIBRARY. That would cause a false load dependency to be generated ly_delayed_generate_settings_registry() -# 3. link targets where the dependency was yet not declared, we need to have the declaration so we do different +# 4. link targets where the dependency was yet not declared, we need to have the declaration so we do different # linking logic depending on the type of target ly_delayed_target_link_libraries() -# 4. generate a registry file for unit testing for platforms that support unit testing +# 5. generate a registry file for unit testing for platforms that support unit testing if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) ly_delayed_generate_unit_test_module_registry() endif() From f9fe2392f422655fa8803bb30296cf90f63ee331 Mon Sep 17 00:00:00 2001 From: Junbo Liang <68558268+junbo75@users.noreply.github.com> Date: Fri, 11 Jun 2021 15:34:31 -0700 Subject: [PATCH 061/116] [SPEC-7257] [LYN-4472] [AWSMetrics] The background thread that monitors the metrics queue burns a lot of CPU (#1256) [LYN-4472] [AWSMetrics] The background thread that monitors the metrics queue burns a lot of CPU --- .../Code/Include/Private/MetricsManager.h | 19 ++---- .../AWSMetrics/Code/Source/MetricsManager.cpp | 65 ++++++++----------- .../Code/Tests/MetricsManagerTest.cpp | 5 +- 3 files changed, 38 insertions(+), 51 deletions(-) diff --git a/Gems/AWSMetrics/Code/Include/Private/MetricsManager.h b/Gems/AWSMetrics/Code/Include/Private/MetricsManager.h index 28c8c3d762..b8b6a8ccce 100644 --- a/Gems/AWSMetrics/Code/Include/Private/MetricsManager.h +++ b/Gems/AWSMetrics/Code/Include/Private/MetricsManager.h @@ -122,29 +122,22 @@ namespace AWSMetrics //! @return Outcome of the operation. AZ::Outcome SendMetricsToFile(AZStd::shared_ptr metricsQueue); - //! Check whether the consumer should flush the metrics queue. - //! @return whether the limit is hit. - bool ShouldSendMetrics(); - //! Push metrics events to the front of the queue for retry. //! @param metricsEventsForRetry Metrics events for retry. void PushMetricsForRetry(MetricsQueue& metricsEventsForRetry); void SubmitLocalMetricsAsync(); - //////////////////////////////////////////// - // These data are protected by m_metricsMutex. - AZStd::mutex m_metricsMutex; - AZStd::chrono::system_clock::time_point m_lastSendMetricsTime; - MetricsQueue m_metricsQueue; - //////////////////////////////////////////// + AZStd::mutex m_metricsMutex; //!< Mutex to protect the metrics queue + MetricsQueue m_metricsQueue; //!< Queue fo buffering the metrics events - AZStd::mutex m_metricsFileMutex; //!< Local metrics file is protected by m_metricsFileMutex + AZStd::mutex m_metricsFileMutex; //!< Mutex to protect the local metrics file AZStd::atomic m_sendMetricsId;//!< Request ID for sending metrics - AZStd::thread m_consumerThread; //!< Thread to monitor and consume the metrics queue - AZStd::atomic m_consumerTerminated; + AZStd::thread m_monitorThread; //!< Thread to monitor and consume the metrics queue + AZStd::atomic m_monitorTerminated; + AZStd::binary_semaphore m_waitEvent; // Client Configurations. AZStd::unique_ptr m_clientConfiguration; diff --git a/Gems/AWSMetrics/Code/Source/MetricsManager.cpp b/Gems/AWSMetrics/Code/Source/MetricsManager.cpp index 2f4f1fb5e5..d48ec1a041 100644 --- a/Gems/AWSMetrics/Code/Source/MetricsManager.cpp +++ b/Gems/AWSMetrics/Code/Source/MetricsManager.cpp @@ -29,7 +29,7 @@ namespace AWSMetrics MetricsManager::MetricsManager() : m_clientConfiguration(AZStd::make_unique()) , m_clientIdProvider(IdentityProvider::CreateIdentityProvider()) - , m_consumerTerminated(true) + , m_monitorTerminated(true) , m_sendMetricsId(0) { } @@ -53,31 +53,27 @@ namespace AWSMetrics void MetricsManager::StartMetrics() { - if (!m_consumerTerminated) + if (!m_monitorTerminated) { // The background thread has been started. return; } - - m_consumerTerminated = false; - - AZStd::lock_guard lock(m_metricsMutex); - m_lastSendMetricsTime = AZStd::chrono::system_clock::now(); + m_monitorTerminated = false; // Start a separate thread to monitor and consume the metrics queue. // Avoid using the job system since the worker is long-running over multiple frames - m_consumerThread = AZStd::thread(AZStd::bind(&MetricsManager::MonitorMetricsQueue, this)); + m_monitorThread = AZStd::thread(AZStd::bind(&MetricsManager::MonitorMetricsQueue, this)); } void MetricsManager::MonitorMetricsQueue() { - while (!m_consumerTerminated) + // Continue to loop until the monitor is terminated. + while (!m_monitorTerminated) { - if (ShouldSendMetrics()) - { - // Flush the metrics queue when the accumulated metrics size or time period hits the limit - FlushMetricsAsync(); - } + // The thread will wake up either when the metrics event queue is full (try_acquire_for call returns true), + // or the flush period limit is hit (try_acquire_for call returns false). + m_waitEvent.try_acquire_for(AZStd::chrono::seconds(m_clientConfiguration->GetQueueFlushPeriodInSeconds())); + FlushMetricsAsync(); } } @@ -114,6 +110,12 @@ namespace AWSMetrics AZStd::lock_guard lock(m_metricsMutex); m_metricsQueue.AddMetrics(metricsEvent); + if (m_metricsQueue.GetSizeInBytes() >= m_clientConfiguration->GetMaxQueueSizeInBytes()) + { + // Flush the metrics queue when the accumulated metrics size hits the limit + m_waitEvent.release(); + } + return true; } @@ -348,9 +350,6 @@ namespace AWSMetrics void MetricsManager::FlushMetricsAsync() { AZStd::lock_guard lock(m_metricsMutex); - - m_lastSendMetricsTime = AZStd::chrono::system_clock::now(); - if (m_metricsQueue.GetNumMetrics() == 0) { return; @@ -363,34 +362,20 @@ namespace AWSMetrics SendMetricsAsync(metricsToFlush); } - bool MetricsManager::ShouldSendMetrics() - { - AZStd::lock_guard lock(m_metricsMutex); - - auto secondsSinceLastFlush = AZStd::chrono::duration_cast(AZStd::chrono::system_clock::now() - m_lastSendMetricsTime); - if (secondsSinceLastFlush >= AZStd::chrono::seconds(m_clientConfiguration->GetQueueFlushPeriodInSeconds()) || - m_metricsQueue.GetSizeInBytes() >= m_clientConfiguration->GetMaxQueueSizeInBytes()) - { - return true; - } - - return false; - } - void MetricsManager::ShutdownMetrics() { - if (m_consumerTerminated) + if (m_monitorTerminated) { return; } - // Terminate the consumer thread - m_consumerTerminated = true; - FlushMetricsAsync(); + // Terminate the monitor thread + m_monitorTerminated = true; + m_waitEvent.release(); - if (m_consumerThread.joinable()) + if (m_monitorThread.joinable()) { - m_consumerThread.join(); + m_monitorThread.join(); } } @@ -449,6 +434,12 @@ namespace AWSMetrics { AZStd::lock_guard lock(m_metricsMutex); m_metricsQueue.AddMetrics(offlineRecords[index]); + + if (m_metricsQueue.GetSizeInBytes() >= m_clientConfiguration->GetMaxQueueSizeInBytes()) + { + // Flush the metrics queue when the accumulated metrics size hits the limit + m_waitEvent.release(); + } } // Remove the local metrics file after reading all its content. diff --git a/Gems/AWSMetrics/Code/Tests/MetricsManagerTest.cpp b/Gems/AWSMetrics/Code/Tests/MetricsManagerTest.cpp index 82385b8bdd..bd7ecb722e 100644 --- a/Gems/AWSMetrics/Code/Tests/MetricsManagerTest.cpp +++ b/Gems/AWSMetrics/Code/Tests/MetricsManagerTest.cpp @@ -355,6 +355,9 @@ namespace AWSMetrics TEST_F(MetricsManagerTest, FlushMetrics_NonEmptyQueue_Success) { + ResetClientConfig(true, (double)TestMetricsEventSizeInBytes * (MaxNumMetricsEvents + 1) / MbToBytes, + DefaultFlushPeriodInSeconds, 1); + for (int index = 0; index < MaxNumMetricsEvents; ++index) { AZStd::vector metricsAttributes; @@ -377,7 +380,7 @@ namespace AWSMetrics TEST_F(MetricsManagerTest, ResetOfflineRecordingStatus_ResubmitLocalMetrics_Success) { // Disable offline recording in the config file. - ResetClientConfig(false, 0.0, 0, 0); + ResetClientConfig(false, (double)TestMetricsEventSizeInBytes * 2 / MbToBytes, 0, 0); // Enable offline recording after initialize the metric manager. m_metricsManager->UpdateOfflineRecordingStatus(true); From 469b1a0858ac8bf4827d93f2473cc41067a2282c Mon Sep 17 00:00:00 2001 From: amzn-sj Date: Fri, 11 Jun 2021 16:30:46 -0700 Subject: [PATCH 062/116] Fix monolithic link error involving gem variants which are "aliased" as interface libraries with multiple gem target dependencies --- Code/LauncherUnified/launcher_generator.cmake | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Code/LauncherUnified/launcher_generator.cmake b/Code/LauncherUnified/launcher_generator.cmake index 36cd3c5899..15bbc0fe89 100644 --- a/Code/LauncherUnified/launcher_generator.cmake +++ b/Code/LauncherUnified/launcher_generator.cmake @@ -196,6 +196,16 @@ function(ly_delayed_generate_static_modules_inl) ly_get_gem_load_dependencies(all_game_gem_dependencies ${project_name}.GameLauncher) foreach(game_gem_dependency ${all_game_gem_dependencies}) + # Sometimes, a gem's Client variant may be an interface library + # which dependes on multiple gem targets. The interface libraries + # should be skipped; the real dependencies of the interface will be processed + if(TARGET ${game_gem_dependency}) + get_target_property(target_type ${game_gem_dependency} TYPE) + if(${target_type} STREQUAL "INTERFACE_LIBRARY") + continue() + endif() + endif() + # To match the convention on how gems targets vs gem modules are named, # we remove the ".Static" from the suffix # Replace "." with "_" From a86062bd91eb3184726319cec221304a8976b32a Mon Sep 17 00:00:00 2001 From: amzn-sj Date: Fri, 11 Jun 2021 16:42:09 -0700 Subject: [PATCH 063/116] Skip interface libraries when genrating StaticModules for game server as well --- Code/LauncherUnified/launcher_generator.cmake | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Code/LauncherUnified/launcher_generator.cmake b/Code/LauncherUnified/launcher_generator.cmake index 15bbc0fe89..5fa0f7a0e3 100644 --- a/Code/LauncherUnified/launcher_generator.cmake +++ b/Code/LauncherUnified/launcher_generator.cmake @@ -234,6 +234,14 @@ function(ly_delayed_generate_static_modules_inl) list(APPEND all_server_gem_dependencies ${server_gem_load_dependencies} ${server_gem_dependency}) endforeach() foreach(server_gem_dependency ${all_server_gem_dependencies}) + # Skip interface libraries + if(TARGET ${server_gem_dependency}) + get_target_property(target_type ${server_gem_dependency} TYPE) + if(${target_type} STREQUAL "INTERFACE_LIBRARY") + continue() + endif() + endif() + # Replace "." with "_" string(REPLACE "." "_" server_gem_dependency ${server_gem_dependency}) From f32590d241c12b01c1ff0ed0c2f2c248b0ca60b1 Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Fri, 11 Jun 2021 16:43:53 -0700 Subject: [PATCH 064/116] LYN-4042 | No UI Indication that Level is Modified (#1277) * Restore the code that display the dirty marker on the Level container. Ensure the dirty marker is cleared on level save. * Moving call one level up to allow usage of the SaveTemplateToString function without clearing the dirty flag. --- .../PrefabEditorEntityOwnershipService.cpp | 17 ++++++++++++----- .../UI/Prefab/LevelRootUiHandler.cpp | 13 +++++++++++-- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp index fa7d5f6e9b..6e96511507 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp @@ -252,13 +252,20 @@ namespace AzToolsFramework } AZStd::string out; - if (m_loaderInterface->SaveTemplateToString(m_rootInstance->GetTemplateId(), out)) + + if (!m_loaderInterface->SaveTemplateToString(m_rootInstance->GetTemplateId(), out)) { - const size_t bytesToWrite = out.size(); - const size_t bytesWritten = stream.Write(bytesToWrite, out.data()); - return bytesWritten == bytesToWrite; + return false; } - return false; + + const size_t bytesToWrite = out.size(); + const size_t bytesWritten = stream.Write(bytesToWrite, out.data()); + if(bytesWritten != bytesToWrite) + { + return false; + } + m_prefabSystemComponent->SetTemplateDirtyFlag(templateId, false); + return true; } void PrefabEditorEntityOwnershipService::CreateNewLevelPrefab(AZStd::string_view filename, const AZStd::string& templateFilename) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.cpp index 7915403c0a..d6b7aebddc 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.cpp @@ -58,8 +58,17 @@ namespace AzToolsFramework if (!path.empty()) { - infoString = - QObject::tr("(%1)").arg(path.Filename().Native().data()); + QString saveFlag = ""; + auto dirtyOutcome = m_prefabPublicInterface->HasUnsavedChanges(path); + + if (dirtyOutcome.IsSuccess() && dirtyOutcome.GetValue() == true) + { + saveFlag = "*"; + } + + infoString = QObject::tr("(%1%2)") + .arg(path.Filename().Native().data()) + .arg(saveFlag); } return infoString; From 8089b6469b2d62fa8954a02f348ed9ac4a8a9192 Mon Sep 17 00:00:00 2001 From: Peng Date: Fri, 11 Jun 2021 17:14:31 -0700 Subject: [PATCH 065/116] ATOM-15774 [RHI][Vulkan] Fix issue with null image that is released prior to creating image view. JIRA: https://jira.agscollab.com/browse/ATOM-15774 --- Gems/Atom/RHI/Vulkan/Code/Source/RHI/ImageView.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/ImageView.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/ImageView.cpp index 605f61fc33..ec58b5c940 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/ImageView.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/ImageView.cpp @@ -55,7 +55,11 @@ namespace AZ const auto& image = static_cast(resourceBase); const RHI::ImageViewDescriptor& descriptor = GetDescriptor(); - AZ_Assert(image.GetNativeImage() != VK_NULL_HANDLE, "Image has not been initialized."); + // this can happen when image has been invalidated/released right before re-compiling the image + if (image.GetNativeImage() == VK_NULL_HANDLE) + { + return RHI::ResultCode::Fail; + } RHI::Format viewFormat = descriptor.m_overrideFormat; // If an image is not owner of native image, it is a swapchain image. From e4921c8d0aa0fe5ea3916e2e486dfdabc52255a7 Mon Sep 17 00:00:00 2001 From: sconel Date: Fri, 11 Jun 2021 17:45:46 -0700 Subject: [PATCH 066/116] Fix nested container entities not getting editor info removed during prefab processing --- .../PrefabEditorEntityOwnershipService.cpp | 17 ++- .../Prefab/Instance/Instance.cpp | 130 +++++++++++------- .../Prefab/Instance/Instance.h | 17 ++- .../Prefab/Spawnable/EditorInfoRemover.cpp | 33 ++--- .../Prefab/Spawnable/EditorInfoRemover.h | 4 +- .../Prefab/PrefabUpdateWithPatchesTests.cpp | 2 +- 6 files changed, 116 insertions(+), 87 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp index fa7d5f6e9b..71781d29d5 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp @@ -159,12 +159,23 @@ namespace AzToolsFramework void PrefabEditorEntityOwnershipService::GetNonPrefabEntities(EntityList& entities) { - m_rootInstance->GetEntities(entities, false); + m_rootInstance->GetEntities( + [&entities](const AZStd::unique_ptr& entity) + { + entities.emplace_back(entity.get()); + return true; + }); } bool PrefabEditorEntityOwnershipService::GetAllEntities(EntityList& entities) { - m_rootInstance->GetEntities(entities, true); + m_rootInstance->GetAllEntitiesInHierarchy( + [&entities](const AZStd::unique_ptr& entity) + { + entities.emplace_back(entity.get()); + return true; + }); + return true; } @@ -544,7 +555,7 @@ namespace AzToolsFramework return; } - m_rootInstance->GetNestedEntities([this](AZStd::unique_ptr& entity) + m_rootInstance->GetAllEntitiesInHierarchy([this](AZStd::unique_ptr& entity) { AZ_Assert(entity, "Invalid entity found in root instance while starting play in editor."); if (entity->GetState() == AZ::Entity::State::Active) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.cpp index 83a76aeb01..e5179f4229 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.cpp @@ -373,17 +373,25 @@ namespace AzToolsFramework } } - void Instance::GetConstNestedEntities(const AZStd::function& callback) + bool Instance::GetEntities_Impl(const AZStd::function&)>& callback) { - GetConstEntities(callback); - - for (const auto& [instanceAlias, instance] : m_nestedInstances) + for (auto& [entityAlias, entity] : m_entities) { - instance->GetConstNestedEntities(callback); + if (!entity) + { + continue; + } + + if (!callback(entity)) + { + return false; + } } + + return true; } - void Instance::GetConstEntities(const AZStd::function& callback) + bool Instance::GetConstEntities_Impl(const AZStd::function& callback) const { for (const auto& [entityAlias, entity] : m_entities) { @@ -394,19 +402,83 @@ namespace AzToolsFramework if (!callback(*entity)) { - break; + return false; } } + + return true; } - void Instance::GetNestedEntities(const AZStd::function&)>& callback) + bool Instance::GetAllEntitiesInHierarchy_Impl(const AZStd::function&)>& callback) { - GetEntities(callback); + if (HasContainerEntity()) + { + if (!callback(m_containerEntity)) + { + return false; + } + } + + if (!GetEntities_Impl(callback)) + { + return false; + } for (auto& [instanceAlias, instance] : m_nestedInstances) { - instance->GetNestedEntities(callback); + if (!instance->GetAllEntitiesInHierarchy_Impl(callback)) + { + return false; + } } + + return true; + } + + bool Instance::GetAllEntitiesInHierarchyConst_Impl(const AZStd::function& callback) const + { + if (HasContainerEntity()) + { + if (!callback(*m_containerEntity)) + { + return false; + } + } + + if (!GetConstEntities_Impl(callback)) + { + return false; + } + + for (const auto& [instanceAlias, instance] : m_nestedInstances) + { + if (!instance->GetAllEntitiesInHierarchyConst_Impl(callback)) + { + return false; + } + } + + return true; + } + + void Instance::GetEntities(const AZStd::function&)>& callback) + { + GetEntities_Impl(callback); + } + + void Instance::GetConstEntities(const AZStd::function& callback) const + { + GetConstEntities_Impl(callback); + } + + void Instance::GetAllEntitiesInHierarchy(const AZStd::function&)>& callback) + { + GetAllEntitiesInHierarchy_Impl(callback); + } + + void Instance::GetAllEntitiesInHierarchyConst(const AZStd::function& callback) const + { + GetAllEntitiesInHierarchyConst_Impl(callback); } void Instance::GetNestedInstances(const AZStd::function&)>& callback) @@ -417,44 +489,6 @@ namespace AzToolsFramework } } - void Instance::GetEntities(const AZStd::function&)>& callback) - { - for (auto& [entityAlias, entity] : m_entities) - { - if (!callback(entity)) - { - break; - } - } - } - - void Instance::GetEntities(EntityList& entities, bool includeNestedEntities) - { - // Non-recursive traversal of instances - AZStd::vector instancesToTraverse = { this }; - while (!instancesToTraverse.empty()) - { - Instance* currentInstance = instancesToTraverse.back(); - instancesToTraverse.pop_back(); - if (includeNestedEntities) - { - instancesToTraverse.reserve(instancesToTraverse.size() + currentInstance->m_nestedInstances.size()); - for (const auto& instanceByAlias : currentInstance->m_nestedInstances) - { - instancesToTraverse.push_back(instanceByAlias.second.get()); - } - } - - // Size increases by 1 for each instance because we have to count the container entity also. - entities.reserve(entities.size() + currentInstance->m_entities.size() + 1); - entities.push_back(m_containerEntity.get()); - for (const auto& entityByAlias : currentInstance->m_entities) - { - entities.push_back(entityByAlias.second.get()); - } - } - } - EntityAliasOptionalReference Instance::GetEntityAlias(const AZ::EntityId& id) { if (m_instanceToTemplateEntityIdMap.count(id)) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.h index 5f36ac10dc..9d3ae31796 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.h @@ -121,10 +121,10 @@ namespace AzToolsFramework /** * Gets the entities in the Instance DOM. Can recursively trace all nested instances. */ - void GetConstNestedEntities(const AZStd::function& callback); - void GetConstEntities(const AZStd::function& callback); - void GetNestedEntities(const AZStd::function&)>& callback); void GetEntities(const AZStd::function&)>& callback); + void GetConstEntities(const AZStd::function& callback) const; + void GetAllEntitiesInHierarchy(const AZStd::function&)>& callback); + void GetAllEntitiesInHierarchyConst(const AZStd::function& callback) const; void GetNestedInstances(const AZStd::function&)>& callback); /** @@ -184,12 +184,6 @@ namespace AzToolsFramework static InstanceAlias GenerateInstanceAlias(); - protected: - /** - * Gets the entities owned by this instance - */ - void GetEntities(EntityList& entities, bool includeNestedEntities = false); - private: static constexpr const char s_aliasPathSeparator = '/'; @@ -197,6 +191,11 @@ namespace AzToolsFramework void RemoveEntities(const AZStd::function&)>& filter); + bool GetEntities_Impl(const AZStd::function&)>& callback); + bool GetConstEntities_Impl(const AZStd::function& callback) const; + bool GetAllEntitiesInHierarchy_Impl(const AZStd::function&)>& callback); + bool GetAllEntitiesInHierarchyConst_Impl(const AZStd::function& callback) const; + bool RegisterEntity(const AZ::EntityId& entityId, const EntityAlias& entityAlias); AZStd::unique_ptr DetachEntity(const EntityAlias& entityAlias); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.cpp index 6480ac37d7..cc04fe24c1 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.cpp @@ -62,25 +62,16 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils } } - AZStd::vector EditorInfoRemover::GetEntitiesFromInstance(AZStd::unique_ptr& instance) + void EditorInfoRemover::GetEntitiesFromInstance( + AZStd::unique_ptr& instance, EntityList& hierarchyEntities) { - AZStd::vector result; - - instance->GetNestedEntities( - [&result](const AZStd::unique_ptr& entity) + instance->GetAllEntitiesInHierarchy( + [&hierarchyEntities](const AZStd::unique_ptr& entity) { - result.emplace_back(entity.get()); + hierarchyEntities.emplace_back(entity.get()); return true; } ); - - if (instance->HasContainerEntity()) - { - auto containerEntityReference = instance->GetContainerEntity(); - result.emplace_back(&containerEntityReference->get()); - } - - return result; } void EditorInfoRemover::SetEditorOnlyEntityHandlerFromCandidates(const EntityList& entities) @@ -543,7 +534,9 @@ exportComponent, prefabProcessorContext); } // grab all nested entities from the Instance as source entities. - EntityList sourceEntities = GetEntitiesFromInstance(instance); + EntityList sourceEntities; + GetEntitiesFromInstance(instance, sourceEntities); + EntityList exportEntities; // prepare for validation of component requirements. @@ -616,7 +609,7 @@ exportComponent, prefabProcessorContext); ); // replace entities of instance with exported ones. - instance->GetNestedEntities( + instance->GetAllEntitiesInHierarchy( [&exportEntitiesMap](AZStd::unique_ptr& entity) { auto entityId = entity->GetId(); @@ -625,14 +618,6 @@ exportComponent, prefabProcessorContext); } ); - if (instance->HasContainerEntity()) - { - if (auto found = exportEntitiesMap.find(instance->GetContainerEntityId()); found != exportEntitiesMap.end()) - { - instance->SetContainerEntity(*found->second); - } - } - // save the final result in the target Prefab DOM. PrefabDom filteredPrefab; if (!PrefabDomUtils::StoreInstanceInPrefabDom(*instance, filteredPrefab)) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.h index 1e00485e42..5de5c516f8 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.h @@ -55,8 +55,8 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils protected: using EntityList = AZStd::vector; - static EntityList GetEntitiesFromInstance( - AZStd::unique_ptr& instance); + static void GetEntitiesFromInstance( + AZStd::unique_ptr& instance, EntityList& hierarchyEntities); static bool ReadComponentAttribute( AZ::Component* component, diff --git a/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabUpdateWithPatchesTests.cpp b/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabUpdateWithPatchesTests.cpp index aef3cad5f3..e3460c307f 100644 --- a/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabUpdateWithPatchesTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabUpdateWithPatchesTests.cpp @@ -93,7 +93,7 @@ namespace UnitTest // Retrieve the entity pointer from the component application bus. AZ::Entity* wheelEntityUnderAxle = nullptr; - axleInstance->GetNestedEntities([&wheelEntityUnderAxle, wheelEntityIdUnderAxle](AZStd::unique_ptr& entity) + axleInstance->GetAllEntitiesInHierarchy([&wheelEntityUnderAxle, wheelEntityIdUnderAxle](AZStd::unique_ptr& entity) { if (entity->GetId() == wheelEntityIdUnderAxle) { From 633de3d28bfa8582eebe0d41aff086cfc8995207 Mon Sep 17 00:00:00 2001 From: scottr Date: Fri, 11 Jun 2021 17:58:14 -0700 Subject: [PATCH 067/116] [cpack/stabilization/2106] bootstrap installer theme support (required for changes requested by legal) --- .../Windows/Packaging/Bootstrapper.wxs | 4 + .../Packaging/BootstrapperTheme.wxl.in | 70 +++++++++++++++ .../Packaging/BootstrapperTheme.xml.in | 87 +++++++++++++++++++ .../Platform/Windows/PackagingPostBuild.cmake | 1 + .../Platform/Windows/Packaging_windows.cmake | 22 +++++ .../Windows/platform_windows_files.cmake | 2 + 6 files changed, 186 insertions(+) create mode 100644 cmake/Platform/Windows/Packaging/BootstrapperTheme.wxl.in create mode 100644 cmake/Platform/Windows/Packaging/BootstrapperTheme.xml.in diff --git a/cmake/Platform/Windows/Packaging/Bootstrapper.wxs b/cmake/Platform/Windows/Packaging/Bootstrapper.wxs index 55e8a8cd95..fd8aa68b77 100644 --- a/cmake/Platform/Windows/Packaging/Bootstrapper.wxs +++ b/cmake/Platform/Windows/Packaging/Bootstrapper.wxs @@ -22,6 +22,8 @@ @@ -29,6 +31,8 @@ diff --git a/cmake/Platform/Windows/Packaging/BootstrapperTheme.wxl.in b/cmake/Platform/Windows/Packaging/BootstrapperTheme.wxl.in new file mode 100644 index 0000000000..fe125cfdfe --- /dev/null +++ b/cmake/Platform/Windows/Packaging/BootstrapperTheme.wxl.in @@ -0,0 +1,70 @@ + + + + + [WixBundleName] Setup + [WixBundleName] + Version [WixBundleVersion] + Are you sure you want to cancel? + + + Welcome + +Setup will install [WixBundleName] on your computer. Click install to continue, options to set the install directory or Close to exit. + + [WixBundleName] <a href="#">license terms</a>. + I &agree to the license terms and conditions + &Options + &Install + &Close + + + Setup Options + Install location: + &Browse + &OK + &Cancel + + + Modify Setup + &Repair + &Uninstall + &Close + + + Setup Progress + Processing: + Initializing... + &Cancel + + + Setup Successful + Installation Successfully Completed + Repair Successfully Completed + Uninstall Successfully Completed + &Launch + &Close + + + Setup Failed + Setup Failed + Uninstall Failed + Repair Failed + +One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the <a href="#">log file</a>. + + &Close + + + Setup Help + +/install | /repair | /uninstall | /layout [directory] - installs, repairs, uninstalls or creates a complete local copy of the bundle in directory. Install is the default. + +/passive | /quiet - displays minimal UI with no prompts or displays no UI and no prompts. By default UI and all prompts are displayed. + +/log log.txt - logs to a specific file. By default a log file is created in %TEMP%. + + &Close + diff --git a/cmake/Platform/Windows/Packaging/BootstrapperTheme.xml.in b/cmake/Platform/Windows/Packaging/BootstrapperTheme.xml.in new file mode 100644 index 0000000000..61b338cc13 --- /dev/null +++ b/cmake/Platform/Windows/Packaging/BootstrapperTheme.xml.in @@ -0,0 +1,87 @@ + + + + #(loc.WindowTitle) + + Segoe UI + Segoe UI + Segoe UI + Segoe UI + + + + #(loc.Title) + + + + @WIX_THEME_INSTALL_LICENSE_ELEMENT@ + + #(loc.InstallAcceptCheckbox) + + + + + + + + #(loc.OptionsHeader) + + #(loc.OptionsLocationLabel) + + + + + + + + + + #(loc.ModifyHeader) + + + + + + + + + #(loc.ProgressHeader) + + #(loc.ProgressLabel) + #(loc.OverallProgressPackageText) + + + + + + + + #(loc.SuccessHeader) + #(loc.SuccessInstallHeader) + #(loc.SuccessRepairHeader) + #(loc.SuccessUninstallHeader) + + + + + + + + #(loc.FailureHeader) + #(loc.FailureInstallHeader) + #(loc.FailureUninstallHeader) + #(loc.FailureRepairHeader) + + #(loc.FailureHyperlinkLogText) + + + + + + + + #(loc.HelpHeader) + #(loc.HelpText) + + + diff --git a/cmake/Platform/Windows/PackagingPostBuild.cmake b/cmake/Platform/Windows/PackagingPostBuild.cmake index 89b3efb44b..1dcbedcba7 100644 --- a/cmake/Platform/Windows/PackagingPostBuild.cmake +++ b/cmake/Platform/Windows/PackagingPostBuild.cmake @@ -25,6 +25,7 @@ set(_ext_flags ) set(_addtional_defines + -dCPACK_BOOTSTRAP_THEME_FILE=${CPACK_BINARY_DIR}/BootstrapperTheme -dCPACK_BOOTSTRAP_UPGRADE_GUID=${CPACK_WIX_BOOTSTRAP_UPGRADE_GUID} -dCPACK_DOWNLOAD_SITE=${CPACK_DOWNLOAD_SITE} -dCPACK_LOCAL_INSTALLER_DIR=${_cpack_wix_out_dir} diff --git a/cmake/Platform/Windows/Packaging_windows.cmake b/cmake/Platform/Windows/Packaging_windows.cmake index 2fd281ad51..aec0edeee2 100644 --- a/cmake/Platform/Windows/Packaging_windows.cmake +++ b/cmake/Platform/Windows/Packaging_windows.cmake @@ -92,6 +92,28 @@ set(CPACK_WIX_EXTENSIONS set(_embed_artifacts "yes") if(LY_INSTALLER_DOWNLOAD_URL) + + if(LY_INSTALLER_LICENSE_URL) + set(WIX_THEME_INSTALL_LICENSE_ELEMENT + "#(loc.InstallLicenseLinkText)" + ) + else() + set(WIX_THEME_INSTALL_LICENSE_ELEMENT + "" + ) + endif() + + configure_file( + "${CPACK_SOURCE_DIR}/Platform/Windows/Packaging/BootstrapperTheme.xml.in" + "${CPACK_BINARY_DIR}/BootstrapperTheme.xml" + @ONLY + ) + configure_file( + "${CPACK_SOURCE_DIR}/Platform/Windows/Packaging/BootstrapperTheme.wxl.in" + "${CPACK_BINARY_DIR}/BootstrapperTheme.wxl" + @ONLY + ) + set(_embed_artifacts "no") # the bootstrapper will at the very least need a different upgrade guid diff --git a/cmake/Platform/Windows/platform_windows_files.cmake b/cmake/Platform/Windows/platform_windows_files.cmake index 3ce53fbcea..b3cdc8a4ff 100644 --- a/cmake/Platform/Windows/platform_windows_files.cmake +++ b/cmake/Platform/Windows/platform_windows_files.cmake @@ -26,6 +26,8 @@ set(FILES Packaging_windows.cmake PackagingPostBuild.cmake Packaging/Bootstrapper.wxs + Packaging/BootstrapperTheme.wxl.in + Packaging/BootstrapperTheme.xml.in Packaging/Shortcuts.wxs Packaging/Template.wxs.in ) From b2bcd6a326d6b5519198d875d38ce5fd92a18a67 Mon Sep 17 00:00:00 2001 From: jromnoa Date: Fri, 11 Jun 2021 18:12:24 -0700 Subject: [PATCH 068/116] adds TEST_SCREENSHOTS boolean toggle to build_config.json & adds subdirectory searching for upload_to_s3.py script --- .../build/Platform/Windows/build_config.json | 3 +- scripts/build/tools/upload_to_s3.py | 67 ++++++++++++++----- 2 files changed, 51 insertions(+), 19 deletions(-) diff --git a/scripts/build/Platform/Windows/build_config.json b/scripts/build/Platform/Windows/build_config.json index 71abf9021f..abf163a2e7 100644 --- a/scripts/build/Platform/Windows/build_config.json +++ b/scripts/build/Platform/Windows/build_config.json @@ -177,7 +177,8 @@ "CMAKE_NATIVE_BUILD_ARGS": "/m /nologo", "CTEST_OPTIONS": "-L \"(SUITE_smoke_REQUIRES_gpu|SUITE_main_REQUIRES_gpu)\" -T Test", "TEST_METRICS": "True", - "TEST_RESULTS": "True" + "TEST_RESULTS": "True", + "TEST_SCREENSHOTS": "True" } }, "asset_profile_vs2019": { diff --git a/scripts/build/tools/upload_to_s3.py b/scripts/build/tools/upload_to_s3.py index 5dfe5eb66e..132929d83e 100755 --- a/scripts/build/tools/upload_to_s3.py +++ b/scripts/build/tools/upload_to_s3.py @@ -17,6 +17,9 @@ python upload_to_s3.py --base_dir %WORKSPACE% --file_regex "(.*zip$|.*MD5$)" --b Use profile to upload all .zip and .MD5 files in %WORKSPACE% folder to bucket ly-packages-mainline: python upload_to_s3.py --base_dir %WORKSPACE% --profile profile --file_regex "(.*zip$|.*MD5$)" --bucket ly-packages-mainline +Another example usage for uploading all .png and .ppm files inside base_dir and only subdirectories within base_dir: +python upload_to_s3.py --base_dir %WORKSPACE%/path/to/files --file_regex "(.*png$|.*ppm$)" --bucket screenshot-test-bucket --search_subdirectories True --key_prefix Test + ''' @@ -34,6 +37,8 @@ def parse_args(): parser.add_option("--profile", dest="profile", default=None, help="The name of a profile to use. If not given, then the default profile is used.") parser.add_option("--bucket", dest="bucket", default=None, help="S3 bucket the files are uploaded to.") parser.add_option("--key_prefix", dest="key_prefix", default='', help="Object key prefix.") + parser.add_option("--search_subdirectories", dest="search_subdirectories", action='store_true', + help="Toggle for searching for files in subdirectories beneath base_dir, defaults to False") ''' ExtraArgs used to call s3.upload_file(), should be in json format. extra_args key must be one of: ACL, CacheControl, ContentDisposition, ContentEncoding, ContentLanguage, ContentType, Expires, GrantFullControl, GrantRead, GrantReadACP, GrantWriteACP, Metadata, RequestPayer, ServerSideEncryption, StorageClass, @@ -62,48 +67,74 @@ def get_client(service_name, profile_name): return client -def get_files_to_upload(base_dir, regex): +def get_files_to_upload(base_dir, regex, search_subdirectories): + """ + Uses a regex expression pattern to return a list of file paths for files to upload to the s3 bucket. + :param base_dir: path for the base directory, if using search_subdirectories=True ensure this is the parent. + :param regex: pattern to use for regex searching, ex. "(.*zip$|.*MD5$)" + :param search_subdirectories: boolean False for only getting files in base_dir, True to get all files in base_dir + and any subdirectory inside base_dir, defaults to False from the parse_args() function. + :return: a list of string file paths for files to upload to the s3 bucket matching the regex expression. + """ # Get all file names in base directory - files = [x for x in os.listdir(base_dir) if os.path.isfile(os.path.join(base_dir, x))] - # strip the surround quotes, if they exist + files = [os.path.join(base_dir, x) for x in os.listdir(base_dir) if os.path.isfile(os.path.join(base_dir, x))] + if search_subdirectories: # Get all file names in base directory and any subdirectories. + for subdirectory in os.walk(base_dir): + # Example output for subdirectory: + # ('C:\path\to\base_dir\', ['Subfolder1', 'Subfolder2'], ['file1', 'file2']) + subdirectory_file_path = subdirectory[0] + subdirectory_files = subdirectory[2] + subdirectory_file_paths = _build_file_paths(subdirectory_file_path, subdirectory_files) + files.extend(subdirectory_file_paths) + try: - regex = json.loads(regex) + regex = json.loads(regex) # strip the surround quotes, if they exist except: pass # Get all file names matching the regular expression, those file will be uploaded to S3 - files_to_upload = [x for x in files if re.match(regex, x)] - return files_to_upload + regex_files_to_upload = [x for x in files if re.match(regex, x)] + + return regex_files_to_upload -def s3_upload_file(client, base_dir, file, bucket, key_prefix=None, extra_args=None, max_retry=1): - print(('Uploading file {} to bucket {}.'.format(file, bucket))) +def s3_upload_file(client, file, bucket, key_prefix=None, extra_args=None, max_retry=1): key = file if key_prefix is None else '{}/{}'.format(key_prefix, file) for x in range(max_retry): try: - client.upload_file( - os.path.join(base_dir, file), bucket, key, - ExtraArgs=extra_args - ) - print('Upload succeeded') + client.upload_file(file, bucket, key, ExtraArgs=extra_args) return True except Exception as err: - print(('exception while uploading: {}'.format(err))) - print('Retrying upload...') - print('Upload failed') + print(('Upload failed: Exception while uploading: {}'.format(err))) return False +def _build_file_paths(path_to_files, files_in_path): + """ + Given a path containing files, returns a list of strings representing complete paths to each file. + :param path_to_files: path to the location storing the files to create string paths for + :param files_in_path: list of files that are inside the path_to_files path string + :return: list of fully parsed file path strings from path_to_files path. + """ + parsed_file_paths = [] + + for file_in_path in files_in_path: + complete_file_path = os.path.join(path_to_files, file_in_path) + parsed_file_paths.append(complete_file_path) + + return parsed_file_paths + + if __name__ == "__main__": options = parse_args() client = get_client('s3', options.profile) - files_to_upload = get_files_to_upload(options.base_dir, options.file_regex) + files_to_upload = get_files_to_upload(options.base_dir, options.file_regex, options.search_subdirectories) extra_args = json.loads(options.extra_args) if options.extra_args else None print(('Uploading {} files to bucket {}.'.format(len(files_to_upload), options.bucket))) failure = [] success = [] for file in files_to_upload: - if not s3_upload_file(client, options.base_dir, file, options.bucket, options.key_prefix, extra_args, 2): + if not s3_upload_file(client, file, options.bucket, options.key_prefix, extra_args, 2): failure.append(file) else: success.append(file) From 8459cbe5c2e1c75f47720594ffa8976ebf81b465 Mon Sep 17 00:00:00 2001 From: Doug McDiarmid Date: Sat, 12 Jun 2021 01:18:24 -0700 Subject: [PATCH 069/116] Removed the DiffuseGlobalIllumination component from the editor Entity Component list, it was intended to be a Level Component only. Checked for a valid quality level in DiffuseGlobalIlluminationFeatureProcessor::SetQualityLevel. Initialized the quality level to Low in DiffuseGlobalIlluminationComponentConfig. --- .../DiffuseGlobalIlluminationFeatureProcessorInterface.h | 4 +++- .../DiffuseGlobalIlluminationFeatureProcessor.cpp | 6 ++++++ .../DiffuseGlobalIlluminationComponentConfig.h | 2 +- .../EditorDiffuseGlobalIlluminationComponent.cpp | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/DiffuseGlobalIllumination/DiffuseGlobalIlluminationFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/DiffuseGlobalIllumination/DiffuseGlobalIlluminationFeatureProcessorInterface.h index 88faac1728..ce50cea17f 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/DiffuseGlobalIllumination/DiffuseGlobalIlluminationFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/DiffuseGlobalIllumination/DiffuseGlobalIlluminationFeatureProcessorInterface.h @@ -23,7 +23,9 @@ namespace AZ { Low, Medium, - High + High, + + Count }; //! This class provides general features and configuration for the diffuse global illumination environment, diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseGlobalIlluminationFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseGlobalIlluminationFeatureProcessor.cpp index 5040665456..1c28e18e0e 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseGlobalIlluminationFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseGlobalIlluminationFeatureProcessor.cpp @@ -43,6 +43,12 @@ namespace AZ void DiffuseGlobalIlluminationFeatureProcessor::SetQualityLevel(DiffuseGlobalIlluminationQualityLevel qualityLevel) { + if (qualityLevel >= DiffuseGlobalIlluminationQualityLevel::Count) + { + AZ_Assert(false, "SetQualityLevel called with invalid quality level [%d]", qualityLevel); + return; + } + m_qualityLevel = qualityLevel; UpdatePasses(); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/DiffuseGlobalIlluminationComponentConfig.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/DiffuseGlobalIlluminationComponentConfig.h index fb99a99e1a..8f1b216af5 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/DiffuseGlobalIlluminationComponentConfig.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/DiffuseGlobalIlluminationComponentConfig.h @@ -29,7 +29,7 @@ namespace AZ static void Reflect(ReflectContext* context); - DiffuseGlobalIlluminationQualityLevel m_qualityLevel; + DiffuseGlobalIlluminationQualityLevel m_qualityLevel = DiffuseGlobalIlluminationQualityLevel::Low; }; } } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/EditorDiffuseGlobalIlluminationComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/EditorDiffuseGlobalIlluminationComponent.cpp index bdb5686e89..7df965d831 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/EditorDiffuseGlobalIlluminationComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/EditorDiffuseGlobalIlluminationComponent.cpp @@ -36,7 +36,7 @@ namespace AZ ->Attribute(Edit::Attributes::Category, "Atom") ->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Component_Placeholder.svg") ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.png") - ->Attribute(Edit::Attributes::AppearsInAddComponentMenu, AZStd::vector({ AZ_CRC("Level", 0x9aeacc13), AZ_CRC("Game", 0x232b318c) })) + ->Attribute(Edit::Attributes::AppearsInAddComponentMenu, AZStd::vector({ AZ_CRC("Level", 0x9aeacc13) })) ->Attribute(Edit::Attributes::AutoExpand, true) ->Attribute(Edit::Attributes::HelpPageURL, "https://") ; From 886601ad947142cfeff23c6cb810c1798aeb43dc Mon Sep 17 00:00:00 2001 From: Doug McDiarmid Date: Sat, 12 Jun 2021 03:20:31 -0700 Subject: [PATCH 070/116] Created a new ReflectionScreenSpaceCompositePass to set the maximum roughness mip in the pass Srg. Changed the ReflectionScreenSpaceBlurPass to auto-generate the mip chain, which will compute the appropriate number of mips. --- .../Passes/ReflectionScreenSpaceBlur.pass | 4 +- .../ReflectionScreenSpaceComposite.pass | 2 +- .../ReflectionScreenSpaceComposite.azsl | 10 ++-- .../Code/Source/CommonSystemComponent.cpp | 2 + .../ReflectionScreenSpaceBlurPass.h | 3 + .../ReflectionScreenSpaceCompositePass.cpp | 55 +++++++++++++++++++ .../ReflectionScreenSpaceCompositePass.h | 43 +++++++++++++++ .../Code/atom_feature_common_files.cmake | 2 + 8 files changed, 112 insertions(+), 9 deletions(-) create mode 100644 Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceCompositePass.cpp create mode 100644 Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceCompositePass.h diff --git a/Gems/Atom/Feature/Common/Assets/Passes/ReflectionScreenSpaceBlur.pass b/Gems/Atom/Feature/Common/Assets/Passes/ReflectionScreenSpaceBlur.pass index 1d20382408..e2fde2d4ef 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/ReflectionScreenSpaceBlur.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/ReflectionScreenSpaceBlur.pass @@ -24,9 +24,9 @@ }, "ImageDescriptor": { "Format": "R16G16B16A16_FLOAT", - "MipLevels": "8", "SharedQueueMask": "Graphics" - } + }, + "GenerateFullMipChain": true } ], "Connections": [ diff --git a/Gems/Atom/Feature/Common/Assets/Passes/ReflectionScreenSpaceComposite.pass b/Gems/Atom/Feature/Common/Assets/Passes/ReflectionScreenSpaceComposite.pass index 80c4e8987b..5443c32406 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/ReflectionScreenSpaceComposite.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/ReflectionScreenSpaceComposite.pass @@ -5,7 +5,7 @@ "ClassData": { "PassTemplate": { "Name": "ReflectionScreenSpaceCompositePassTemplate", - "PassClass": "FullScreenTriangle", + "PassClass": "ReflectionScreenSpaceCompositePass", "Slots": [ { "Name": "TraceInput", diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionScreenSpaceComposite.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionScreenSpaceComposite.azsl index fa3885f180..c5c724e106 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionScreenSpaceComposite.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionScreenSpaceComposite.azsl @@ -37,6 +37,9 @@ ShaderResourceGroup PassSrg : SRG_PerPass AddressV = Clamp; AddressW = Clamp; }; + + // the max roughness mip level for sampling the previous frame image + uint m_maxMipLevel; } #include @@ -69,10 +72,6 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex) float4 positionWS = mul(ViewSrg::m_viewProjectionInverseMatrix, projectedPos); positionWS /= positionWS.w; - //float4 positionVS = mul(ViewSrg::m_projectionMatrixInverse, projectedPos); - //positionVS /= positionVS.w; - //float4 positionWS = mul(ViewSrg::m_viewMatrixInverse, positionVS); - // compute ray from camera to surface position float3 cameraToPositionWS = normalize(positionWS.xyz - ViewSrg::m_worldPosition); @@ -103,8 +102,7 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex) // compute the roughness mip to use in the previous frame image // remap the roughness mip into a lower range to more closely match the material roughness values const float MaxRoughness = 0.5f; - const float MaxRoughnessMip = 7; - float mip = saturate(roughness / MaxRoughness) * MaxRoughnessMip; + float mip = saturate(roughness / MaxRoughness) * PassSrg::m_maxMipLevel; // sample reflection value from the roughness mip float4 reflectionColor = float4(PassSrg::m_previousFrame.SampleLevel(PassSrg::LinearSampler, tracePrevUV, mip).rgb, 1.0f); diff --git a/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp index af28624357..1866da63e5 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp @@ -103,6 +103,7 @@ #include #include #include +#include #include #include @@ -283,6 +284,7 @@ namespace AZ // Add Reflection passes passSystem->AddPassCreator(Name("ReflectionScreenSpaceBlurPass"), &Render::ReflectionScreenSpaceBlurPass::Create); passSystem->AddPassCreator(Name("ReflectionScreenSpaceBlurChildPass"), &Render::ReflectionScreenSpaceBlurChildPass::Create); + passSystem->AddPassCreator(Name("ReflectionScreenSpaceCompositePass"), &Render::ReflectionScreenSpaceCompositePass::Create); passSystem->AddPassCreator(Name("ReflectionCopyFrameBufferPass"), &Render::ReflectionCopyFrameBufferPass::Create); // Add RayTracing pas diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurPass.h b/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurPass.h index 4a2ccce1d4..be8dc6d596 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurPass.h +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurPass.h @@ -37,6 +37,9 @@ namespace AZ //! to store the previous frame image Data::Instance& GetFrameBufferImageAttachment() { return m_frameBufferImageAttachment; } + //! Returns the number of mip levels in the blur + uint32_t GetNumBlurMips() const { return m_numBlurMips; } + private: explicit ReflectionScreenSpaceBlurPass(const RPI::PassDescriptor& descriptor); diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceCompositePass.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceCompositePass.cpp new file mode 100644 index 0000000000..fe2030ca7e --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceCompositePass.cpp @@ -0,0 +1,55 @@ +/* +* 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 "ReflectionScreenSpaceCompositePass.h" +#include "ReflectionScreenSpaceBlurPass.h" +#include +#include + +namespace AZ +{ + namespace Render + { + RPI::Ptr ReflectionScreenSpaceCompositePass::Create(const RPI::PassDescriptor& descriptor) + { + RPI::Ptr pass = aznew ReflectionScreenSpaceCompositePass(descriptor); + return AZStd::move(pass); + } + + ReflectionScreenSpaceCompositePass::ReflectionScreenSpaceCompositePass(const RPI::PassDescriptor& descriptor) + : RPI::FullscreenTrianglePass(descriptor) + { + } + + void ReflectionScreenSpaceCompositePass::CompileResources([[maybe_unused]] const RHI::FrameGraphCompileContext& context) + { + if (!m_shaderResourceGroup) + { + return; + } + + RPI::PassHierarchyFilter passFilter(AZ::Name("ReflectionScreenSpaceBlurPass")); + const AZStd::vector& passes = RPI::PassSystemInterface::Get()->FindPasses(passFilter); + if (!passes.empty()) + { + Render::ReflectionScreenSpaceBlurPass* blurPass = azrtti_cast(passes.front()); + const uint32_t MaxNumRoughnessMips = 8; + uint32_t maxMipLevel = AZStd::min(MaxNumRoughnessMips, blurPass->GetNumBlurMips()) - 1; + + auto constantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_maxMipLevel")); + m_shaderResourceGroup->SetConstant(constantIndex, maxMipLevel); + } + + FullscreenTrianglePass::CompileResources(context); + } + } // namespace RPI +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceCompositePass.h b/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceCompositePass.h new file mode 100644 index 0000000000..110673541e --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceCompositePass.h @@ -0,0 +1,43 @@ +/* +* 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 +#include +#include +#include + +namespace AZ +{ + namespace Render + { + //! This pass composites the screenspace reflection trace onto the reflection buffer. + class ReflectionScreenSpaceCompositePass + : public RPI::FullscreenTrianglePass + { + AZ_RPI_PASS(ReflectionScreenSpaceCompositePass); + + public: + AZ_RTTI(Render::ReflectionScreenSpaceCompositePass, "{88739CC9-C3F1-413A-A527-9916C697D93A}", FullscreenTrianglePass); + AZ_CLASS_ALLOCATOR(Render::ReflectionScreenSpaceCompositePass, SystemAllocator, 0); + + //! Creates a new pass without a PassTemplate + static RPI::Ptr Create(const RPI::PassDescriptor& descriptor); + + private: + explicit ReflectionScreenSpaceCompositePass(const RPI::PassDescriptor& descriptor); + + // Pass Overrides... + void CompileResources(const RHI::FrameGraphCompileContext& context) override; + }; + } // namespace RPI +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake b/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake index a759de77fa..a656558abf 100644 --- a/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake +++ b/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake @@ -267,6 +267,8 @@ set(FILES Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurPass.h Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurChildPass.cpp Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurChildPass.h + Source/ReflectionScreenSpace/ReflectionScreenSpaceCompositePass.cpp + Source/ReflectionScreenSpace/ReflectionScreenSpaceCompositePass.h Source/ReflectionScreenSpace/ReflectionCopyFrameBufferPass.cpp Source/ReflectionScreenSpace/ReflectionCopyFrameBufferPass.h Source/ScreenSpace/DeferredFogSettings.cpp From 00062430a2788e21f61186f78d199b56aae5f316 Mon Sep 17 00:00:00 2001 From: Santora Date: Sat, 12 Jun 2021 11:52:46 -0700 Subject: [PATCH 071/116] Updated the usage of ShaderReloadDebugTracker to include the address of the object. This is necessary for debugging where multiple assets may be reloading at the same time. Also added a Printf function for generic messages at the current indent level. This is specifically in support of: ATOM-14613 Baseviewer MatertialHotReloadTest fails to change the color after turning blending on and off ATOM-15728 Shader Hot Reload Fails in Debug Build --- .../RPI.Public/Shader/ShaderReloadDebugTracker.h | 14 ++++++++++++++ .../Code/Source/RPI.Public/Material/Material.cpp | 9 +++++---- .../RPI/Code/Source/RPI.Public/Shader/Shader.cpp | 2 +- .../Source/RPI.Reflect/Material/MaterialAsset.cpp | 2 +- .../RPI.Reflect/Material/MaterialTypeAsset.cpp | 2 +- .../Code/Source/RPI.Reflect/Shader/ShaderAsset.cpp | 4 ++-- 6 files changed, 24 insertions(+), 9 deletions(-) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Shader/ShaderReloadDebugTracker.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Shader/ShaderReloadDebugTracker.h index dfda93dca3..8220d25eb8 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Shader/ShaderReloadDebugTracker.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Shader/ShaderReloadDebugTracker.h @@ -57,6 +57,20 @@ namespace AZ } #endif } + + //! Prints a generic message at the appropriate indent level. + template + static void Printf([[maybe_unused]] const char* format, [[maybe_unused]] Args... args) + { +#ifdef AZ_ENABLE_SHADER_RELOAD_DEBUG_TRACKER + if (IsEnabled()) + { + const AZStd::string message = AZStd::string::format(format, args...); + + AZ_TracePrintf("ShaderReloadDebug", "%*s %s \n", s_indent, "", message.c_str()); + } +#endif + } //! Use this utility to call BeginSection(), and automatically call EndSection() when the object goes out of scope. class ScopedSection final diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp index 4a2718b9d5..eac1ee42e5 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp @@ -97,6 +97,7 @@ namespace AZ ShaderReloadNotificationBus::MultiHandler::BusDisconnect(); for (auto& shaderItem : m_shaderCollection) { + ShaderReloadDebugTracker::Printf("(Material has ShaderAsset %p)", shaderItem.GetShaderAsset().Get()); ShaderReloadNotificationBus::MultiHandler::BusConnect(shaderItem.GetShaderAsset().GetId()); } @@ -226,7 +227,7 @@ namespace AZ // AssetBus overrides... void Material::OnAssetReloaded(Data::Asset asset) { - ShaderReloadDebugTracker::ScopedSection reloadSection("Material::OnAssetReloaded %s", asset.GetHint().c_str()); + ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnAssetReloaded %s", this, asset.GetHint().c_str()); Data::Asset newMaterialAsset = { asset.GetAs(), AZ::Data::AssetLoadBehavior::PreLoad }; @@ -241,7 +242,7 @@ namespace AZ // MaterialReloadNotificationBus overrides... void Material::OnMaterialAssetReinitialized(const Data::Asset& materialAsset) { - ShaderReloadDebugTracker::ScopedSection reloadSection("Material::OnMaterialAssetReinitialized %s", materialAsset.GetHint().c_str()); + ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnMaterialAssetReinitialized %s", this, materialAsset.GetHint().c_str()); OnAssetReloaded(materialAsset); } @@ -249,7 +250,7 @@ namespace AZ // ShaderReloadNotificationBus overrides... void Material::OnShaderReinitialized([[maybe_unused]] const Shader& shader) { - ShaderReloadDebugTracker::ScopedSection reloadSection("Material::OnShaderReinitialized %s", shader.GetAsset().GetHint().c_str()); + ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnShaderReinitialized %s", this, shader.GetAsset().GetHint().c_str()); // Note that it might not be strictly necessary to reinitialize the entire material, we might be able to get away with // just bumping the m_currentChangeId or some other minor updates. But it's pretty hard to know what exactly needs to be // updated to correctly handle the reload, so it's safer to just reinitialize the whole material. @@ -269,7 +270,7 @@ namespace AZ void Material::OnShaderVariantReinitialized(const Shader& shader, const ShaderVariantId& /*shaderVariantId*/, ShaderVariantStableId shaderVariantStableId) { - ShaderReloadDebugTracker::ScopedSection reloadSection("Material::OnShaderVariantReinitialized %s variant %u", shader.GetAsset().GetHint().c_str(), shaderVariantStableId.GetIndex()); + ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnShaderVariantReinitialized %s variant %u", this, shader.GetAsset().GetHint().c_str(), shaderVariantStableId.GetIndex()); // Note that it would be better to check the shaderVariantId to see if that variant is relevant to this particular material before reinitializing it. // There could be hundreds or even thousands of variants for a shader, but only one of those variants will be used by any given material. So we could diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp index 7194c524ae..147f24d4f8 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp @@ -132,7 +132,7 @@ namespace AZ // AssetBus overrides void Shader::OnAssetReloaded(Data::Asset asset) { - ShaderReloadDebugTracker::ScopedSection reloadSection("Shader::OnAssetReloaded %s", asset.GetHint().c_str()); + ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Shader::OnAssetReloaded %s", this, asset.GetHint().c_str()); if (asset->GetId() == m_asset->GetId()) { diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp index 7e9e2ddb10..2e56c30652 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp @@ -119,7 +119,7 @@ namespace AZ void MaterialAsset::OnAssetReloaded(Data::Asset asset) { - ShaderReloadDebugTracker::ScopedSection reloadSection("MaterialAsset::OnAssetReloaded %s", asset.GetHint().c_str()); + ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->MaterialAsset::OnAssetReloaded %s", this, asset.GetHint().c_str()); Data::Asset newMaterialTypeAsset = { asset.GetAs(), AZ::Data::AssetLoadBehavior::PreLoad }; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAsset.cpp index 20adb63cb8..f7d0a83ac9 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAsset.cpp @@ -130,7 +130,7 @@ namespace AZ void MaterialTypeAsset::OnAssetReloaded(Data::Asset asset) { - ShaderReloadDebugTracker::ScopedSection reloadSection("MaterialTypeAsset::OnAssetReloaded %s", asset.GetHint().c_str()); + ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->MaterialTypeAsset::OnAssetReloaded %s", this, asset.GetHint().c_str()); // The order of asset reloads is non-deterministic. If the MaterialTypeAsset reloads before these // dependency assets, this will make sure the MaterialTypeAsset gets the latest ones when they reload. diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderAsset.cpp index cf655d43f7..75d4a47bc0 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderAsset.cpp @@ -381,7 +381,7 @@ namespace AZ // AssetBus overrides... void ShaderAsset::OnAssetReloaded(Data::Asset asset) { - ShaderReloadDebugTracker::ScopedSection reloadSection("ShaderAsset::OnAssetReloaded %s", asset.GetHint().c_str()); + ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->ShaderAsset::OnAssetReloaded %s", this, asset.GetHint().c_str()); Data::Asset shaderVariantAsset = { asset.GetAs(), AZ::Data::AssetLoadBehavior::PreLoad }; AZ_Assert(shaderVariantAsset->GetStableId() == RootShaderVariantStableId, @@ -396,7 +396,7 @@ namespace AZ /// ShaderVariantFinderNotificationBus overrides void ShaderAsset::OnShaderVariantTreeAssetReady(Data::Asset shaderVariantTreeAsset, bool isError) { - ShaderReloadDebugTracker::ScopedSection reloadSection("ShaderAsset::OnShaderVariantTreeAssetReady %s", shaderVariantTreeAsset.GetHint().c_str()); + ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->ShaderAsset::OnShaderVariantTreeAssetReady %s", this, shaderVariantTreeAsset.GetHint().c_str()); AZStd::unique_lock lock(m_variantTreeMutex); if (isError) From bb083fde3c3e58458a94e1ffed1315b835fb6746 Mon Sep 17 00:00:00 2001 From: Doug McDiarmid Date: Sat, 12 Jun 2021 17:28:50 -0700 Subject: [PATCH 072/116] Added ReflectiveCubeMap usage flag if the shadow is rendering in an EnvironmentCubeMap pipeline --- .../DirectionalLightFeatureProcessor.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp index c4f4bc54b3..08bc443586 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #include #include @@ -1070,7 +1072,18 @@ namespace AZ segment.m_pipelineViewTag = viewTag; if (!segment.m_view || segment.m_view->GetName() != viewName) { - segment.m_view = RPI::View::CreateView(viewName, RPI::View::UsageShadow); + RPI::View::UsageFlags usageFlags = RPI::View::UsageShadow; + + // if the shadow is rendering in an EnvironmentCubeMapPass it also needs to be a ReflectiveCubeMap view, + // to filter out shadows from objects that are excluded from the cubemap + RPI::PassClassFilter passFilter; + AZStd::vector cubeMapPasses = AZ::RPI::PassSystemInterface::Get()->FindPasses(passFilter); + if (!cubeMapPasses.empty()) + { + usageFlags |= RPI::View::UsageReflectiveCubeMap; + } + + segment.m_view = RPI::View::CreateView(viewName, usageFlags); } } } From e72cae47b42fc742506e25a975b0bbc67f1488bd Mon Sep 17 00:00:00 2001 From: moudgils Date: Sat, 12 Jun 2021 21:16:22 -0700 Subject: [PATCH 073/116] Buffer update fixes for metal --- .../Code/Source/RHI/AsyncUploadQueue.cpp | 42 +++++++++++++------ .../Code/Source/RHI/BufferPoolResolver.cpp | 7 +++- .../Code/Source/RHI/MemoryPageAllocator.cpp | 2 +- 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/AsyncUploadQueue.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/AsyncUploadQueue.cpp index 594a4931b9..e9cf06967a 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/AsyncUploadQueue.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/AsyncUploadQueue.cpp @@ -85,16 +85,34 @@ namespace AZ uint64_t AsyncUploadQueue::QueueUpload(const RHI::BufferStreamRequest& uploadRequest) { - uint64_t queueValue = m_uploadFence.Increment(); - - const MemoryView& memoryView = static_cast(*uploadRequest.m_buffer).GetMemoryView(); - RHI::Ptr buffer = memoryView.GetMemory(); - + Buffer& destBuffer = static_cast(*uploadRequest.m_buffer); + const MemoryView& destMemoryView = destBuffer.GetMemoryView(); + MTLStorageMode mtlStorageMode = destBuffer.GetMemoryView().GetStorageMode(); + RHI::BufferPool& bufferPool = static_cast(*destBuffer.GetPool()); + /* + if(mtlStorageMode == MTLStorageModeShared || mtlStorageMode == GetCPUGPUMemoryMode()) + { + RHI::BufferMapRequest mapRequest; + mapRequest.m_buffer = uploadRequest.m_buffer; + mapRequest.m_byteCount = uploadRequest.m_byteCount; + mapRequest.m_byteOffset = uploadRequest.m_byteOffset; + RHI::BufferMapResponse mapResponse; + bufferPool.MapBuffer(mapRequest, mapResponse); + ::memcpy(mapResponse.m_data, uploadRequest.m_sourceData, uploadRequest.m_byteCount); + bufferPool.UnmapBuffer(*uploadRequest.m_buffer); + if (uploadRequest.m_fenceToSignal) + { + uploadRequest.m_fenceToSignal->SignalOnCpu(); + } + return m_uploadFence.GetPendingValue(); + } + */ Fence* fenceToSignal = nullptr; uint64_t fenceToSignalValue = 0; - size_t byteCount = uploadRequest.m_byteCount; - size_t byteOffset = memoryView.GetOffset() + uploadRequest.m_byteOffset; + size_t byteOffset = destMemoryView.GetOffset() + uploadRequest.m_byteOffset; + uint64_t queueValue = m_uploadFence.Increment(); + const uint8_t* sourceData = reinterpret_cast(uploadRequest.m_sourceData); if (uploadRequest.m_fenceToSignal) @@ -125,11 +143,11 @@ namespace AZ } id blitEncoder = [framePacket->m_mtlCommandBuffer blitCommandEncoder]; - [blitEncoder copyFromBuffer:framePacket->m_stagingResource - sourceOffset:0 - toBuffer:buffer->GetGpuAddress>() - destinationOffset:byteOffset + pendingByteOffset - size:bytesToCopy]; + [blitEncoder copyFromBuffer: framePacket->m_stagingResource + sourceOffset: 0 + toBuffer: destMemoryView.GetGpuAddress>() + destinationOffset: byteOffset + pendingByteOffset + size: bytesToCopy]; [blitEncoder endEncoding]; blitEncoder = nil; diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/BufferPoolResolver.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/BufferPoolResolver.cpp index 2ca8303dc9..ce5ff64280 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/BufferPoolResolver.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/BufferPoolResolver.cpp @@ -40,7 +40,7 @@ namespace AZ buffer->m_pendingResolves++; uploadRequest.m_attachmentBuffer = buffer; - uploadRequest.m_byteOffset = request.m_byteOffset; + uploadRequest.m_byteOffset = request.m_byteOffset;;//buffer->GetMemoryView().GetOffset() + request.m_byteOffset; uploadRequest.m_stagingBuffer = stagingBuffer; uploadRequest.m_byteSize = request.m_byteCount; @@ -64,9 +64,12 @@ namespace AZ AZ_Assert(stagingBuffer, "Staging Buffer is null."); AZ_Assert(destBuffer, "Attachment Buffer is null."); + //Inform the GPU that the CPU has modified the staging buffer. + //Platform::SynchronizeBufferOnCPU(stagingBuffer->GetMemoryView().GetGpuAddress>(), stagingBuffer->GetMemoryView().GetOffset(), stagingBuffer->GetMemoryView().GetSize()); + RHI::CopyBufferDescriptor copyDescriptor; copyDescriptor.m_sourceBuffer = stagingBuffer; - copyDescriptor.m_sourceOffset = 0; + copyDescriptor.m_sourceOffset = 0;//stagingBuffer->GetMemoryView().GetOffset(); copyDescriptor.m_destinationBuffer = destBuffer; copyDescriptor.m_destinationOffset = static_cast(packet.m_byteOffset); copyDescriptor.m_size = static_cast(packet.m_byteSize); diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/MemoryPageAllocator.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/MemoryPageAllocator.cpp index 60581aeb2c..dedfb8157e 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/MemoryPageAllocator.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/MemoryPageAllocator.cpp @@ -44,7 +44,7 @@ namespace AZ if (memoryView.IsValid()) { heapMemoryUsage.m_residentInBytes += m_descriptor.m_pageSizeInBytes; - memoryView.SetName("BufferPage"); + //memoryView.SetName(AZStd::string::format("BufferPage_%s", AZ::Uuid::CreateRandom().ToString().c_str())); } else { From 4e5d690584094014b3527970a19cb30f8d330ca2 Mon Sep 17 00:00:00 2001 From: moudgils Date: Sun, 13 Jun 2021 22:05:21 -0700 Subject: [PATCH 074/116] Fixes to buffer updates --- Gems/Atom/RHI/Metal/Code/Source/RHI/AsyncUploadQueue.cpp | 6 ++++-- Gems/Atom/RHI/Metal/Code/Source/RHI/BufferPoolResolver.cpp | 6 +++--- Gems/Atom/RHI/Metal/Code/Source/RHI/MemoryPageAllocator.cpp | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/AsyncUploadQueue.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/AsyncUploadQueue.cpp index e9cf06967a..29e0b19b75 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/AsyncUploadQueue.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/AsyncUploadQueue.cpp @@ -89,7 +89,9 @@ namespace AZ const MemoryView& destMemoryView = destBuffer.GetMemoryView(); MTLStorageMode mtlStorageMode = destBuffer.GetMemoryView().GetStorageMode(); RHI::BufferPool& bufferPool = static_cast(*destBuffer.GetPool()); - /* + + // No need to use staging buffers since it's host memory. + // We just map, copy and then unmap. if(mtlStorageMode == MTLStorageModeShared || mtlStorageMode == GetCPUGPUMemoryMode()) { RHI::BufferMapRequest mapRequest; @@ -106,7 +108,7 @@ namespace AZ } return m_uploadFence.GetPendingValue(); } - */ + Fence* fenceToSignal = nullptr; uint64_t fenceToSignalValue = 0; size_t byteCount = uploadRequest.m_byteCount; diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/BufferPoolResolver.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/BufferPoolResolver.cpp index ce5ff64280..18cd51df3f 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/BufferPoolResolver.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/BufferPoolResolver.cpp @@ -40,7 +40,7 @@ namespace AZ buffer->m_pendingResolves++; uploadRequest.m_attachmentBuffer = buffer; - uploadRequest.m_byteOffset = request.m_byteOffset;;//buffer->GetMemoryView().GetOffset() + request.m_byteOffset; + uploadRequest.m_byteOffset = buffer->GetMemoryView().GetOffset() + request.m_byteOffset; uploadRequest.m_stagingBuffer = stagingBuffer; uploadRequest.m_byteSize = request.m_byteCount; @@ -65,11 +65,11 @@ namespace AZ AZ_Assert(destBuffer, "Attachment Buffer is null."); //Inform the GPU that the CPU has modified the staging buffer. - //Platform::SynchronizeBufferOnCPU(stagingBuffer->GetMemoryView().GetGpuAddress>(), stagingBuffer->GetMemoryView().GetOffset(), stagingBuffer->GetMemoryView().GetSize()); + Platform::SynchronizeBufferOnCPU(stagingBuffer->GetMemoryView().GetGpuAddress>(), stagingBuffer->GetMemoryView().GetOffset(), stagingBuffer->GetMemoryView().GetSize()); RHI::CopyBufferDescriptor copyDescriptor; copyDescriptor.m_sourceBuffer = stagingBuffer; - copyDescriptor.m_sourceOffset = 0;//stagingBuffer->GetMemoryView().GetOffset(); + copyDescriptor.m_sourceOffset = stagingBuffer->GetMemoryView().GetOffset(); copyDescriptor.m_destinationBuffer = destBuffer; copyDescriptor.m_destinationOffset = static_cast(packet.m_byteOffset); copyDescriptor.m_size = static_cast(packet.m_byteSize); diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/MemoryPageAllocator.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/MemoryPageAllocator.cpp index dedfb8157e..88aa4b4ed1 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/MemoryPageAllocator.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/MemoryPageAllocator.cpp @@ -44,7 +44,7 @@ namespace AZ if (memoryView.IsValid()) { heapMemoryUsage.m_residentInBytes += m_descriptor.m_pageSizeInBytes; - //memoryView.SetName(AZStd::string::format("BufferPage_%s", AZ::Uuid::CreateRandom().ToString().c_str())); + memoryView.SetName(AZStd::string::format("BufferPage_%s", AZ::Uuid::CreateRandom().ToString().c_str())); } else { From f8f282998b8e3b26483dcbf69358fb1473738bd4 Mon Sep 17 00:00:00 2001 From: moudgils Date: Sun, 13 Jun 2021 23:36:56 -0700 Subject: [PATCH 075/116] Added support to call not call UseResources on samee resource multiple times. --- .../Metal/Code/Source/RHI/ArgumentBuffer.cpp | 25 +++++++++---------- .../Metal/Code/Source/RHI/ArgumentBuffer.h | 13 +++------- .../Code/Source/RHI/BufferPoolResolver.cpp | 3 +-- .../Code/Source/RHI/BufferPoolResolver.h | 1 - 4 files changed, 17 insertions(+), 25 deletions(-) diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp index 49ff4146fc..c433a6f9cf 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp @@ -400,15 +400,13 @@ namespace AZ id mtlconstantBufferResource = m_constantBuffer.GetGpuAddress>(); if(RHI::CheckBitsAny(srgResourcesVisInfo.m_constantDataStageMask, RHI::ShaderStageMask::Compute)) { - uint16_t arrayIndex = resourcesToMakeResidentCompute[MTLResourceUsageRead].m_resourceArrayLen++; - resourcesToMakeResidentCompute[MTLResourceUsageRead].m_resourceArray[arrayIndex] = mtlconstantBufferResource; + resourcesToMakeResidentCompute[MTLResourceUsageRead].emplace(mtlconstantBufferResource); } else { MTLRenderStages mtlRenderStages = GetRenderStages(srgResourcesVisInfo.m_constantDataStageMask); - AZStd::pair key = AZStd::make_pair(MTLResourceUsageRead, mtlRenderStages); - uint16_t arrayIndex = resourcesToMakeResidentGraphics[key].m_resourceArrayLen++; - resourcesToMakeResidentGraphics[key].m_resourceArray[arrayIndex] = mtlconstantBufferResource; + AZStd::pair key = AZStd::make_pair(MTLResourceUsageRead, mtlRenderStages); + resourcesToMakeResidentGraphics[key].emplace(mtlconstantBufferResource); } } } @@ -440,16 +438,18 @@ namespace AZ //Call UseResource on all resources for Compute stage for (const auto& key : resourcesToMakeResidentCompute) { - [static_cast>(commandEncoder) useResources: key.second.m_resourceArray.data() - count: key.second.m_resourceArrayLen + AZStd::vector> resourcesToProcessVec(key.second.begin(), key.second.end()); + [static_cast>(commandEncoder) useResources: &resourcesToProcessVec[0] + count: resourcesToProcessVec.size() usage: key.first]; } //Call UseResource on all resources for Vertex and Fragment stages for (const auto& key : resourcesToMakeResidentGraphics) { - [static_cast>(commandEncoder) useResources: key.second.m_resourceArray.data() - count: key.second.m_resourceArrayLen + AZStd::vector> resourcesToProcessVec(key.second.begin(), key.second.end()); + [static_cast>(commandEncoder) useResources: &resourcesToProcessVec[0] + count: resourcesToProcessVec.size() usage: key.first.first stages: key.first.second]; } @@ -480,9 +480,9 @@ namespace AZ AZ_Assert(false, "Undefined Resource type"); } } - uint16_t arrayIndex = resourcesToMakeResidentMap[resourceUsage].m_resourceArrayLen++; + id mtlResourceToBind = resourceBindingData.m_resourcPtr->GetGpuAddress>(); - resourcesToMakeResidentMap[resourceUsage].m_resourceArray[arrayIndex] = mtlResourceToBind; + resourcesToMakeResidentMap[resourceUsage].emplace(mtlResourceToBind); } } @@ -516,9 +516,8 @@ namespace AZ } AZStd::pair key = AZStd::make_pair(resourceUsage, mtlRenderStages); - uint16_t arrayIndex = resourcesToMakeResidentMap[key].m_resourceArrayLen++; id mtlResourceToBind = resourceBindingData.m_resourcPtr->GetGpuAddress>(); - resourcesToMakeResidentMap[key].m_resourceArray[arrayIndex] = mtlResourceToBind; + resourcesToMakeResidentMap[key].emplace(mtlResourceToBind); } } } diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.h b/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.h index c4cfd17390..29d7d5e239 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.h +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.h @@ -120,15 +120,10 @@ namespace AZ ResourceBindingsMap m_resourceBindings; static const int MaxEntriesInArgTable = 31; - struct MetalResourceArray - { - AZStd::array, MaxEntriesInArgTable> m_resourceArray; - uint16_t m_resourceArrayLen = 0; - }; - //Map to cache all the resources based on the usage as we can batch all the resources for a given usage - using ComputeResourcesToMakeResidentMap = AZStd::unordered_map; - //Map to cache all the resources based on the usage and shader stage as we can batch all the resources for a given usage/shader usage - using GraphicsResourcesToMakeResidentMap = AZStd::unordered_map, MetalResourceArray>; + //Map to cache all the resources based on the usage as we can batch all the resources for a given usage. + using ComputeResourcesToMakeResidentMap = AZStd::unordered_map>>; + //Map to cache all the resources based on the usage and shader stage as we can batch all the resources for a given usage/shader usage. + using GraphicsResourcesToMakeResidentMap = AZStd::unordered_map, AZStd::unordered_set>>; void CollectResourcesForCompute(id encoder, const ResourceBindingsSet& resourceBindingData, diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/BufferPoolResolver.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/BufferPoolResolver.cpp index 18cd51df3f..b986b8ea75 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/BufferPoolResolver.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/BufferPoolResolver.cpp @@ -42,7 +42,6 @@ namespace AZ uploadRequest.m_attachmentBuffer = buffer; uploadRequest.m_byteOffset = buffer->GetMemoryView().GetOffset() + request.m_byteOffset; uploadRequest.m_stagingBuffer = stagingBuffer; - uploadRequest.m_byteSize = request.m_byteCount; return stagingBuffer->GetMemoryView().GetCpuAddress(); } @@ -72,7 +71,7 @@ namespace AZ copyDescriptor.m_sourceOffset = stagingBuffer->GetMemoryView().GetOffset(); copyDescriptor.m_destinationBuffer = destBuffer; copyDescriptor.m_destinationOffset = static_cast(packet.m_byteOffset); - copyDescriptor.m_size = static_cast(packet.m_byteSize); + copyDescriptor.m_size = stagingBuffer->GetMemoryView().GetSize(); commandList.Submit(RHI::CopyItem(copyDescriptor)); device.QueueForRelease(stagingBuffer->GetMemoryView()); diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/BufferPoolResolver.h b/Gems/Atom/RHI/Metal/Code/Source/RHI/BufferPoolResolver.h index c62d9494db..3e60bb31fa 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/BufferPoolResolver.h +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/BufferPoolResolver.h @@ -54,7 +54,6 @@ namespace AZ Buffer* m_attachmentBuffer = nullptr; RHI::Ptr m_stagingBuffer; size_t m_byteOffset = 0; - size_t m_byteSize = 0; }; AZStd::mutex m_uploadPacketsLock; From 59f3813b104f582b51872356d37460f2e6bab274 Mon Sep 17 00:00:00 2001 From: Benjamin Jillich <43751992+amzn-jillich@users.noreply.github.com> Date: Mon, 14 Jun 2021 08:45:00 +0200 Subject: [PATCH 076/116] [LYN-3481] EMotionFX crashes when reloading an Actor (#1184) (#1217) * [LYN-3481] Added new actor instance request and notification buses * [LYN-3481] Actor instance notifies bus about it being created or destroyed * [LYN-3481] Selection lists are now automatically removing destroyed actor instances * [LYN-3481] Morph targets window plugin reinitializing when used actor instance got destroyed * [LYN-3481] Removing the OnDeleteActorInstance() from the emfx event handler/manager and porting the recorder to the new actor instance bus * [LYN-3481] Removed the create actor instance calls from the event handler/manager * [LYN-3481] Fixing automated tests --- .../CommandSystem/Source/SelectionList.cpp | 7 +++ .../CommandSystem/Source/SelectionList.h | 7 ++- .../Code/EMotionFX/Source/ActorInstance.cpp | 13 ++--- .../Code/EMotionFX/Source/ActorInstanceBus.h | 54 +++++++++++++++++++ .../Code/EMotionFX/Source/EventHandler.h | 12 ----- .../Code/EMotionFX/Source/EventManager.cpp | 21 -------- .../Code/EMotionFX/Source/EventManager.h | 10 ---- .../Code/EMotionFX/Source/Recorder.cpp | 10 ++-- .../Code/EMotionFX/Source/Recorder.h | 8 +-- .../MorphTargetsWindowPlugin.cpp | 37 +++++++------ .../MorphTargetsWindowPlugin.h | 6 +++ .../Code/EMotionFX/emotionfx_files.cmake | 1 + 12 files changed, 107 insertions(+), 79 deletions(-) create mode 100644 Gems/EMotionFX/Code/EMotionFX/Source/ActorInstanceBus.h diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionList.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionList.cpp index a9f8cc063c..9beeebef86 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionList.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionList.cpp @@ -20,10 +20,12 @@ namespace CommandSystem SelectionList::SelectionList() { EMotionFX::ActorNotificationBus::Handler::BusConnect(); + EMotionFX::ActorInstanceNotificationBus::Handler::BusConnect(); } SelectionList::~SelectionList() { + EMotionFX::ActorInstanceNotificationBus::Handler::BusDisconnect(); EMotionFX::ActorNotificationBus::Handler::BusDisconnect(); } @@ -378,4 +380,9 @@ namespace CommandSystem RemoveActor(actor); } + + void SelectionList::OnActorInstanceDestroyed(EMotionFX::ActorInstance* actorInstance) + { + RemoveActorInstance(actorInstance); + } } // namespace CommandSystem diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionList.h b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionList.h index cd2eb3af5d..c85f8e601b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionList.h +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionList.h @@ -15,6 +15,7 @@ #include "CommandSystemConfig.h" #include #include +#include #include #include #include @@ -27,7 +28,8 @@ namespace CommandSystem * specific time stamp in a scene. */ class COMMANDSYSTEM_API SelectionList - : EMotionFX::ActorNotificationBus::Handler + : private EMotionFX::ActorNotificationBus::Handler + , private EMotionFX::ActorInstanceNotificationBus::Handler { MCORE_MEMORYOBJECTCATEGORY(SelectionList, MCore::MCORE_DEFAULT_ALIGNMENT, MEMCATEGORY_COMMANDSYSTEM); @@ -400,6 +402,9 @@ namespace CommandSystem // ActorNotificationBus overrides void OnActorDestroyed(EMotionFX::Actor* actor) override; + // ActorInstanceNotificationBus overrides + void OnActorInstanceDestroyed(EMotionFX::ActorInstance* actorInstance) override; + AZStd::vector mSelectedNodes; /**< Array of selected nodes. */ AZStd::vector mSelectedActors; /**< The selected actors. */ AZStd::vector mSelectedActorInstances; /**< Array of selected actor instances. */ diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp index ec1b00bda4..8175d15496 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp @@ -34,6 +34,7 @@ #include "NodeGroup.h" #include "Recorder.h" #include "TransformData.h" +#include #include #include @@ -153,20 +154,14 @@ namespace EMotionFX // register it GetActorManager().RegisterActorInstance(this); - // automatically register the actor instance - GetEventManager().OnCreateActorInstance(this); - GetActorManager().GetScheduler()->RecursiveInsertActorInstance(this); + + ActorInstanceNotificationBus::Broadcast(&ActorInstanceNotificationBus::Events::OnActorInstanceCreated, this); } - // the destructor ActorInstance::~ActorInstance() { - // trigger the OnDeleteActorInstance event - GetEventManager().OnDeleteActorInstance(this); - - // remove it from the recording - GetRecorder().RemoveActorInstanceFromRecording(this); + ActorInstanceNotificationBus::Broadcast(&ActorInstanceNotificationBus::Events::OnActorInstanceDestroyed, this); // get rid of the motion system if (mMotionSystem) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstanceBus.h b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstanceBus.h new file mode 100644 index 0000000000..15b25ce0d3 --- /dev/null +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstanceBus.h @@ -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 + +namespace EMotionFX +{ + class ActorInstance; + + /** + * EMotion FX Actor Instance Request Bus + * Used for making requests to actor instances. + */ + class ActorInstanceRequests + : public AZ::EBusTraits + { + public: + }; + + using ActorInstanceRequestBus = AZ::EBus; + + /** + * EMotion FX Actor Instance Notification Bus + * Used for monitoring events from actor instances. + */ + class ActorInstanceNotifications + : public AZ::EBusTraits + { + public: + // Enable multi-threaded access by locking primitive using a mutex when connecting handlers to the EBus or executing events. + using MutexType = AZStd::recursive_mutex; + + virtual void OnActorInstanceCreated([[maybe_unused]] ActorInstance* actorInstance) {} + + /** + * Called when any of the actor instances gets destructed. + * @param actorInstance The actorInstance that gets destructed. + */ + virtual void OnActorInstanceDestroyed([[maybe_unused]] ActorInstance* actorInstance) {} + }; + + using ActorInstanceNotificationBus = AZ::EBus; +} // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/EventHandler.h b/Gems/EMotionFX/Code/EMotionFX/Source/EventHandler.h index 1e6fb86156..2c8ae9d868 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/EventHandler.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/EventHandler.h @@ -51,7 +51,6 @@ namespace EMotionFX EVENT_TYPE_MOTION_INSTANCE_LAST_EVENT = EVENT_TYPE_ON_QUEUE_MOTION_INSTANCE, EVENT_TYPE_ON_DELETE_ACTOR, - EVENT_TYPE_ON_DELETE_ACTOR_INSTANCE, EVENT_TYPE_ON_SIMULATE_PHYSICS, EVENT_TYPE_ON_CUSTOM_EVENT, EVENT_TYPE_ON_DRAW_LINE, @@ -64,7 +63,6 @@ namespace EMotionFX EVENT_TYPE_ON_CREATE_MOTION_INSTANCE, EVENT_TYPE_ON_CREATE_MOTION_SYSTEM, EVENT_TYPE_ON_CREATE_ACTOR, - EVENT_TYPE_ON_CREATE_ACTOR_INSTANCE, EVENT_TYPE_ON_POST_CREATE_ACTOR, EVENT_TYPE_ON_DELETE_ANIM_GRAPH, EVENT_TYPE_ON_DELETE_ANIM_GRAPH_INSTANCE, @@ -298,15 +296,6 @@ namespace EMotionFX */ virtual void OnDeleteActor(Actor* actor) { MCORE_UNUSED(actor); } - /** - * The event that gets triggered once an ActorInstance object is being deleted. - * You could for example use this event to delete any allocations you have done inside the - * custom user data object linked with the ActorInstance object. - * You can get and set this data object with the ActorInstance::GetCustomData() and ActorInstance::SetCustomData(...) methods. - * @param actorInstance The actorInstance that is being deleted. - */ - virtual void OnDeleteActorInstance(ActorInstance* actorInstance) { MCORE_UNUSED(actorInstance); } - virtual void OnSimulatePhysics(float timeDelta) { MCORE_UNUSED(timeDelta); } virtual void OnCustomEvent(uint32 eventType, void* data) { MCORE_UNUSED(eventType); MCORE_UNUSED(data); } @@ -321,7 +310,6 @@ namespace EMotionFX virtual void OnCreateMotionInstance(MotionInstance* motionInstance) { MCORE_UNUSED(motionInstance); } virtual void OnCreateMotionSystem(MotionSystem* motionSystem) { MCORE_UNUSED(motionSystem); } virtual void OnCreateActor(Actor* actor) { MCORE_UNUSED(actor); } - virtual void OnCreateActorInstance(ActorInstance* actorInstance) { MCORE_UNUSED(actorInstance); } virtual void OnPostCreateActor(Actor* actor) { MCORE_UNUSED(actor); } // delete callbacks diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/EventManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/EventManager.cpp index bc9843c787..10c64b9433 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/EventManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/EventManager.cpp @@ -305,16 +305,6 @@ namespace EMotionFX } - void EventManager::OnDeleteActorInstance(ActorInstance* actorInstance) - { - const EventHandlerVector& eventHandlers = m_eventHandlersByEventType[EVENT_TYPE_ON_DELETE_ACTOR_INSTANCE]; - for (EventHandler* eventHandler : eventHandlers) - { - eventHandler->OnDeleteActorInstance(actorInstance); - } - } - - // draw a debug triangle void EventManager::OnDrawTriangle(const AZ::Vector3& posA, const AZ::Vector3& posB, const AZ::Vector3& posC, const AZ::Vector3& normalA, const AZ::Vector3& normalB, const AZ::Vector3& normalC, uint32 color) { @@ -670,17 +660,6 @@ namespace EMotionFX } - // create an actor instance - void EventManager::OnCreateActorInstance(ActorInstance* actorInstance) - { - const EventHandlerVector& eventHandlers = m_eventHandlersByEventType[EVENT_TYPE_ON_CREATE_ACTOR_INSTANCE]; - for (EventHandler* eventHandler : eventHandlers) - { - eventHandler->OnCreateActorInstance(actorInstance); - } - } - - // on post create actor void EventManager::OnPostCreateActor(Actor* actor) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/EventManager.h b/Gems/EMotionFX/Code/EMotionFX/Source/EventManager.h index 81767d5a66..f12d1de8cb 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/EventManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/EventManager.h @@ -286,15 +286,6 @@ namespace EMotionFX */ void OnDeleteActor(Actor* actor); - /** - * The event that gets triggered once an ActorInstance object is being deleted. - * You could for example use this event to delete any allocations you have done inside the - * custom user data object linked with the ActorInstance object. - * You can get and set this data object with the ActorInstance::GetCustomData() and ActorInstance::SetCustomData(...) methods. - * @param actorInstance The actorInstance that is being deleted. - */ - void OnDeleteActorInstance(ActorInstance* actorInstance); - void OnSimulatePhysics(float timeDelta); void OnCustomEvent(uint32 eventType, void* data); void OnDrawTriangle(const AZ::Vector3& posA, const AZ::Vector3& posB, const AZ::Vector3& posC, const AZ::Vector3& normalA, const AZ::Vector3& normalB, const AZ::Vector3& normalC, uint32 color); @@ -343,7 +334,6 @@ namespace EMotionFX void OnCreateMotionInstance(MotionInstance* motionInstance); void OnCreateMotionSystem(MotionSystem* motionSystem); void OnCreateActor(Actor* actor); - void OnCreateActorInstance(ActorInstance* actorInstance); void OnPostCreateActor(Actor* actor); // delete callbacks diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.cpp index d12970bc04..8670851334 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.cpp @@ -106,16 +106,12 @@ namespace EMotionFX mCurrentPlayTime = 0.0f; mObjects.SetMemoryCategory(EMFX_MEMCATEGORY_RECORDER); - - GetEMotionFX().GetEventManager()->AddEventHandler(this); + EMotionFX::ActorInstanceNotificationBus::Handler::BusConnect(); } Recorder::~Recorder() { - if (EventManager* eventManager = GetEMotionFX().GetEventManager()) - { - eventManager->RemoveEventHandler(this); - } + EMotionFX::ActorInstanceNotificationBus::Handler::BusDisconnect(); Clear(); } @@ -1448,7 +1444,7 @@ namespace EMotionFX Unlock(); } - void Recorder::OnDeleteActorInstance(ActorInstance* actorInstance) + void Recorder::OnActorInstanceDestroyed(EMotionFX::ActorInstance* actorInstance) { // Actor instances created by actor components do not use the command system and don't call a ClearRecorder command. // Thus, these actor instances will have to be removed from the recorder to avoid dangling data. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.h b/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.h index 157ef2c88b..33ab3ce35d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -47,7 +48,7 @@ namespace EMotionFX class EMFX_API Recorder : public BaseObject - , public EventHandler + , private EMotionFX::ActorInstanceNotificationBus::Handler { public: AZ_CLASS_ALLOCATOR_DECL @@ -319,9 +320,8 @@ namespace EMotionFX void RemoveActorInstanceFromRecording(ActorInstance* actorInstance); void RemoveAnimGraphFromRecording(AnimGraph* animGraph); - // EventHandler overrides - const AZStd::vector GetHandledEventTypes() const override { return {EMotionFX::EVENT_TYPE_ON_DELETE_ACTOR_INSTANCE}; } - void OnDeleteActorInstance(ActorInstance* actorInstance) override; + // ActorInstanceNotificationBus overrides + void OnActorInstanceDestroyed(EMotionFX::ActorInstance* actorInstance) override; void SampleAndApplyTransforms(float timeInSeconds, ActorInstance* actorInstance) const; void SampleAndApplyMainTransform(float timeInSeconds, ActorInstance* actorInstance) const; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetsWindowPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetsWindowPlugin.cpp index 80bbb24928..a0b018d999 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetsWindowPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetsWindowPlugin.cpp @@ -17,25 +17,26 @@ #include "../../../../EMStudioSDK/Source/EMStudioCore.h" #include #include +#include #include #include "../../../../EMStudioSDK/Source/EMStudioManager.h" - namespace EMStudio { - // constructor MorphTargetsWindowPlugin::MorphTargetsWindowPlugin() : EMStudio::DockWidgetPlugin() { - mDialogStack = nullptr; - mCurrentActorInstance = nullptr; + mDialogStack = nullptr; + mCurrentActorInstance = nullptr; mStaticTextWidget = nullptr; + + EMotionFX::ActorInstanceNotificationBus::Handler::BusConnect(); } - - // destructor MorphTargetsWindowPlugin::~MorphTargetsWindowPlugin() { + EMotionFX::ActorInstanceNotificationBus::Handler::BusDisconnect(); + // unregister the command callbacks and get rid of the memory for (auto callback : m_callbacks) { @@ -110,14 +111,16 @@ namespace EMStudio mMorphTargetGroups.clear(); } - // reinit the morph target dialog, e.g. if selection changes void MorphTargetsWindowPlugin::ReInit(bool forceReInit) { - // get the selected actorinstance - const CommandSystem::SelectionList& selection = GetCommandManager()->GetCurrentSelection(); - EMotionFX::ActorInstance* actorInstance = selection.GetSingleActorInstance(); + const CommandSystem::SelectionList& selection = GetCommandManager()->GetCurrentSelection(); + EMotionFX::ActorInstance* actorInstance = selection.GetSingleActorInstance(); + ReInit(actorInstance, forceReInit); + } + void MorphTargetsWindowPlugin::ReInit(EMotionFX::ActorInstance* actorInstance, bool forceReInit) + { // show hint if no/multiple actor instances is/are selected if (actorInstance == nullptr) { @@ -135,10 +138,7 @@ namespace EMStudio return; } - // get our selected actor instance and the corresponding actor - EMotionFX::Actor* actor = actorInstance->GetActor(); - - // only reinit the morph targets if actorinstance changed + // only reinit the morph targets if actor instance changed if (mCurrentActorInstance != actorInstance || forceReInit) { // set the current actor instance in any case @@ -150,7 +150,7 @@ namespace EMStudio AZStd::vector phonemeInstances; AZStd::vector defaultMorphTargetInstances; - // get the morph target setup + EMotionFX::Actor* actor = actorInstance->GetActor(); EMotionFX::MorphSetup* morphSetup = actor->GetMorphSetup(actorInstance->GetLODLevel()); if (morphSetup == nullptr) { @@ -278,6 +278,13 @@ namespace EMStudio } } + void MorphTargetsWindowPlugin::OnActorInstanceDestroyed(EMotionFX::ActorInstance* actorInstance) + { + if (mCurrentActorInstance == actorInstance) + { + ReInit(/*actorInstance=*/nullptr); + } + } //----------------------------------------------------------------------------------------- // Command callbacks diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetsWindowPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetsWindowPlugin.h index ec64af2789..1f5abba310 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetsWindowPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetsWindowPlugin.h @@ -16,6 +16,7 @@ #include #include "../../../../EMStudioSDK/Source/DockWidgetPlugin.h" #include +#include #include "MorphTargetGroupWidget.h" #include #include @@ -26,6 +27,7 @@ namespace EMStudio { class MorphTargetsWindowPlugin : public EMStudio::DockWidgetPlugin + , private EMotionFX::ActorInstanceNotificationBus::Handler { Q_OBJECT MCORE_MEMORYOBJECTCATEGORY(MorphTargetsWindowPlugin, MCore::MCORE_DEFAULT_ALIGNMENT, MEMCATEGORY_STANDARDPLUGINS); @@ -54,6 +56,7 @@ namespace EMStudio EMStudioPlugin* Clone() override; // update the morph targets window based on the current selection + void ReInit(EMotionFX::ActorInstance* actorInstance, bool forceReInit = false); void ReInit(bool forceReInit = false); // clear all widgets from the window @@ -70,6 +73,9 @@ namespace EMStudio void WindowReInit(bool visible); private: + // ActorInstanceNotificationBus overrides + void OnActorInstanceDestroyed(EMotionFX::ActorInstance* actorInstance) override; + // declare the callbacks MCORE_DEFINECOMMANDCALLBACK(CommandSelectCallback); MCORE_DEFINECOMMANDCALLBACK(CommandUnselectCallback); diff --git a/Gems/EMotionFX/Code/EMotionFX/emotionfx_files.cmake b/Gems/EMotionFX/Code/EMotionFX/emotionfx_files.cmake index 9f5fe617d4..9743ab5f15 100644 --- a/Gems/EMotionFX/Code/EMotionFX/emotionfx_files.cmake +++ b/Gems/EMotionFX/Code/EMotionFX/emotionfx_files.cmake @@ -15,6 +15,7 @@ set(FILES Source/ActorBus.h Source/ActorInstance.cpp Source/ActorInstance.h + Source/ActorInstanceBus.h Source/ActorManager.cpp Source/ActorManager.h Source/ActorUpdateScheduler.h From 73d5617af354fe8dd18ea044c374645082041f9b Mon Sep 17 00:00:00 2001 From: Yuriy Toporovskyy Date: Mon, 14 Jun 2021 10:02:49 -0400 Subject: [PATCH 077/116] Full screen game preview for Atom viewport --- Code/Sandbox/Editor/CryEdit.cpp | 5 + Code/Sandbox/Editor/EditorViewportWidget.cpp | 144 +++++++++++++++++++ Code/Sandbox/Editor/EditorViewportWidget.h | 5 + Code/Sandbox/Editor/MainWindow.cpp | 16 ++- Code/Sandbox/Editor/Resource.h | 1 + Code/Sandbox/Editor/Settings.cpp | 6 + Code/Sandbox/Editor/ToolbarManager.cpp | 1 + 7 files changed, 174 insertions(+), 4 deletions(-) diff --git a/Code/Sandbox/Editor/CryEdit.cpp b/Code/Sandbox/Editor/CryEdit.cpp index 955a299172..815f986e1a 100644 --- a/Code/Sandbox/Editor/CryEdit.cpp +++ b/Code/Sandbox/Editor/CryEdit.cpp @@ -376,6 +376,11 @@ void CCryEditApp::RegisterActionHandlers() ON_COMMAND(ID_EDIT_FETCH, OnEditFetch) ON_COMMAND(ID_FILE_EXPORTTOGAMENOSURFACETEXTURE, OnFileExportToGameNoSurfaceTexture) ON_COMMAND(ID_VIEW_SWITCHTOGAME, OnViewSwitchToGame) + MainWindow::instance()->GetActionManager()->RegisterActionHandler(ID_VIEW_SWITCHTOGAME_FULLSCREEN, [this]() { + auto fs = gEnv->pConsole->GetCVar("ed_previewGameInFullscreen_once"); + fs->Set(1); + OnViewSwitchToGame(); + }); ON_COMMAND(ID_MOVE_OBJECT, OnMoveObject) ON_COMMAND(ID_RENAME_OBJ, OnRenameObj) ON_COMMAND(ID_EDITMODE_MOVE, OnEditmodeMove) diff --git a/Code/Sandbox/Editor/EditorViewportWidget.cpp b/Code/Sandbox/Editor/EditorViewportWidget.cpp index 5a444f0521..10a680c00c 100644 --- a/Code/Sandbox/Editor/EditorViewportWidget.cpp +++ b/Code/Sandbox/Editor/EditorViewportWidget.cpp @@ -82,6 +82,8 @@ #include "AnimationContext.h" #include "Objects/SelectionGroup.h" #include "Core/QtEditorApplication.h" +#include "MainWindow.h" +#include "LayoutWnd.h" // ComponentEntityEditorPlugin #include @@ -694,6 +696,11 @@ void EditorViewportWidget::OnEditorNotifyEvent(EEditorNotifyEvent event) } } SetCurrentCursor(STD_CURSOR_GAME); + + if (ShouldPreviewFullscreen()) + { + StartFullscreenPreview(); + } } if (m_renderViewport) @@ -712,6 +719,11 @@ void EditorViewportWidget::OnEditorNotifyEvent(EEditorNotifyEvent event) m_bInOrbitMode = false; m_bInZoomMode = false; + if (m_inFullscreenPreview) + { + StopFullscreenPreview(); + } + RestoreViewportAfterGameMode(); } @@ -1368,11 +1380,30 @@ void EditorViewportWidget::SetViewportId(int id) { CViewport::SetViewportId(id); + // First delete any existing layout + // This also deletes any existing render viewport widget (since it will be added to the layout + if (QLayout* l = layout()) + { + QLayoutItem* item; + while ((item = l->takeAt(0)) != 0) + { + if (QWidget* w = item->widget()) + { + delete w; + } + l->removeItem(item); + delete item; + } + delete l; + } + // Now that we have an ID, we can initialize our viewport. m_renderViewport = new AtomToolsFramework::RenderViewportWidget(this, false); if (!m_renderViewport->InitializeViewportContext(id)) { AZ_Warning("EditorViewportWidget", false, "Failed to initialize RenderViewportWidget's ViewportContext"); + delete m_renderViewport; + m_renderViewport = nullptr; return; } auto viewportContext = m_renderViewport->GetViewportContext(); @@ -3027,4 +3058,117 @@ float EditorViewportSettings::AngleStep() const return SandboxEditor::AngleSnappingSize(); } +bool EditorViewportWidget::ShouldPreviewFullscreen() +{ + CLayoutWnd* layout = GetIEditor()->GetViewManager()->GetLayout(); + if (!layout) + { + AZ_Assert(false, "CRenderViewport: No View Manager layout"); + return false; + } + + // Doesn't work with split layout (TODO: figure out why and make it work) + if (layout->GetLayout() != EViewLayout::ET_Layout0) { return false; } + + // Not supported in VR + if (gSettings.bEnableGameModeVR) { return false; } + + // If level not loaded, don't preview in fullscreen (preview shouldn't work at all without a level, but it does) + if (auto ge = GetIEditor()->GetGameEngine()) + { + if (!ge->IsLevelLoaded()) { return false; } + } + + // Check 'ed_previewGameInFullscreen_once' and 'ed_previewGameInFullscreen' cvars + if (gEnv->pConsole) + { + if (auto v = gEnv->pConsole->GetCVar("ed_previewGameInFullscreen_once")) + { + if (v->GetIVal() != 0) + { + v->Set(0); + return true; + } + } + + { + auto v = gEnv->pConsole->GetCVar("ed_previewGameInFullscreen"); + return v && v->GetIVal() != 0; // if it doesn't exist, assume its value is 0 + } + + return true; + } + else + { + return false; + } +} + +void EditorViewportWidget::StartFullscreenPreview() +{ + AZ_Assert(!m_inFullscreenPreview, AZ_FUNCTION_SIGNATURE " - called when already in full screen preview"); + m_inFullscreenPreview = true; + + QScreen* screen = QGuiApplication::primaryScreen(); + QRect screenGeometry = screen->geometry(); + + // Unparent this and show it, which turns it into a free floating window + // Also set style to frameless and disable resizing by user + setParent(nullptr); + setWindowFlag(Qt::FramelessWindowHint, true); + setWindowFlag(Qt::MSWindowsFixedSizeDialogHint, true); + setFixedSize(screenGeometry.size()); + move(QPoint(screenGeometry.x(), screenGeometry.y())); + showMaximized(); + + // Hide the main window + MainWindow::instance()->hide(); +} + +void EditorViewportWidget::StopFullscreenPreview() +{ + AZ_Assert(m_inFullscreenPreview, AZ_FUNCTION_SIGNATURE " - called when not in full screen preview"); + m_inFullscreenPreview = false; + + // Unset frameless window flags + setWindowFlag(Qt::FramelessWindowHint, false); + setWindowFlag(Qt::MSWindowsFixedSizeDialogHint, false); + + // Unset fixed size (note that 50x50 is the minimum set in the constructor) + setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); + setMinimumSize(50, 50); + + // Attach this viewport to the primary view pane (whose index is 0). + if (CLayoutWnd* layout = GetIEditor()->GetViewManager()->GetLayout()) + { + if (CLayoutViewPane* viewPane = layout->GetViewPaneByIndex(0)) + { + // Force-reattach this viewport to its view pane by first detaching + viewPane->DetachViewport(); + viewPane->AttachViewport(this); + + // Set the main widget of the layout, which causes this widgets size to be bound to the layout + // and the viewport title bar to be displayed + layout->SetMainWidget(viewPane); + } + else + { + AZ_Assert(false, "CRenderViewport: No view pane with ID 0 (primary view pane)"); + } + } + else + { + AZ_Assert(false, "CRenderViewport: No View Manager layout"); + } + + // Set this as the selected viewport + GetIEditor()->GetViewManager()->SelectViewport(this); + + // Show this widget (setting flags may hide it) + showNormal(); + + // Show the main window + MainWindow::instance()->show(); +} + #include diff --git a/Code/Sandbox/Editor/EditorViewportWidget.h b/Code/Sandbox/Editor/EditorViewportWidget.h index 6b2db65847..53c96011b1 100644 --- a/Code/Sandbox/Editor/EditorViewportWidget.h +++ b/Code/Sandbox/Editor/EditorViewportWidget.h @@ -385,6 +385,11 @@ protected: }; void ResetToViewSourceType(const ViewSourceType& viewSourType); + bool ShouldPreviewFullscreen(); + void StartFullscreenPreview(); + void StopFullscreenPreview(); + + bool m_inFullscreenPreview = false; bool m_bRenderContextCreated = false; bool m_bInRotateMode = false; bool m_bInMoveMode = false; diff --git a/Code/Sandbox/Editor/MainWindow.cpp b/Code/Sandbox/Editor/MainWindow.cpp index ddc8ff5058..4b0b0e104a 100644 --- a/Code/Sandbox/Editor/MainWindow.cpp +++ b/Code/Sandbox/Editor/MainWindow.cpp @@ -949,6 +949,12 @@ void MainWindow::InitActions() .SetApplyHoverEffect() .SetCheckable(true) .RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdatePlayGame); + am->AddAction(ID_VIEW_SWITCHTOGAME_FULLSCREEN, tr("Play &Game (Maximized)")) + .SetShortcut(tr("Ctrl+Shift+G")) + .SetStatusTip(tr("Activate the game input mode (maximized)")) + .SetIcon(Style::icon("Play")) + .SetApplyHoverEffect() + .SetCheckable(true); am->AddAction(ID_TOOLBAR_WIDGET_PLAYCONSOLE_LABEL, tr("Play Controls")) .SetText(tr("Play Controls")); am->AddAction(ID_SWITCH_PHYSICS, tr("Simulate")) @@ -1266,10 +1272,12 @@ void MainWindow::OnGameModeChanged(bool inGameMode) { menuBar()->setDisabled(inGameMode); m_toolbarManager->SetEnabled(!inGameMode); - QAction* action = m_actionManager->GetAction(ID_VIEW_SWITCHTOGAME); - action->blockSignals(true); // avoid a loop - action->setChecked(inGameMode); - action->blockSignals(false); + + // avoid a loop + AZStd::vector actions = { m_actionManager->GetAction(ID_VIEW_SWITCHTOGAME), m_actionManager->GetAction(ID_VIEW_SWITCHTOGAME_FULLSCREEN) }; + for (auto action : actions) action->blockSignals(true); + for (auto action : actions) action->setChecked(inGameMode); + for (auto action : actions) action->blockSignals(false); } void MainWindow::OnEditorNotifyEvent(EEditorNotifyEvent ev) diff --git a/Code/Sandbox/Editor/Resource.h b/Code/Sandbox/Editor/Resource.h index bd6ae94184..8ef6c0b906 100644 --- a/Code/Sandbox/Editor/Resource.h +++ b/Code/Sandbox/Editor/Resource.h @@ -111,6 +111,7 @@ #define ID_EDIT_FETCH 33465 #define ID_FILE_EXPORTTOGAMENOSURFACETEXTURE 33473 #define ID_VIEW_SWITCHTOGAME 33477 +#define ID_VIEW_SWITCHTOGAME_FULLSCREEN 33478 #define ID_EDIT_DELETE 33480 #define ID_MOVE_OBJECT 33481 #define ID_RENAME_OBJ 33483 diff --git a/Code/Sandbox/Editor/Settings.cpp b/Code/Sandbox/Editor/Settings.cpp index 15d3e793a5..66271a9967 100644 --- a/Code/Sandbox/Editor/Settings.cpp +++ b/Code/Sandbox/Editor/Settings.cpp @@ -947,6 +947,12 @@ void SEditorSettings::PostInitApply() REGISTER_CVAR2_CB("ed_keepEditorActive", &keepEditorActive, 0, VF_NULL, "Keep the editor active, even if no focus is set", KeepEditorActiveChanged); REGISTER_CVAR2("g_TemporaryLevelName", &g_TemporaryLevelName, "temp_level", VF_NULL, "Temporary level named used for experimental levels."); + REGISTER_INT("ed_previewGameInFullscreen", 0, VF_DEV_ONLY, "Preview the game (Ctrl+G, \"Play Game\", etc.) in fullscreen. 0 = no, 1 = yes"); + gEnv->pConsole->GetCVar("ed_previewGameInFullscreen")->SetLimits(0, 1); + + REGISTER_INT("ed_previewGameInFullscreen_once", 0, VF_DEV_ONLY | VF_INVISIBLE, "Preview the game (Ctrl+G, \"Play Game\", etc.) in fullscreen once. 0 = no, 1 = yes"); + gEnv->pConsole->GetCVar("ed_previewGameInFullscreen_once")->SetLimits(0, 1); + CCryEditApp::instance()->KeepEditorActive(keepEditorActive > 0); } diff --git a/Code/Sandbox/Editor/ToolbarManager.cpp b/Code/Sandbox/Editor/ToolbarManager.cpp index 137057a4fa..0c68797b6a 100644 --- a/Code/Sandbox/Editor/ToolbarManager.cpp +++ b/Code/Sandbox/Editor/ToolbarManager.cpp @@ -603,6 +603,7 @@ AmazonToolbar ToolbarManager::GetPlayConsoleToolbar() const t.AddAction(ID_TOOLBAR_SEPARATOR, ORIGINAL_TOOLBAR_VERSION); t.AddAction(ID_TOOLBAR_WIDGET_PLAYCONSOLE_LABEL, ORIGINAL_TOOLBAR_VERSION); t.AddAction(ID_VIEW_SWITCHTOGAME, TOOLBARS_WITH_PLAY_GAME); + t.AddAction(ID_VIEW_SWITCHTOGAME_FULLSCREEN, TOOLBARS_WITH_PLAY_GAME); t.AddAction(ID_TOOLBAR_SEPARATOR, ORIGINAL_TOOLBAR_VERSION); t.AddAction(ID_SWITCH_PHYSICS, TOOLBARS_WITH_PLAY_GAME); return t; From f8cf4ba08767ecb02b82b49b48786cf803fd1a0e Mon Sep 17 00:00:00 2001 From: Benjamin Jillich <43751992+amzn-jillich@users.noreply.github.com> Date: Mon, 14 Jun 2021 17:34:29 +0200 Subject: [PATCH 078/116] [LYN-3416] Animation: Attachment component does not update it's location automatically (#1305) --- .../Code/Source/Animation/EditorAttachmentComponent.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/EditorAttachmentComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/EditorAttachmentComponent.cpp index f14340b4c9..e7f2a98a71 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/EditorAttachmentComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/EditorAttachmentComponent.cpp @@ -118,8 +118,7 @@ namespace AZ void EditorAttachmentComponent::Activate() { Base::Activate(); - m_boneFollower.Activate(GetEntity(), CreateAttachmentConfiguration(), - false); // Entity's don't animate in Editor + m_boneFollower.Activate(GetEntity(), CreateAttachmentConfiguration(), /*targetCanAnimate=*/true); } void EditorAttachmentComponent::Deactivate() From 074c3107cd08560fcae41c8e308e748335dbddc6 Mon Sep 17 00:00:00 2001 From: Yuriy Toporovskyy Date: Mon, 14 Jun 2021 11:54:11 -0400 Subject: [PATCH 079/116] Expose protected method required by full screen preview feature --- Code/Sandbox/Editor/LayoutWnd.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Code/Sandbox/Editor/LayoutWnd.h b/Code/Sandbox/Editor/LayoutWnd.h index 2af56f907c..66c9a9e889 100644 --- a/Code/Sandbox/Editor/LayoutWnd.h +++ b/Code/Sandbox/Editor/LayoutWnd.h @@ -113,6 +113,8 @@ public: //! Switch 2D viewports. void Cycle2DViewport(); + using AzQtComponents::ToolBarArea::SetMainWidget; + public slots: void ResetLayout(); From 37f70fb47cd9f5badb17022955473916cbe66160 Mon Sep 17 00:00:00 2001 From: Yuriy Toporovskyy Date: Mon, 14 Jun 2021 12:08:43 -0400 Subject: [PATCH 080/116] Address some PR feedback. - Better variable names - Close a parenthesis in a comment - Check equality against nullptr instead of 0 - Add comment to document method of clearing a QLayout - Format some things - Const correctness - Remove a TODO in a comment - Attempt at removing concatenation of string literal AZ_FUNCTION_SIGNATURE, which might not be a literal on every compiler/platform --- Code/Sandbox/Editor/EditorViewportWidget.cpp | 44 ++++++++++++-------- Code/Sandbox/Editor/EditorViewportWidget.h | 2 +- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/Code/Sandbox/Editor/EditorViewportWidget.cpp b/Code/Sandbox/Editor/EditorViewportWidget.cpp index 10a680c00c..ba181aa99b 100644 --- a/Code/Sandbox/Editor/EditorViewportWidget.cpp +++ b/Code/Sandbox/Editor/EditorViewportWidget.cpp @@ -1381,20 +1381,21 @@ void EditorViewportWidget::SetViewportId(int id) CViewport::SetViewportId(id); // First delete any existing layout - // This also deletes any existing render viewport widget (since it will be added to the layout - if (QLayout* l = layout()) + // This also deletes any existing render viewport widget (since it will be added to the layout) + // Below is the typical method of clearing a QLayout, see e.g. https://doc.qt.io/qt-5/qlayout.html#takeAt + if (QLayout* thisLayout = layout()) { QLayoutItem* item; - while ((item = l->takeAt(0)) != 0) + while ((item = thisLayout->takeAt(0)) != nullptr) { - if (QWidget* w = item->widget()) + if (QWidget* widget = item->widget()) { - delete w; + delete widget; } - l->removeItem(item); + thisLayout->removeItem(item); delete item; } - delete l; + delete thisLayout; } // Now that we have an ID, we can initialize our viewport. @@ -3058,7 +3059,7 @@ float EditorViewportSettings::AngleStep() const return SandboxEditor::AngleSnappingSize(); } -bool EditorViewportWidget::ShouldPreviewFullscreen() +bool EditorViewportWidget::ShouldPreviewFullscreen() const { CLayoutWnd* layout = GetIEditor()->GetViewManager()->GetLayout(); if (!layout) @@ -3067,16 +3068,25 @@ bool EditorViewportWidget::ShouldPreviewFullscreen() return false; } - // Doesn't work with split layout (TODO: figure out why and make it work) - if (layout->GetLayout() != EViewLayout::ET_Layout0) { return false; } + // Doesn't work with split layout + if (layout->GetLayout() != EViewLayout::ET_Layout0) + { + return false; + } // Not supported in VR - if (gSettings.bEnableGameModeVR) { return false; } + if (gSettings.bEnableGameModeVR) + { + return false; + } // If level not loaded, don't preview in fullscreen (preview shouldn't work at all without a level, but it does) if (auto ge = GetIEditor()->GetGameEngine()) { - if (!ge->IsLevelLoaded()) { return false; } + if (!ge->IsLevelLoaded()) + { + return false; + } } // Check 'ed_previewGameInFullscreen_once' and 'ed_previewGameInFullscreen' cvars @@ -3106,11 +3116,11 @@ bool EditorViewportWidget::ShouldPreviewFullscreen() void EditorViewportWidget::StartFullscreenPreview() { - AZ_Assert(!m_inFullscreenPreview, AZ_FUNCTION_SIGNATURE " - called when already in full screen preview"); + AZ_Assert(!m_inFullscreenPreview, "EditorViewportWidget::StartFullscreenPreview called when already in full screen preview"); m_inFullscreenPreview = true; - QScreen* screen = QGuiApplication::primaryScreen(); - QRect screenGeometry = screen->geometry(); + const QScreen* screen = QGuiApplication::primaryScreen(); + const QRect screenGeometry = screen->geometry(); // Unparent this and show it, which turns it into a free floating window // Also set style to frameless and disable resizing by user @@ -3121,13 +3131,13 @@ void EditorViewportWidget::StartFullscreenPreview() move(QPoint(screenGeometry.x(), screenGeometry.y())); showMaximized(); - // Hide the main window + // This must be done after unparenting this widget above MainWindow::instance()->hide(); } void EditorViewportWidget::StopFullscreenPreview() { - AZ_Assert(m_inFullscreenPreview, AZ_FUNCTION_SIGNATURE " - called when not in full screen preview"); + AZ_Assert(m_inFullscreenPreview, "EditorViewportWidget::StartFullscreenPreview called when not in full screen preview"); m_inFullscreenPreview = false; // Unset frameless window flags diff --git a/Code/Sandbox/Editor/EditorViewportWidget.h b/Code/Sandbox/Editor/EditorViewportWidget.h index 53c96011b1..511a7910c6 100644 --- a/Code/Sandbox/Editor/EditorViewportWidget.h +++ b/Code/Sandbox/Editor/EditorViewportWidget.h @@ -385,7 +385,7 @@ protected: }; void ResetToViewSourceType(const ViewSourceType& viewSourType); - bool ShouldPreviewFullscreen(); + bool ShouldPreviewFullscreen() const; void StartFullscreenPreview(); void StopFullscreenPreview(); From 5becf25a79d194286169d5f83d17d2d411731f32 Mon Sep 17 00:00:00 2001 From: Yuriy Toporovskyy Date: Mon, 14 Jun 2021 12:14:58 -0400 Subject: [PATCH 081/116] Address some PR feedback. - Better comment explaining signal blocking - Clang format --- Code/Sandbox/Editor/MainWindow.cpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/Code/Sandbox/Editor/MainWindow.cpp b/Code/Sandbox/Editor/MainWindow.cpp index 4b0b0e104a..1ad97f31de 100644 --- a/Code/Sandbox/Editor/MainWindow.cpp +++ b/Code/Sandbox/Editor/MainWindow.cpp @@ -1273,11 +1273,24 @@ void MainWindow::OnGameModeChanged(bool inGameMode) menuBar()->setDisabled(inGameMode); m_toolbarManager->SetEnabled(!inGameMode); - // avoid a loop + // block signals on the switch to game actions before setting the checked state, as + // setting the checked state triggers the action, which will re-enter this function + // and result in an infinite loop AZStd::vector actions = { m_actionManager->GetAction(ID_VIEW_SWITCHTOGAME), m_actionManager->GetAction(ID_VIEW_SWITCHTOGAME_FULLSCREEN) }; - for (auto action : actions) action->blockSignals(true); - for (auto action : actions) action->setChecked(inGameMode); - for (auto action : actions) action->blockSignals(false); + for (auto action : actions) + { + action->blockSignals(true); + } + + for (auto action : actions) + { + action->setChecked(inGameMode); + } + + for (auto action : actions) + { + action->blockSignals(false); + } } void MainWindow::OnEditorNotifyEvent(EEditorNotifyEvent ev) From 7ef292d2102a3212d0150d8ed1e9aaaa7b2bf60b Mon Sep 17 00:00:00 2001 From: Doug McDiarmid Date: Mon, 14 Jun 2021 10:27:03 -0700 Subject: [PATCH 082/116] Removed VK_KHR_ray_query extension requirement for enabling ray tracing --- .../RHI/Vulkan/External/glad/2.0.0-beta/include/glad/vulkan.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Gems/Atom/RHI/Vulkan/External/glad/2.0.0-beta/include/glad/vulkan.h b/Gems/Atom/RHI/Vulkan/External/glad/2.0.0-beta/include/glad/vulkan.h index a6ee9e8634..33d4b64082 100644 --- a/Gems/Atom/RHI/Vulkan/External/glad/2.0.0-beta/include/glad/vulkan.h +++ b/Gems/Atom/RHI/Vulkan/External/glad/2.0.0-beta/include/glad/vulkan.h @@ -12691,8 +12691,7 @@ static int glad_vk_find_extensions_vulkan( VkPhysicalDevice physical_device) { #endif GLAD_VK_KHR_push_descriptor = glad_vk_has_extension("VK_KHR_push_descriptor", extension_count, extensions); GLAD_VK_KHR_ray_tracing = (glad_vk_has_extension("VK_KHR_acceleration_structure", extension_count, extensions) - && glad_vk_has_extension("VK_KHR_ray_tracing_pipeline", extension_count, extensions) - && glad_vk_has_extension("VK_KHR_ray_query", extension_count, extensions)); + && glad_vk_has_extension("VK_KHR_ray_tracing_pipeline", extension_count, extensions)); GLAD_VK_KHR_relaxed_block_layout = glad_vk_has_extension("VK_KHR_relaxed_block_layout", extension_count, extensions); GLAD_VK_KHR_sampler_mirror_clamp_to_edge = glad_vk_has_extension("VK_KHR_sampler_mirror_clamp_to_edge", extension_count, extensions); GLAD_VK_KHR_sampler_ycbcr_conversion = glad_vk_has_extension("VK_KHR_sampler_ycbcr_conversion", extension_count, extensions); From b31de1da3304067149ac309acb63d280744953c3 Mon Sep 17 00:00:00 2001 From: jckand-amzn Date: Mon, 14 Jun 2021 13:46:53 -0500 Subject: [PATCH 083/116] LYN-4518: Updating expected actions for test_Menus_ViewMenuOptions_Work --- .../PythonTests/editor/EditorScripts/Menus_ViewMenuOptions.py | 2 +- AutomatedTesting/Gem/PythonTests/editor/test_Menus.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_ViewMenuOptions.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_ViewMenuOptions.py index 173d658b3c..3f94a23696 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_ViewMenuOptions.py +++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_ViewMenuOptions.py @@ -49,7 +49,7 @@ class TestViewMenuOptions(EditorTestHelper): view_menu_options = [ ("Center on Selection",), ("Show Quick Access Bar",), - ("Viewport", "Wireframe"), + ("Viewport", "Configure Layout"), ("Viewport", "Go to Position"), ("Viewport", "Center on Selection"), ("Viewport", "Go to Location"), diff --git a/AutomatedTesting/Gem/PythonTests/editor/test_Menus.py b/AutomatedTesting/Gem/PythonTests/editor/test_Menus.py index 2b3fdcbdf3..26231e33d7 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/test_Menus.py +++ b/AutomatedTesting/Gem/PythonTests/editor/test_Menus.py @@ -89,7 +89,7 @@ class TestMenus(object): expected_lines = [ "Center on Selection Action triggered", "Show Quick Access Bar Action triggered", - "Wireframe Action triggered", + "Configure Layout Action triggered", "Go to Position Action triggered", "Center on Selection Action triggered", "Go to Location Action triggered", From 6f61454be4fbe3bd9b32c16773ec50b41c9e9911 Mon Sep 17 00:00:00 2001 From: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> Date: Mon, 14 Jun 2021 14:20:39 -0500 Subject: [PATCH 084/116] Added support for remapping entity refs across slice instances (#1284) * Fixed memory assert on shutdown. Cleaned up the entity pointers on serialization, so that they no longer leak themselves, their asset references, or anything else within them. * Added support for remapping entity refs across slice instances. Slice instances can have components with entity references that have been modified to reference entities in other slice instances, or even in the parent. This change detects and remaps those references so that they work correctly. --- .../SerializeContextTools/SliceConverter.cpp | 192 ++++++++++++++---- .../SerializeContextTools/SliceConverter.h | 46 +++-- 2 files changed, 185 insertions(+), 53 deletions(-) diff --git a/Code/Tools/SerializeContextTools/SliceConverter.cpp b/Code/Tools/SerializeContextTools/SliceConverter.cpp index 9fba060960..e7dc49d5b3 100644 --- a/Code/Tools/SerializeContextTools/SliceConverter.cpp +++ b/Code/Tools/SerializeContextTools/SliceConverter.cpp @@ -177,9 +177,10 @@ namespace AZ AZ::Entity* rootEntity = reinterpret_cast(classPtr); bool convertResult = ConvertSliceToPrefab(context, outputPath, isDryRun, rootEntity); - // Clear out the references to any nested slices so that the nested assets get unloaded correctly at the end of - // the conversion. - ClearSliceAssetReferences(rootEntity); + + // Delete the root entity pointer. Otherwise, it will leak itself along with all of the slice asset references held + // within it. + delete rootEntity; return convertResult; }; @@ -229,8 +230,12 @@ namespace AZ return false; } - // Get all of the entities from the slice. + // Get all of the entities from the slice. We're taking ownership of them, so we also remove them from the slice component + // without deleting them. + constexpr bool deleteEntities = false; + constexpr bool removeEmptyInstances = true; SliceComponent::EntityList sliceEntities = sliceComponent->GetNewEntities(); + sliceComponent->RemoveAllEntities(deleteEntities, removeEmptyInstances); AZ_Printf("Convert-Slice", " Slice contains %zu entities.\n", sliceEntities.size()); // Create the Prefab with the entities from the slice. @@ -273,6 +278,12 @@ namespace AZ } } + // Save off a mapping of the slice's metadata entity ID as well, even though we never converted the entity itself. + // This will help us better detect entity ID mapping errors for nested slice instances. + AZ::Entity* metadataEntity = sliceComponent->GetMetadataEntity(); + constexpr bool isMetadataEntity = true; + m_aliasIdMapper.emplace(metadataEntity->GetId(), SliceEntityMappingInfo(templateId, "MetadataEntity", isMetadataEntity)); + // Update the prefab template with the fixed-up data in our prefab instance. AzToolsFramework::Prefab::PrefabDom prefabDom; bool storeResult = AzToolsFramework::Prefab::PrefabDomUtils::StoreInstanceInPrefabDom(*sourceInstance, prefabDom); @@ -402,6 +413,21 @@ namespace AZ "Convert-Slice", " Attaching %zu instances of nested slice '%s'.\n", instances.size(), nestedPrefabPath.Native().c_str()); + // Before processing any further, save off all the known entity IDs from all the instances and how they map back to + // the base nested prefab that they've come from (i.e. this one). As we proceed up the chain of nesting, this will + // build out a hierarchical list of owning instances for each entity that we can trace upwards to know where to add + // the entity into our nested prefab instance. + // This step needs to occur *before* converting the instances themselves, because while converting instances, they + // might have entity ID references that point to other instances. By having the full instance entity ID map in place + // before conversion, we'll be able to fix them up appropriately. + + for (auto& instance : instances) + { + AZStd::string instanceAlias = GetInstanceAlias(instance); + UpdateSliceEntityInstanceMappings(instance.GetEntityIdToBaseMap(), instanceAlias); + } + + // Now that we have all the entity ID mappings, convert all the instances. for (auto& instance : instances) { bool instanceConvertResult = ConvertSliceInstance(instance, sliceAsset, nestedTemplate, sourceInstance); @@ -415,6 +441,28 @@ namespace AZ return true; } + AZStd::string SliceConverter::GetInstanceAlias(const AZ::SliceComponent::SliceInstance& instance) + { + // When creating the new instance, we would like to have deterministic instance aliases. Prefabs that depend on this one + // will have patches that reference the alias, so if we reconvert this slice a second time, we would like it to produce + // the same results. To get a deterministic and unique alias, we rely on the slice instance. The slice instance contains + // a map of slice entity IDs to unique instance entity IDs. We'll just consistently use the first entry in the map as the + // unique instance ID. + AZStd::string instanceAlias; + auto entityIdMap = instance.GetEntityIdMap(); + if (!entityIdMap.empty()) + { + instanceAlias = AZStd::string::format("Instance_%s", entityIdMap.begin()->second.ToString().c_str()); + } + else + { + AZ_Error("Convert-Slice", false, " Couldn't create deterministic instance alias."); + instanceAlias = AZStd::string::format("Instance_%s", AZ::Entity::MakeId().ToString().c_str()); + } + return instanceAlias; + } + + bool SliceConverter::ConvertSliceInstance( AZ::SliceComponent::SliceInstance& instance, AZ::Data::Asset& sliceAsset, @@ -438,27 +486,7 @@ namespace AZ auto instanceToTemplateInterface = AZ::Interface::Get(); auto prefabSystemComponentInterface = AZ::Interface::Get(); - // When creating the new instance, we would like to have deterministic instance aliases. Prefabs that depend on this one - // will have patches that reference the alias, so if we reconvert this slice a second time, we would like it to produce - // the same results. To get a deterministic and unique alias, we rely on the slice instance. The slice instance contains - // a map of slice entity IDs to unique instance entity IDs. We'll just consistently use the first entry in the map as the - // unique instance ID. - AZStd::string instanceAlias; - auto entityIdMap = instance.GetEntityIdMap(); - if (!entityIdMap.empty()) - { - instanceAlias = AZStd::string::format("Instance_%s", entityIdMap.begin()->second.ToString().c_str()); - } - else - { - instanceAlias = AZStd::string::format("Instance_%s", AZ::Entity::MakeId().ToString().c_str()); - } - - // Before processing any further, save off all the known entity IDs from this instance and how they map back to the base - // nested prefab that they've come from (i.e. this one). As we proceed up the chain of nesting, this will build out a - // hierarchical list of owning instances for each entity that we can trace upwards to know where to add the entity into - // our nested prefab instance. - UpdateSliceEntityInstanceMappings(instance.GetEntityIdToBaseMap(), instanceAlias); + AZStd::string instanceAlias = GetInstanceAlias(instance); // Create a new unmodified prefab Instance for the nested slice instance. auto nestedInstance = AZStd::make_unique(); @@ -619,6 +647,10 @@ namespace AZ SetParentEntity(containerEntity->get(), topLevelInstance->GetContainerEntityId(), onlySetIfInvalid); } + // After doing all of the above, run through entity references in any of the patched entities, and fix up the entity IDs to + // match the new ones in our prefabs. + RemapIdReferences(m_aliasIdMapper, topLevelInstance, nestedInstance.get(), instantiated, dependentSlice->GetSerializeContext()); + // Add the nested instance itself to the top-level prefab. To do this, we need to add it to our top-level instance, // create a patch out of it, and patch the top-level prefab template. @@ -750,17 +782,6 @@ namespace AZ AZ_Error("Convert-Slice", disconnected, "Asset Processor failed to disconnect successfully."); } - void SliceConverter::ClearSliceAssetReferences(AZ::Entity* rootEntity) - { - SliceComponent* sliceComponent = AZ::EntityUtils::FindFirstDerivedComponent(rootEntity); - // Make a copy of the slice list and remove all of them from the loaded component. - AZ::SliceComponent::SliceList slices = sliceComponent->GetSlices(); - for (auto& slice : slices) - { - sliceComponent->RemoveSlice(&slice); - } - } - void SliceConverter::UpdateSliceEntityInstanceMappings( const AZ::SliceComponent::EntityIdToEntityIdMap& sliceEntityIdMap, const AZStd::string& currentInstanceAlias) { @@ -789,9 +810,108 @@ namespace AZ AZ_Assert(oldId == newId, "The same entity instance ID has unexpectedly appeared twice in the same nested prefab."); } } + else + { + AZ_Warning("Convert-Slice", false, " Couldn't find an entity ID conversion for %s.", oldId.ToString().c_str()); + } } } + void SliceConverter::RemapIdReferences( + const AZStd::unordered_map& idMapper, + AzToolsFramework::Prefab::Instance* topLevelInstance, + AzToolsFramework::Prefab::Instance* nestedInstance, + SliceComponent::InstantiatedContainer* instantiatedEntities, + SerializeContext* context) + { + // Given a set of instantiated entities, run through all of them, look for entity references, and replace the entity IDs with + // new ones that match up with our prefabs. + + IdUtils::Remapper::ReplaceIdsAndIdRefs( + instantiatedEntities, + [idMapper, &topLevelInstance, &nestedInstance]( + const EntityId& sourceId, bool isEntityId, [[maybe_unused]] const AZStd::function& idGenerator) -> EntityId + { + EntityId newId = sourceId; + + // Only convert valid entity references. Actual entity IDs have already been taken care of elsewhere, so ignore them. + if (!isEntityId && sourceId.IsValid()) + { + auto entityEntry = idMapper.find(sourceId); + + // Since we've already remapped transform hierarchies to include container entities, it's possible that our entity + // reference is pointing to a container, which means it won't be in our slice mapping table. In that case, just + // return it as-is. + if (entityEntry == idMapper.end()) + { + return sourceId; + } + + // We've got a slice->prefab mapping entry, so now we need to use it. + auto& mappingStruct = entityEntry->second; + + if (mappingStruct.m_nestedInstanceAliases.empty()) + { + // If we don't have a chain of nested instance aliases, then this entity reference is either within the + // current nested instance or it's pointing to an entity in the top-level instance. We'll try them both + // to look for a match. + + EntityId prefabId = nestedInstance->GetEntityId(mappingStruct.m_entityAlias); + if (!prefabId.IsValid()) + { + prefabId = topLevelInstance->GetEntityId(mappingStruct.m_entityAlias); + } + + if (prefabId.IsValid()) + { + newId = prefabId; + } + else + { + AZ_Error("Convert-Slice", false, " Couldn't find source ID %s", sourceId.ToString().c_str()); + } + } + else + { + // We *do* have a chain of nested instance aliases. This chain could either be relative to the nested instance + // or the top-level instance. We can tell which one it is by which one can find the first nested instance + // alias. + + AzToolsFramework::Prefab::Instance* entityInstance = nestedInstance; + auto it = mappingStruct.m_nestedInstanceAliases.rbegin(); + if (!entityInstance->FindNestedInstance(*it).has_value()) + { + entityInstance = topLevelInstance; + } + + // Now that we've got a starting point, iterate through the chain of nested instance aliases to find the + // correct instance to get the entity ID for. We have to go from slice IDs -> entity aliases -> entity IDs + // because prefab instance creation can change some of our entity IDs along the way. + for (; it != mappingStruct.m_nestedInstanceAliases.rend(); it++) + { + auto foundInstance = entityInstance->FindNestedInstance(*it); + if (foundInstance.has_value()) + { + entityInstance = &(foundInstance->get()); + } + else + { + AZ_Assert(false, "Couldn't find nested instance %s", it->c_str()); + } + } + + EntityId prefabId = entityInstance->GetEntityId(mappingStruct.m_entityAlias); + if (prefabId.IsValid()) + { + newId = prefabId; + } + } + } + + return newId; + }, + context); + } } // namespace SerializeContextTools } // namespace AZ diff --git a/Code/Tools/SerializeContextTools/SliceConverter.h b/Code/Tools/SerializeContextTools/SliceConverter.h index ee0bb0a539..31c8306477 100644 --- a/Code/Tools/SerializeContextTools/SliceConverter.h +++ b/Code/Tools/SerializeContextTools/SliceConverter.h @@ -42,6 +42,28 @@ namespace AZ bool ConvertSliceFiles(Application& application); private: + // When converting slice entities, especially for nested slices, we need to keep track of the original + // entity ID, the entity alias it uses in the prefab, and which template and nested instance path it maps to. + // As we encounter each instanced entity ID, we can look it up in this structure and use this to determine how to properly + // add it to the correct place in the hierarchy. + struct SliceEntityMappingInfo + { + SliceEntityMappingInfo( + AzToolsFramework::Prefab::TemplateId templateId, + AzToolsFramework::Prefab::EntityAlias entityAlias, + bool isMetadataEntity = false) + : m_templateId(templateId) + , m_entityAlias(entityAlias) + , m_isMetadataEntity(isMetadataEntity) + { + } + + AzToolsFramework::Prefab::TemplateId m_templateId; + AzToolsFramework::Prefab::EntityAlias m_entityAlias; + AZStd::vector m_nestedInstanceAliases; + bool m_isMetadataEntity{ false }; + }; + bool ConnectToAssetProcessor(); void DisconnectFromAssetProcessor(); @@ -58,27 +80,17 @@ namespace AZ void SetParentEntity(const AZ::Entity& entity, const AZ::EntityId& parentId, bool onlySetIfInvalid); void PrintPrefab(AzToolsFramework::Prefab::TemplateId templateId); bool SavePrefab(AZ::IO::PathView outputPath, AzToolsFramework::Prefab::TemplateId templateId); - void ClearSliceAssetReferences(AZ::Entity* rootEntity); void UpdateSliceEntityInstanceMappings( const AZ::SliceComponent::EntityIdToEntityIdMap& sliceEntityIdMap, const AZStd::string& currentInstanceAlias); + AZStd::string GetInstanceAlias(const AZ::SliceComponent::SliceInstance& instance); - // When converting slice entities, especially for nested slices, we need to keep track of the original - // entity ID, the entity alias it uses in the prefab, and which template and nested instance path it maps to. - // As we encounter each instanced entity ID, we can look it up in this structure and use this to determine how to properly - // add it to the correct place in the hierarchy. - struct SliceEntityMappingInfo - { - SliceEntityMappingInfo(AzToolsFramework::Prefab::TemplateId templateId, AzToolsFramework::Prefab::EntityAlias entityAlias) - : m_templateId(templateId) - , m_entityAlias(entityAlias) - { - } - - AzToolsFramework::Prefab::TemplateId m_templateId; - AzToolsFramework::Prefab::EntityAlias m_entityAlias; - AZStd::vector m_nestedInstanceAliases; - }; + void RemapIdReferences( + const AZStd::unordered_map& idMapper, + AzToolsFramework::Prefab::Instance* topLevelInstance, + AzToolsFramework::Prefab::Instance* nestedInstance, + SliceComponent::InstantiatedContainer* instantiatedEntities, + SerializeContext* context); // Track all of the entity IDs created and associate them with enough conversion information to know how to place the // entities in the correct place in the prefab hierarchy and fix up parent entity ID mappings to work with the nested From 406792606b1c335e138d4caf3770b6b19be737b7 Mon Sep 17 00:00:00 2001 From: Santora Date: Mon, 14 Jun 2021 13:04:15 -0700 Subject: [PATCH 085/116] I missed one spot that needs to print the address. --- Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp index eac1ee42e5..d9691ca175 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp @@ -261,7 +261,7 @@ namespace AZ { // TODO: I think we should make Shader handle OnShaderAssetReinitialized and treat it just like the shader reloaded. - ShaderReloadDebugTracker::ScopedSection reloadSection("Material::OnShaderAssetReinitialized %s", shaderAsset.GetHint().c_str()); + ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnShaderAssetReinitialized %s", this, shaderAsset.GetHint().c_str()); // Note that it might not be strictly necessary to reinitialize the entire material, we might be able to get away with // just bumping the m_currentChangeId or some other minor updates. But it's pretty hard to know what exactly needs to be // updated to correctly handle the reload, so it's safer to just reinitialize the whole material. From 84492dee48b1c0cb3a99a7ab5eef586cc81373b5 Mon Sep 17 00:00:00 2001 From: Yuriy Toporovskyy Date: Mon, 14 Jun 2021 16:19:18 -0400 Subject: [PATCH 086/116] Address some PR feedback - Use AZ::IConsole instead of deprecated Cry IConsole. - Create fullscreen preview widget on the same screen where the main window is found, instead of on the 'primary' screen - Remove "ed_previewGameInFullscreen", which had the effect of always doing a full screen preview. If this functionality is desired, it should be re-added as a registry key instead of a cvar --- Code/Sandbox/Editor/CryEdit.cpp | 6 +++-- Code/Sandbox/Editor/EditorViewportWidget.cpp | 25 +++++++------------- Code/Sandbox/Editor/Settings.cpp | 9 +++---- 3 files changed, 15 insertions(+), 25 deletions(-) diff --git a/Code/Sandbox/Editor/CryEdit.cpp b/Code/Sandbox/Editor/CryEdit.cpp index 815f986e1a..536821ca6c 100644 --- a/Code/Sandbox/Editor/CryEdit.cpp +++ b/Code/Sandbox/Editor/CryEdit.cpp @@ -53,6 +53,7 @@ AZ_POP_DISABLE_WARNING #include #include #include +#include // AzFramework #include @@ -356,6 +357,8 @@ CCryEditDoc* CCryDocManager::OpenDocumentFile(LPCTSTR lpszFileName, BOOL bAddToM for (int i = idStart; i <= idEnd; ++i) \ ON_COMMAND(i, method); +AZ_CVAR_EXTERNED(bool, ed_previewGameInFullscreen_once); + void CCryEditApp::RegisterActionHandlers() { ON_COMMAND(ID_APP_ABOUT, OnAppAbout) @@ -377,8 +380,7 @@ void CCryEditApp::RegisterActionHandlers() ON_COMMAND(ID_FILE_EXPORTTOGAMENOSURFACETEXTURE, OnFileExportToGameNoSurfaceTexture) ON_COMMAND(ID_VIEW_SWITCHTOGAME, OnViewSwitchToGame) MainWindow::instance()->GetActionManager()->RegisterActionHandler(ID_VIEW_SWITCHTOGAME_FULLSCREEN, [this]() { - auto fs = gEnv->pConsole->GetCVar("ed_previewGameInFullscreen_once"); - fs->Set(1); + ed_previewGameInFullscreen_once = true; OnViewSwitchToGame(); }); ON_COMMAND(ID_MOVE_OBJECT, OnMoveObject) diff --git a/Code/Sandbox/Editor/EditorViewportWidget.cpp b/Code/Sandbox/Editor/EditorViewportWidget.cpp index ba181aa99b..b02aafbe32 100644 --- a/Code/Sandbox/Editor/EditorViewportWidget.cpp +++ b/Code/Sandbox/Editor/EditorViewportWidget.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include // AzFramework @@ -3059,6 +3060,8 @@ float EditorViewportSettings::AngleStep() const return SandboxEditor::AngleSnappingSize(); } +AZ_CVAR_EXTERNED(bool, ed_previewGameInFullscreen_once); + bool EditorViewportWidget::ShouldPreviewFullscreen() const { CLayoutWnd* layout = GetIEditor()->GetViewManager()->GetLayout(); @@ -3089,23 +3092,10 @@ bool EditorViewportWidget::ShouldPreviewFullscreen() const } } - // Check 'ed_previewGameInFullscreen_once' and 'ed_previewGameInFullscreen' cvars - if (gEnv->pConsole) + // Check 'ed_previewGameInFullscreen_once' + if (ed_previewGameInFullscreen_once) { - if (auto v = gEnv->pConsole->GetCVar("ed_previewGameInFullscreen_once")) - { - if (v->GetIVal() != 0) - { - v->Set(0); - return true; - } - } - - { - auto v = gEnv->pConsole->GetCVar("ed_previewGameInFullscreen"); - return v && v->GetIVal() != 0; // if it doesn't exist, assume its value is 0 - } - + ed_previewGameInFullscreen_once = true; return true; } else @@ -3119,7 +3109,8 @@ void EditorViewportWidget::StartFullscreenPreview() AZ_Assert(!m_inFullscreenPreview, "EditorViewportWidget::StartFullscreenPreview called when already in full screen preview"); m_inFullscreenPreview = true; - const QScreen* screen = QGuiApplication::primaryScreen(); + // Pick the screen on which the main window lies to use as the screen for the full screen preview + const QScreen* screen = MainWindow::instance()->screen(); const QRect screenGeometry = screen->geometry(); // Unparent this and show it, which turns it into a free floating window diff --git a/Code/Sandbox/Editor/Settings.cpp b/Code/Sandbox/Editor/Settings.cpp index 66271a9967..f805e2e84b 100644 --- a/Code/Sandbox/Editor/Settings.cpp +++ b/Code/Sandbox/Editor/Settings.cpp @@ -26,6 +26,7 @@ #include #include #include +#include // AzFramework #include @@ -926,6 +927,8 @@ void SEditorSettings::Load() } ////////////////////////////////////////////////////////////////////////// +AZ_CVAR(bool, ed_previewGameInFullscreen_once, false, nullptr, AZ::ConsoleFunctorFlags::IsInvisible, "Preview the game (Ctrl+G, \"Play Game\", etc.) in fullscreen once"); + void SEditorSettings::PostInitApply() { if (!gEnv || !gEnv->pConsole) @@ -947,12 +950,6 @@ void SEditorSettings::PostInitApply() REGISTER_CVAR2_CB("ed_keepEditorActive", &keepEditorActive, 0, VF_NULL, "Keep the editor active, even if no focus is set", KeepEditorActiveChanged); REGISTER_CVAR2("g_TemporaryLevelName", &g_TemporaryLevelName, "temp_level", VF_NULL, "Temporary level named used for experimental levels."); - REGISTER_INT("ed_previewGameInFullscreen", 0, VF_DEV_ONLY, "Preview the game (Ctrl+G, \"Play Game\", etc.) in fullscreen. 0 = no, 1 = yes"); - gEnv->pConsole->GetCVar("ed_previewGameInFullscreen")->SetLimits(0, 1); - - REGISTER_INT("ed_previewGameInFullscreen_once", 0, VF_DEV_ONLY | VF_INVISIBLE, "Preview the game (Ctrl+G, \"Play Game\", etc.) in fullscreen once. 0 = no, 1 = yes"); - gEnv->pConsole->GetCVar("ed_previewGameInFullscreen_once")->SetLimits(0, 1); - CCryEditApp::instance()->KeepEditorActive(keepEditorActive > 0); } From 6c05adddec4a1c056fd7e52a28aeccd7f289cec1 Mon Sep 17 00:00:00 2001 From: gallowj Date: Mon, 14 Jun 2021 15:41:50 -0500 Subject: [PATCH 087/116] This material did not look correct, sneaking it in --- .../Objects/PlayfulTeapot_playfulteapot.material | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/PlayfulTeapot_playfulteapot.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/PlayfulTeapot_playfulteapot.material index 27540c587e..da35fda141 100644 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/PlayfulTeapot_playfulteapot.material +++ b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/PlayfulTeapot_playfulteapot.material @@ -14,13 +14,14 @@ }, "clearCoat": { "enable": true, - "normalMap": "EngineAssets/Textures/perlinNoiseNormal_ddn.tif" + "normalMap": "EngineAssets/Textures/perlinNoiseNormal_ddn.tif", + "normalStrength": 0.10000000149011612 }, "general": { "applySpecularAA": true }, "metallic": { - "factor": 0.5 + "factor": 0.10000000149011612 }, "normal": { "factor": 0.05000000074505806, @@ -31,6 +32,9 @@ }, "roughness": { "factor": 0.0 + }, + "specularF0": { + "enableMultiScatterCompensation": true } } -} +} \ No newline at end of file From 11c3a7532198708ff3fb5821aabd289ec8ea4676 Mon Sep 17 00:00:00 2001 From: amzn-hdoke <61443753+hdoke@users.noreply.github.com> Date: Mon, 14 Jun 2021 13:54:04 -0700 Subject: [PATCH 088/116] Enable Client Auth unit test on Linux (#1312) --- scripts/build/Platform/Linux/build_config.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/build/Platform/Linux/build_config.json b/scripts/build/Platform/Linux/build_config.json index ee6da77b29..903ac52568 100644 --- a/scripts/build/Platform/Linux/build_config.json +++ b/scripts/build/Platform/Linux/build_config.json @@ -83,7 +83,7 @@ "CMAKE_OPTIONS": "-G 'Ninja Multi-Config' -DCMAKE_C_COMPILER=clang-6.0 -DCMAKE_CXX_COMPILER=clang++-6.0 -DLY_UNITY_BUILD=TRUE -DLY_PARALLEL_LINK_JOBS=4", "CMAKE_LY_PROJECTS": "AutomatedTesting", "CMAKE_TARGET": "all", - "CTEST_OPTIONS": "-E (Gem::EMotionFX.Editor.Tests|Gem::AWSClientAuth.Tests|Gem::AWSCore.Editor.Tests) -LE SUITE_sandbox -L FRAMEWORK_googletest" + "CTEST_OPTIONS": "-E (Gem::EMotionFX.Editor.Tests|Gem::AWSCore.Editor.Tests) -LE SUITE_sandbox -L FRAMEWORK_googletest" } }, "test_profile_nounity": { @@ -95,7 +95,7 @@ "CMAKE_OPTIONS": "-G 'Ninja Multi-Config' -DCMAKE_C_COMPILER=clang-6.0 -DCMAKE_CXX_COMPILER=clang++-6.0 -DLY_UNITY_BUILD=FALSE -DLY_PARALLEL_LINK_JOBS=4", "CMAKE_LY_PROJECTS": "AutomatedTesting", "CMAKE_TARGET": "all", - "CTEST_OPTIONS": "-E (Gem::EMotionFX.Editor.Tests|Gem::AWSClientAuth.Tests|Gem::AWSCore.Editor.Tests) -LE SUITE_sandbox -L FRAMEWORK_googletest" + "CTEST_OPTIONS": "-E (Gem::EMotionFX.Editor.Tests|Gem::AWSCore.Editor.Tests) -LE SUITE_sandbox -L FRAMEWORK_googletest" } }, "asset_profile": { From 86d0acf76c18b373f81a48f6725605f2489be3c0 Mon Sep 17 00:00:00 2001 From: sharmajs-amzn <82233357+sharmajs-amzn@users.noreply.github.com> Date: Mon, 14 Jun 2021 13:55:37 -0700 Subject: [PATCH 089/116] fixes for invalid drive letter casing for scanfolder (#1281) --- .../assetprocessor_static_files.cmake | 1 + .../AssetManager/assetScanFolderInfo.cpp | 42 +++++++++++++++++++ .../native/AssetManager/assetScanFolderInfo.h | 14 +------ 3 files changed, 44 insertions(+), 13 deletions(-) create mode 100644 Code/Tools/AssetProcessor/native/AssetManager/assetScanFolderInfo.cpp diff --git a/Code/Tools/AssetProcessor/assetprocessor_static_files.cmake b/Code/Tools/AssetProcessor/assetprocessor_static_files.cmake index 194e99b247..1e78d1dc6c 100644 --- a/Code/Tools/AssetProcessor/assetprocessor_static_files.cmake +++ b/Code/Tools/AssetProcessor/assetprocessor_static_files.cmake @@ -19,6 +19,7 @@ set(FILES native/AssetManager/AssetRequestHandler.cpp native/AssetManager/AssetRequestHandler.h native/AssetManager/assetScanFolderInfo.h + native/AssetManager/assetScanFolderInfo.cpp native/AssetManager/assetScanner.cpp native/AssetManager/assetScanner.h native/AssetManager/assetScannerWorker.cpp diff --git a/Code/Tools/AssetProcessor/native/AssetManager/assetScanFolderInfo.cpp b/Code/Tools/AssetProcessor/native/AssetManager/assetScanFolderInfo.cpp new file mode 100644 index 0000000000..f849b4ee49 --- /dev/null +++ b/Code/Tools/AssetProcessor/native/AssetManager/assetScanFolderInfo.cpp @@ -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. +* +*/ + +#include +#include + +namespace AssetProcessor +{ + ScanFolderInfo::ScanFolderInfo( + QString path, + QString displayName, + QString portableKey, + bool isRoot, + bool recurseSubFolders, + AZStd::vector platforms, + int order, + AZ::s64 scanFolderID, + bool canSaveNewAssets) + : m_scanPath(path) + , m_displayName(displayName) + , m_portableKey (portableKey) + , m_isRoot(isRoot) + , m_recurseSubFolders(recurseSubFolders) + , m_order(order) + , m_scanFolderID(scanFolderID) + , m_platforms(platforms) + , m_canSaveNewAssets(canSaveNewAssets) + { + m_scanPath = AssetUtilities::NormalizeFilePath(m_scanPath); + // note that m_scanFolderID is 0 unless its filled in from the DB. + } + +} // end namespace AssetProcessor diff --git a/Code/Tools/AssetProcessor/native/AssetManager/assetScanFolderInfo.h b/Code/Tools/AssetProcessor/native/AssetManager/assetScanFolderInfo.h index 5767822451..5fbda237d7 100644 --- a/Code/Tools/AssetProcessor/native/AssetManager/assetScanFolderInfo.h +++ b/Code/Tools/AssetProcessor/native/AssetManager/assetScanFolderInfo.h @@ -33,19 +33,7 @@ namespace AssetProcessor AZStd::vector platforms = AZStd::vector{}, int order = 0, AZ::s64 scanFolderID = 0, - bool canSaveNewAssets = false) - : m_scanPath(path) - , m_displayName(displayName) - , m_portableKey (portableKey) - , m_isRoot(isRoot) - , m_recurseSubFolders(recurseSubFolders) - , m_order(order) - , m_scanFolderID(scanFolderID) - , m_platforms(platforms) - , m_canSaveNewAssets(canSaveNewAssets) - { - // note that m_scanFolderID is 0 unless its filled in from the DB. - } + bool canSaveNewAssets = false); ScanFolderInfo() = default; ScanFolderInfo(const ScanFolderInfo& other) = default; From 948075fa61a9a08f1ef36b059602eeaabce69a94 Mon Sep 17 00:00:00 2001 From: AMZN-nggieber <52797929+AMZN-nggieber@users.noreply.github.com> Date: Mon, 14 Jun 2021 15:56:54 -0700 Subject: [PATCH 090/116] Gem Catalog Allows Filtering by Gem Selected Status Live (#1274) --- .../Source/GemCatalog/GemCatalogScreen.cpp | 2 + .../Source/GemCatalog/GemFilterWidget.cpp | 111 ++++++++++++++++-- .../Source/GemCatalog/GemFilterWidget.h | 9 +- .../Source/GemCatalog/GemItemDelegate.cpp | 20 ---- .../Source/GemCatalog/GemListHeaderWidget.cpp | 10 ++ .../Source/GemCatalog/GemModel.cpp | 15 +++ .../Source/GemCatalog/GemModel.h | 2 + .../GemCatalog/GemSortFilterProxyModel.cpp | 23 ++++ .../GemCatalog/GemSortFilterProxyModel.h | 13 ++ .../Source/UpdateProjectCtrl.cpp | 6 +- 10 files changed, 179 insertions(+), 32 deletions(-) diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp index 4424767c0b..2c92af4e51 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp @@ -82,6 +82,8 @@ namespace O3DE::ProjectManager m_headerWidget->ReinitForProject(); + connect(m_gemModel, &GemModel::dataChanged, m_filterWidget, &GemFilterWidget::ResetGemStatusFilter); + // Select the first entry after everything got correctly sized QTimer::singleShot(200, [=]{ QModelIndex firstModelIndex = m_gemListView->model()->index(0,0); diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp index a6a4e95ff9..7c6150ff99 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp @@ -26,6 +26,7 @@ namespace O3DE::ProjectManager const QVector& elementNames, const QVector& elementCounts, bool showAllLessButton, + bool collapsed, int defaultShowCount, QWidget* parent) : QWidget(parent) @@ -40,6 +41,7 @@ namespace O3DE::ProjectManager QHBoxLayout* collapseLayout = new QHBoxLayout(); m_collapseButton = new QPushButton(); m_collapseButton->setCheckable(true); + m_collapseButton->setChecked(collapsed); m_collapseButton->setFlat(true); m_collapseButton->setFocusPolicy(Qt::NoFocus); m_collapseButton->setFixedWidth(s_collapseButtonSize); @@ -178,6 +180,11 @@ namespace O3DE::ProjectManager return m_buttonGroup; } + bool FilterCategoryWidget::IsCollapsed() + { + return m_collapseButton->isChecked(); + } + GemFilterWidget::GemFilterWidget(GemSortFilterProxyModel* filterProxyModel, QWidget* parent) : QScrollArea(parent) , m_filterProxyModel(filterProxyModel) @@ -193,20 +200,106 @@ namespace O3DE::ProjectManager QWidget* mainWidget = new QWidget(); setWidget(mainWidget); - m_mainLayout = new QVBoxLayout(); - m_mainLayout->setAlignment(Qt::AlignTop); - mainWidget->setLayout(m_mainLayout); + QVBoxLayout* mainLayout = new QVBoxLayout(); + mainLayout->setAlignment(Qt::AlignTop); + mainWidget->setLayout(mainLayout); QLabel* filterByLabel = new QLabel("Filter by"); filterByLabel->setStyleSheet("font-size: 16px;"); - m_mainLayout->addWidget(filterByLabel); + mainLayout->addWidget(filterByLabel); + QWidget* filterSection = new QWidget(this); + mainLayout->addWidget(filterSection); + + m_filterLayout = new QVBoxLayout(); + m_filterLayout->setAlignment(Qt::AlignTop); + m_filterLayout->setContentsMargins(0, 0, 0, 0); + filterSection->setLayout(m_filterLayout); + + ResetGemStatusFilter(); AddGemOriginFilter(); AddTypeFilter(); AddPlatformFilter(); AddFeatureFilter(); } + void GemFilterWidget::ResetGemStatusFilter() + { + QVector elementNames; + QVector elementCounts; + const int totalGems = m_gemModel->rowCount(); + const int selectedGemTotal = m_gemModel->TotalAddedGems(); + + elementNames.push_back(GemSortFilterProxyModel::GetGemStatusString(GemSortFilterProxyModel::GemStatus::Unselected)); + elementCounts.push_back(totalGems - selectedGemTotal); + + elementNames.push_back(GemSortFilterProxyModel::GetGemStatusString(GemSortFilterProxyModel::GemStatus::Selected)); + elementCounts.push_back(selectedGemTotal); + + bool wasCollapsed = false; + if (m_statusFilter) + { + wasCollapsed = m_statusFilter->IsCollapsed(); + } + + FilterCategoryWidget* filterWidget = + new FilterCategoryWidget("Status", elementNames, elementCounts, /*showAllLessButton=*/false, /*collapsed*/wasCollapsed); + if (m_statusFilter) + { + m_filterLayout->replaceWidget(m_statusFilter, filterWidget); + } + else + { + m_filterLayout->addWidget(filterWidget); + } + + m_statusFilter->deleteLater(); + m_statusFilter = filterWidget; + + const GemSortFilterProxyModel::GemStatus currentFilterState = m_filterProxyModel->GetGemStatus(); + const QList buttons = m_statusFilter->GetButtonGroup()->buttons(); + for (int statusFilterIndex = 0; statusFilterIndex < buttons.size(); ++statusFilterIndex) + { + const GemSortFilterProxyModel::GemStatus gemStatus = static_cast(statusFilterIndex); + QAbstractButton* button = buttons[statusFilterIndex]; + + if (static_cast(statusFilterIndex) == currentFilterState) + { + button->setChecked(true); + } + + connect( + button, &QAbstractButton::toggled, this, + [=](bool checked) + { + GemSortFilterProxyModel::GemStatus filterStatus = m_filterProxyModel->GetGemStatus(); + if (checked) + { + if (filterStatus == GemSortFilterProxyModel::GemStatus::NoFilter) + { + filterStatus = gemStatus; + } + else + { + filterStatus = GemSortFilterProxyModel::GemStatus::NoFilter; + } + } + else + { + if (filterStatus != gemStatus) + { + filterStatus = static_cast(!gemStatus); + } + else + { + filterStatus = GemSortFilterProxyModel::GemStatus::NoFilter; + } + } + m_filterProxyModel->SetGemStatus(filterStatus); + }); + } + } + void GemFilterWidget::AddGemOriginFilter() { QVector elementNames; @@ -233,7 +326,7 @@ namespace O3DE::ProjectManager } FilterCategoryWidget* filterWidget = new FilterCategoryWidget("Provider", elementNames, elementCounts, /*showAllLessButton=*/false); - m_mainLayout->addWidget(filterWidget); + m_filterLayout->addWidget(filterWidget); const QList buttons = filterWidget->GetButtonGroup()->buttons(); for (int i = 0; i < buttons.size(); ++i) @@ -283,7 +376,7 @@ namespace O3DE::ProjectManager } FilterCategoryWidget* filterWidget = new FilterCategoryWidget("Type", elementNames, elementCounts, /*showAllLessButton=*/false); - m_mainLayout->addWidget(filterWidget); + m_filterLayout->addWidget(filterWidget); const QList buttons = filterWidget->GetButtonGroup()->buttons(); for (int i = 0; i < buttons.size(); ++i) @@ -333,7 +426,7 @@ namespace O3DE::ProjectManager } FilterCategoryWidget* filterWidget = new FilterCategoryWidget("Supported Platforms", elementNames, elementCounts, /*showAllLessButton=*/false); - m_mainLayout->addWidget(filterWidget); + m_filterLayout->addWidget(filterWidget); const QList buttons = filterWidget->GetButtonGroup()->buttons(); for (int i = 0; i < buttons.size(); ++i) @@ -388,8 +481,8 @@ namespace O3DE::ProjectManager } FilterCategoryWidget* filterWidget = new FilterCategoryWidget("Features", elementNames, elementCounts, - /*showAllLessButton=*/true, /*defaultShowCount=*/5); - m_mainLayout->addWidget(filterWidget); + /*showAllLessButton=*/true, false, /*defaultShowCount=*/5); + m_filterLayout->addWidget(filterWidget); const QList buttons = filterWidget->GetButtonGroup()->buttons(); for (int i = 0; i < buttons.size(); ++i) diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.h index 017eadc020..520370eb44 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.h @@ -37,11 +37,14 @@ namespace O3DE::ProjectManager const QVector& elementNames, const QVector& elementCounts, bool showAllLessButton = true, + bool collapsed = false, int defaultShowCount = 4, QWidget* parent = nullptr); QButtonGroup* GetButtonGroup(); + bool IsCollapsed(); + private: void UpdateCollapseState(); void UpdateSeeMoreLess(); @@ -66,14 +69,18 @@ namespace O3DE::ProjectManager explicit GemFilterWidget(GemSortFilterProxyModel* filterProxyModel, QWidget* parent = nullptr); ~GemFilterWidget() = default; + public slots: + void ResetGemStatusFilter(); + private: void AddGemOriginFilter(); void AddTypeFilter(); void AddPlatformFilter(); void AddFeatureFilter(); - QVBoxLayout* m_mainLayout = nullptr; + QVBoxLayout* m_filterLayout = nullptr; GemModel* m_gemModel = nullptr; GemSortFilterProxyModel* m_filterProxyModel = nullptr; + FilterCategoryWidget* m_statusFilter = nullptr; }; } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp index 8aa68fb7a2..03787de7e8 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp @@ -204,7 +204,6 @@ namespace O3DE::ProjectManager painter->save(); const QRect buttonRect = CalcButtonRect(contentRect); QPoint circleCenter; - QString buttonText; const bool isAdded = GemModel::IsAdded(modelIndex); if (isAdded) @@ -213,34 +212,15 @@ namespace O3DE::ProjectManager painter->setPen(m_buttonEnabledColor); circleCenter = buttonRect.center() + QPoint(buttonRect.width() / 2 - s_buttonBorderRadius + 1, 1); - buttonText = "Added"; } else { circleCenter = buttonRect.center() + QPoint(-buttonRect.width() / 2 + s_buttonBorderRadius, 1); - buttonText = "Get"; } // Rounded rect painter->drawRoundedRect(buttonRect, s_buttonBorderRadius, s_buttonBorderRadius); - // Text - QFont font; - QRect textRect = GetTextRect(font, buttonText, s_buttonFontSize); - if (isAdded) - { - textRect = QRect(buttonRect.left(), buttonRect.top(), buttonRect.width() - s_buttonCircleRadius * 2.0, buttonRect.height()); - } - else - { - textRect = QRect(buttonRect.left() + s_buttonCircleRadius * 2.0, buttonRect.top(), buttonRect.width() - s_buttonCircleRadius * 2.0, buttonRect.height()); - } - - font.setPixelSize(s_buttonFontSize); - painter->setFont(font); - painter->setPen(m_textColor); - painter->drawText(textRect, Qt::AlignCenter, buttonText); - // Circle painter->setBrush(m_textColor); painter->drawEllipse(circleCenter, s_buttonCircleRadius, s_buttonCircleRadius); diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemListHeaderWidget.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemListHeaderWidget.cpp index bc287e3c61..ad1b57a27c 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemListHeaderWidget.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemListHeaderWidget.cpp @@ -15,6 +15,7 @@ #include #include #include +#include namespace O3DE::ProjectManager { @@ -74,6 +75,15 @@ namespace O3DE::ProjectManager gemSummaryLabel->setStyleSheet("font-size: 12px;"); columnHeaderLayout->addWidget(gemSummaryLabel); + QSpacerItem* horizontalSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum); + columnHeaderLayout->addSpacerItem(horizontalSpacer); + + QLabel* gemSelectedLabel = new QLabel(tr("Selected")); + gemSelectedLabel->setStyleSheet("font-size: 12px;"); + columnHeaderLayout->addWidget(gemSelectedLabel); + + columnHeaderLayout->addSpacing(60); + vLayout->addLayout(columnHeaderLayout); } } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp index 6c09c95572..5dc40723c9 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp @@ -235,4 +235,19 @@ namespace O3DE::ProjectManager } return result; } + + int GemModel::TotalAddedGems() const + { + int result = 0; + for (int row = 0; row < rowCount(); ++row) + { + const QModelIndex modelIndex = index(row, 0); + if (IsAdded(modelIndex)) + { + ++result; + } + } + return result; + } + } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h index 77f973a91c..2e05472cdf 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h @@ -63,6 +63,8 @@ namespace O3DE::ProjectManager QVector GatherGemsToBeAdded() const; QVector GatherGemsToBeRemoved() const; + int TotalAddedGems() const; + private: enum UserRole { diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemSortFilterProxyModel.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemSortFilterProxyModel.cpp index d8f41c077e..c1360cabc6 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemSortFilterProxyModel.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemSortFilterProxyModel.cpp @@ -37,6 +37,16 @@ namespace O3DE::ProjectManager return false; } + // Gem status + if (m_gemStatusFilter != GemStatus::NoFilter) + { + const GemStatus sourceGemStatus = static_cast(GemModel::IsAdded(sourceIndex)); + if (m_gemStatusFilter != sourceGemStatus) + { + return false; + } + } + // Gem origins if (m_gemOriginFilter) { @@ -125,6 +135,19 @@ namespace O3DE::ProjectManager return true; } + QString GemSortFilterProxyModel::GetGemStatusString(GemStatus status) + { + switch (status) + { + case Unselected: + return "Unselected"; + case Selected: + return "Selected"; + default: + return ""; + } + } + void GemSortFilterProxyModel::InvalidateFilter() { invalidate(); diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemSortFilterProxyModel.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemSortFilterProxyModel.h index f24a724ecf..fcde226f40 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemSortFilterProxyModel.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemSortFilterProxyModel.h @@ -29,8 +29,17 @@ namespace O3DE::ProjectManager Q_OBJECT // AUTOMOC public: + enum GemStatus + { + NoFilter = -1, + Unselected, + Selected + }; + GemSortFilterProxyModel(GemModel* sourceModel, QObject* parent = nullptr); + static QString GetGemStatusString(GemStatus status); + bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override; GemModel* GetSourceModel() const { return m_sourceModel; } @@ -38,6 +47,9 @@ namespace O3DE::ProjectManager void SetSearchString(const QString& searchString) { m_searchString = searchString; InvalidateFilter(); } + GemStatus GetGemStatus() const { return m_gemStatusFilter; } + void SetGemStatus(GemStatus gemStatus) { m_gemStatusFilter = gemStatus; InvalidateFilter(); } + GemInfo::GemOrigins GetGemOrigins() const { return m_gemOriginFilter; } void SetGemOrigins(const GemInfo::GemOrigins& gemOrigins) { m_gemOriginFilter = gemOrigins; InvalidateFilter(); } @@ -61,6 +73,7 @@ namespace O3DE::ProjectManager AzQtComponents::SelectionProxyModel* m_selectionProxyModel = nullptr; QString m_searchString; + GemStatus m_gemStatusFilter = GemStatus::NoFilter; GemInfo::GemOrigins m_gemOriginFilter = {}; GemInfo::Platforms m_platformFilter = {}; GemInfo::Types m_typeFilter = {}; diff --git a/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp b/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp index be1f0e5529..65f73accd1 100644 --- a/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp +++ b/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp @@ -189,11 +189,13 @@ namespace O3DE::ProjectManager { if (m_stack->currentIndex() == ScreenOrder::Gems) { - m_header->setSubTitle(QString(tr("Configure Gems for \"%1\"")).arg(m_projectInfo.m_projectName)); - m_nextButton->setText(tr("Confirm")); + m_header->setTitle(QString(tr("Edit Project Settings: \"%1\"")).arg(m_projectInfo.m_projectName)); + m_header->setSubTitle(QString(tr("Configure Gems"))); + m_nextButton->setText(tr("Finalize")); } else { + m_header->setTitle(""); m_header->setSubTitle(QString(tr("Edit Project Settings: \"%1\"")).arg(m_projectInfo.m_projectName)); m_nextButton->setText(tr("Save")); } From ecded991b57be2db905ce4c15d7af9d2fb9c297f Mon Sep 17 00:00:00 2001 From: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> Date: Mon, 14 Jun 2021 17:02:22 -0700 Subject: [PATCH 091/116] Display error when unable to start Python Added AzFramework Application, logging, unit tests --- Code/Framework/AzCore/AzCore/Utils/Utils.cpp | 7 + Code/Framework/AzCore/AzCore/Utils/Utils.h | 3 + Code/Sandbox/Editor/CryEdit.cpp | 2 +- Code/Tools/ProjectManager/CMakeLists.txt | 63 +++++- .../Linux/PAL_linux_tests_files.cmake | 15 ++ .../Linux/ProjectManager_Test_Traits_Linux.h | 15 ++ .../ProjectManager_Test_Traits_Platform.h | 15 ++ .../Platform/Mac/PAL_mac_tests_files.cmake | 15 ++ .../Mac/ProjectManager_Test_Traits_Mac.h | 15 ++ .../Mac/ProjectManager_Test_Traits_Platform.h | 15 ++ .../Windows/PAL_windows_tests_files.cmake | 15 ++ .../ProjectManager_Test_Traits_Platform.h | 15 ++ .../ProjectManager_Test_Traits_Windows.h | 15 ++ .../Resources/ProjectManager.qss | 5 + .../ProjectManager/Source/Application.cpp | 186 ++++++++++++++++++ .../Tools/ProjectManager/Source/Application.h | 48 +++++ .../Source/EngineSettingsScreen.cpp | 2 +- .../Source/ProjectButtonWidget.cpp | 2 +- .../Source/ProjectManagerWindow.cpp | 27 +-- .../Source/ProjectManagerWindow.h | 8 +- .../Source/ProjectSettingsScreen.cpp | 2 +- .../ProjectManager/Source/ProjectsScreen.cpp | 4 +- .../ProjectManager/Source/PythonBindings.cpp | 14 +- .../ProjectManager/Source/PythonBindings.h | 4 + .../Source/PythonBindingsInterface.h | 6 + Code/Tools/ProjectManager/Source/main.cpp | 87 ++------ .../project_manager_app_files.cmake | 17 ++ .../project_manager_files.cmake | 7 +- .../project_manager_tests_files.cmake | 17 ++ .../ProjectManager/tests/ApplicationTests.cpp | 47 +++++ Code/Tools/ProjectManager/tests/main.cpp | 35 ++++ 31 files changed, 606 insertions(+), 122 deletions(-) create mode 100644 Code/Tools/ProjectManager/Platform/Linux/PAL_linux_tests_files.cmake create mode 100644 Code/Tools/ProjectManager/Platform/Linux/ProjectManager_Test_Traits_Linux.h create mode 100644 Code/Tools/ProjectManager/Platform/Linux/ProjectManager_Test_Traits_Platform.h create mode 100644 Code/Tools/ProjectManager/Platform/Mac/PAL_mac_tests_files.cmake create mode 100644 Code/Tools/ProjectManager/Platform/Mac/ProjectManager_Test_Traits_Mac.h create mode 100644 Code/Tools/ProjectManager/Platform/Mac/ProjectManager_Test_Traits_Platform.h create mode 100644 Code/Tools/ProjectManager/Platform/Windows/PAL_windows_tests_files.cmake create mode 100644 Code/Tools/ProjectManager/Platform/Windows/ProjectManager_Test_Traits_Platform.h create mode 100644 Code/Tools/ProjectManager/Platform/Windows/ProjectManager_Test_Traits_Windows.h create mode 100644 Code/Tools/ProjectManager/Source/Application.cpp create mode 100644 Code/Tools/ProjectManager/Source/Application.h create mode 100644 Code/Tools/ProjectManager/project_manager_app_files.cmake create mode 100644 Code/Tools/ProjectManager/project_manager_tests_files.cmake create mode 100644 Code/Tools/ProjectManager/tests/ApplicationTests.cpp create mode 100644 Code/Tools/ProjectManager/tests/main.cpp diff --git a/Code/Framework/AzCore/AzCore/Utils/Utils.cpp b/Code/Framework/AzCore/AzCore/Utils/Utils.cpp index 7025b3977e..e3647ec2cb 100644 --- a/Code/Framework/AzCore/AzCore/Utils/Utils.cpp +++ b/Code/Framework/AzCore/AzCore/Utils/Utils.cpp @@ -175,4 +175,11 @@ namespace AZ::Utils path /= ".o3de"; return path.Native(); } + + AZ::IO::FixedMaxPathString GetO3deLogsDirectory() + { + AZ::IO::FixedMaxPath path = GetO3deManifestDirectory(); + path /= "Logs"; + return path.Native(); + } } diff --git a/Code/Framework/AzCore/AzCore/Utils/Utils.h b/Code/Framework/AzCore/AzCore/Utils/Utils.h index d082a3ebe0..8fb6f05742 100644 --- a/Code/Framework/AzCore/AzCore/Utils/Utils.h +++ b/Code/Framework/AzCore/AzCore/Utils/Utils.h @@ -97,6 +97,9 @@ namespace AZ //! Retrieves the full path where the manifest file lives, i.e. "/.o3de/o3de_manifest.json" AZ::IO::FixedMaxPathString GetEngineManifestPath(); + //! Retrieves the full directory to the O3DE logs directory, i.e. "/.o3de/Logs" + AZ::IO::FixedMaxPathString GetO3deLogsDirectory(); + //! Retrieves the App root path to use on the current platform //! If the optional is not engaged the AppRootPath should be calculated based //! on the location of the bootstrap.cfg file diff --git a/Code/Sandbox/Editor/CryEdit.cpp b/Code/Sandbox/Editor/CryEdit.cpp index a972a4bd9b..67e228a3ce 100644 --- a/Code/Sandbox/Editor/CryEdit.cpp +++ b/Code/Sandbox/Editor/CryEdit.cpp @@ -2891,7 +2891,7 @@ void CCryEditApp::OpenProjectManager(const AZStd::string& screen) { // provide the current project path for in case we want to update the project AZ::IO::FixedMaxPathString projectPath = AZ::Utils::GetProjectPath(); - const AZStd::string commandLineOptions = AZStd::string::format(" --screen %s --project_path %s", screen.c_str(), projectPath.c_str()); + const AZStd::string commandLineOptions = AZStd::string::format(" --screen %s --project-path %s", screen.c_str(), projectPath.c_str()); bool launchSuccess = AzFramework::ProjectManager::LaunchProjectManager(commandLineOptions); if (!launchSuccess) { diff --git a/Code/Tools/ProjectManager/CMakeLists.txt b/Code/Tools/ProjectManager/CMakeLists.txt index aeb7be9793..434ce1424e 100644 --- a/Code/Tools/ProjectManager/CMakeLists.txt +++ b/Code/Tools/ProjectManager/CMakeLists.txt @@ -20,12 +20,11 @@ if (NOT python_package_name) message(WARNING "Python was not found in the package assocation list. Did someone call ly_associate_package(xxxxxxx Python) ?") endif() + ly_add_target( - NAME ProjectManager APPLICATION - OUTPUT_NAME o3de + NAME ProjectManager.Static STATIC NAMESPACE AZ AUTOMOC - AUTORCC FILES_CMAKE project_manager_files.cmake Platform/${PAL_PLATFORM_NAME}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake @@ -47,6 +46,60 @@ ly_add_target( 3rdParty::pybind11 AZ::AzCore AZ::AzFramework - AZ::AzToolsFramework AZ::AzQtComponents -) \ No newline at end of file +) + +ly_add_target( + NAME ProjectManager APPLICATION + OUTPUT_NAME o3de + NAMESPACE AZ + AUTORCC + FILES_CMAKE + project_manager_app_files.cmake + INCLUDE_DIRECTORIES + PRIVATE + Source + BUILD_DEPENDENCIES + PRIVATE + 3rdParty::Qt::Core + 3rdParty::Qt::Concurrent + 3rdParty::Qt::Widgets + 3rdParty::Python + 3rdParty::pybind11 + AZ::AzCore + AZ::AzFramework + AZ::AzQtComponents + AZ::ProjectManager.Static +) + +if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) + ly_add_target( + NAME ProjectManager.Tests EXECUTABLE + NAMESPACE AZ + AUTORCC + FILES_CMAKE + project_manager_tests_files.cmake + Platform/${PAL_PLATFORM_NAME}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}_tests_files.cmake + INCLUDE_DIRECTORIES + PRIVATE + Source + Platform/${PAL_PLATFORM_NAME} + BUILD_DEPENDENCIES + PRIVATE + 3rdParty::Qt::Core + 3rdParty::Qt::Concurrent + 3rdParty::Qt::Widgets + 3rdParty::Python + 3rdParty::pybind11 + AZ::AzTest + AZ::AzFramework + AZ::AzFrameworkTestShared + AZ::ProjectManager.Static + ) + + ly_add_googletest( + NAME AZ::ProjectManager.Tests + TEST_COMMAND $ --unittest + ) + +endif() diff --git a/Code/Tools/ProjectManager/Platform/Linux/PAL_linux_tests_files.cmake b/Code/Tools/ProjectManager/Platform/Linux/PAL_linux_tests_files.cmake new file mode 100644 index 0000000000..e79da7183d --- /dev/null +++ b/Code/Tools/ProjectManager/Platform/Linux/PAL_linux_tests_files.cmake @@ -0,0 +1,15 @@ +# +# 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. +# + +set(FILES + ProjectManager_Test_Traits_Platform.h + ProjectManager_Test_Traits_Linux.h +) diff --git a/Code/Tools/ProjectManager/Platform/Linux/ProjectManager_Test_Traits_Linux.h b/Code/Tools/ProjectManager/Platform/Linux/ProjectManager_Test_Traits_Linux.h new file mode 100644 index 0000000000..c8b428a1c2 --- /dev/null +++ b/Code/Tools/ProjectManager/Platform/Linux/ProjectManager_Test_Traits_Linux.h @@ -0,0 +1,15 @@ +/* + * 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 + +#define AZ_TRAIT_DISABLE_FAILED_PROJECT_MANAGER_TESTS true diff --git a/Code/Tools/ProjectManager/Platform/Linux/ProjectManager_Test_Traits_Platform.h b/Code/Tools/ProjectManager/Platform/Linux/ProjectManager_Test_Traits_Platform.h new file mode 100644 index 0000000000..639ef8a387 --- /dev/null +++ b/Code/Tools/ProjectManager/Platform/Linux/ProjectManager_Test_Traits_Platform.h @@ -0,0 +1,15 @@ +/* + * 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 diff --git a/Code/Tools/ProjectManager/Platform/Mac/PAL_mac_tests_files.cmake b/Code/Tools/ProjectManager/Platform/Mac/PAL_mac_tests_files.cmake new file mode 100644 index 0000000000..a2d480de40 --- /dev/null +++ b/Code/Tools/ProjectManager/Platform/Mac/PAL_mac_tests_files.cmake @@ -0,0 +1,15 @@ +# +# 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. +# + +set(FILES + ProjectManager_Test_Traits_Platform.h + ProjectManager_Test_Traits_Mac.h +) diff --git a/Code/Tools/ProjectManager/Platform/Mac/ProjectManager_Test_Traits_Mac.h b/Code/Tools/ProjectManager/Platform/Mac/ProjectManager_Test_Traits_Mac.h new file mode 100644 index 0000000000..053db745ea --- /dev/null +++ b/Code/Tools/ProjectManager/Platform/Mac/ProjectManager_Test_Traits_Mac.h @@ -0,0 +1,15 @@ +/* + * 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 + +#define AZ_TRAIT_DISABLE_FAILED_PROJECT_MANAGER_TESTS false diff --git a/Code/Tools/ProjectManager/Platform/Mac/ProjectManager_Test_Traits_Platform.h b/Code/Tools/ProjectManager/Platform/Mac/ProjectManager_Test_Traits_Platform.h new file mode 100644 index 0000000000..af8817998f --- /dev/null +++ b/Code/Tools/ProjectManager/Platform/Mac/ProjectManager_Test_Traits_Platform.h @@ -0,0 +1,15 @@ +/* + * 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 diff --git a/Code/Tools/ProjectManager/Platform/Windows/PAL_windows_tests_files.cmake b/Code/Tools/ProjectManager/Platform/Windows/PAL_windows_tests_files.cmake new file mode 100644 index 0000000000..00d9da3db3 --- /dev/null +++ b/Code/Tools/ProjectManager/Platform/Windows/PAL_windows_tests_files.cmake @@ -0,0 +1,15 @@ +# +# 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. +# + +set(FILES + ProjectManager_Test_Traits_Platform.h + ProjectManager_Test_Traits_Windows.h +) diff --git a/Code/Tools/ProjectManager/Platform/Windows/ProjectManager_Test_Traits_Platform.h b/Code/Tools/ProjectManager/Platform/Windows/ProjectManager_Test_Traits_Platform.h new file mode 100644 index 0000000000..915a86644a --- /dev/null +++ b/Code/Tools/ProjectManager/Platform/Windows/ProjectManager_Test_Traits_Platform.h @@ -0,0 +1,15 @@ +/* + * 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 diff --git a/Code/Tools/ProjectManager/Platform/Windows/ProjectManager_Test_Traits_Windows.h b/Code/Tools/ProjectManager/Platform/Windows/ProjectManager_Test_Traits_Windows.h new file mode 100644 index 0000000000..053db745ea --- /dev/null +++ b/Code/Tools/ProjectManager/Platform/Windows/ProjectManager_Test_Traits_Windows.h @@ -0,0 +1,15 @@ +/* + * 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 + +#define AZ_TRAIT_DISABLE_FAILED_PROJECT_MANAGER_TESTS false diff --git a/Code/Tools/ProjectManager/Resources/ProjectManager.qss b/Code/Tools/ProjectManager/Resources/ProjectManager.qss index 80470591a8..efc01802b7 100644 --- a/Code/Tools/ProjectManager/Resources/ProjectManager.qss +++ b/Code/Tools/ProjectManager/Resources/ProjectManager.qss @@ -7,6 +7,11 @@ QMainWindow { margin:0; } +#ScreensCtrl { + min-width:1200px; + min-height:800px; +} + QPushButton:focus { outline: none; border:1px solid #1e70eb; diff --git a/Code/Tools/ProjectManager/Source/Application.cpp b/Code/Tools/ProjectManager/Source/Application.cpp new file mode 100644 index 0000000000..c566e76ef1 --- /dev/null +++ b/Code/Tools/ProjectManager/Source/Application.cpp @@ -0,0 +1,186 @@ +/* + * 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 +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace O3DE::ProjectManager +{ + Application::~Application() + { + TearDown(); + } + + bool Application::Init(bool interactive) + { + constexpr const char* applicationName { "O3DE" }; + + QApplication::setOrganizationName(applicationName); + QApplication::setOrganizationDomain("o3de.org"); + + QCoreApplication::setApplicationName(applicationName); + QCoreApplication::setApplicationVersion("1.0"); + + // Use the LogComponent for non-dev logging log + RegisterComponentDescriptor(AzFramework::LogComponent::CreateDescriptor()); + + // set the log alias to .o3de/Logs instead of the default user/logs + AZ::IO::FixedMaxPath path = AZ::Utils::GetO3deLogsDirectory(); + + // DevWriteStorage is where the event log is written during development + m_settingsRegistry->Set(AZ::SettingsRegistryMergeUtils::FilePathKey_DevWriteStorage, path.LexicallyNormal().Native()); + + // Save event logs to .o3de/Logs/eventlogger/EventLogO3DE.azsl + m_settingsRegistry->Set(AZ::SettingsRegistryMergeUtils::BuildTargetNameKey, applicationName); + + Start(AzFramework::Application::Descriptor()); + + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); + QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); + + QLocale::setDefault(QLocale(QLocale::English, QLocale::UnitedStates)); + + QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); + AzQtComponents::Utilities::HandleDpiAwareness(AzQtComponents::Utilities::SystemDpiAware); + + // Create the actual Qt Application - this needs to happen before using QMessageBox + m_app.reset(new QApplication(*GetArgC(), *GetArgV())); + + if(!InitLog(applicationName)) + { + AZ_Warning("ProjectManager", false, "Failed to init logging"); + } + + m_pythonBindings = AZStd::make_unique(GetEngineRoot()); + if (!m_pythonBindings || !m_pythonBindings->PythonStarted()) + { + if (interactive) + { + QMessageBox::critical(nullptr, QObject::tr("Failed to start Python"), + QObject::tr("This tool requires an O3DE engine with a Python runtime, " + "but either Python is missing or mis-configured. Please rename " + "your python/runtime folder to python/runtime_bak, then run " + "python/get_python.bat to restore the Python runtime folder.")); + } + return false; + } + + const AZ::CommandLine* commandLine = GetCommandLine(); + AZ_Assert(commandLine, "Failed to get command line"); + + ProjectManagerScreen startScreen = ProjectManagerScreen::Projects; + if (size_t screenSwitchCount = commandLine->GetNumSwitchValues("screen"); screenSwitchCount > 0) + { + QString screenOption = commandLine->GetSwitchValue("screen", screenSwitchCount - 1).c_str(); + ProjectManagerScreen screen = ProjectUtils::GetProjectManagerScreen(screenOption); + if (screen != ProjectManagerScreen::Invalid) + { + startScreen = screen; + } + } + + AZ::IO::FixedMaxPath projectPath; + if (size_t projectSwitchCount = commandLine->GetNumSwitchValues("project-path"); projectSwitchCount > 0) + { + projectPath = commandLine->GetSwitchValue("project-path", projectSwitchCount - 1).c_str(); + } + + m_mainWindow.reset(new ProjectManagerWindow(nullptr, projectPath, startScreen)); + + return true; + } + + bool Application::InitLog(const char* logName) + { + if (!m_entity) + { + // override the log alias to the O3de Logs directory instead of the default project user/Logs folder + AZ::IO::FixedMaxPath path = AZ::Utils::GetO3deLogsDirectory(); + AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance(); + AZ_Assert(fileIO, "Failed to get FileIOBase instance"); + + fileIO->SetAlias("@log@", path.LexicallyNormal().Native().c_str()); + + // this entity exists because we need a home for LogComponent + // and cannot use the system entity because we need to be able to call SetLogFileBaseName + // so the log will be named O3DE.log + m_entity = aznew AZ::Entity("Application Entity"); + if (m_entity) + { + AzFramework::LogComponent* logger = aznew AzFramework::LogComponent(); + AZ_Assert(logger, "Failed to create LogComponent"); + logger->SetLogFileBaseName(logName); + m_entity->AddComponent(logger); + m_entity->Init(); + m_entity->Activate(); + } + } + + return m_entity != nullptr; + } + + void Application::TearDown() + { + if (m_entity) + { + m_entity->Deactivate(); + delete m_entity; + m_entity = nullptr; + } + + m_pythonBindings.reset(); + m_mainWindow.reset(); + m_app.reset(); + } + + bool Application::Run() + { + // Set up the Style Manager + AzQtComponents::StyleManager styleManager(qApp); + styleManager.initialize(qApp, GetEngineRoot()); + + // setup stylesheets and hot reloading + AZ::IO::FixedMaxPath engineRoot(GetEngineRoot()); + QDir rootDir(engineRoot.c_str()); + const auto pathOnDisk = rootDir.absoluteFilePath("Code/Tools/ProjectManager/Resources"); + const auto qrcPath = QStringLiteral(":/ProjectManager/style"); + AzQtComponents::StyleManager::addSearchPaths("style", pathOnDisk, qrcPath, engineRoot); + + // set stylesheet after creating the main window or their styles won't get updated + AzQtComponents::StyleManager::setStyleSheet(m_mainWindow.data(), QStringLiteral("style:ProjectManager.qss")); + + // the decoration wrapper is intended to remember window positioning and sizing + auto wrapper = new AzQtComponents::WindowDecorationWrapper(); + wrapper->setGuest(m_mainWindow.data()); + wrapper->show(); + m_mainWindow->show(); + + qApp->setQuitOnLastWindowClosed(true); + + // Run the application + return qApp->exec(); + } + +} diff --git a/Code/Tools/ProjectManager/Source/Application.h b/Code/Tools/ProjectManager/Source/Application.h new file mode 100644 index 0000000000..d4e94e8dd4 --- /dev/null +++ b/Code/Tools/ProjectManager/Source/Application.h @@ -0,0 +1,48 @@ +/* + * 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 +#include +#include +#include +#endif + +namespace AZ +{ + class Entity; +} + +namespace O3DE::ProjectManager +{ + class Application + : public AzFramework::Application + { + public: + using AzFramework::Application::Application; + virtual ~Application(); + + bool Init(bool interactive = true); + bool Run(); + void TearDown(); + + private: + bool InitLog(const char* logName); + + AZStd::unique_ptr m_pythonBindings; + QSharedPointer m_app; + QSharedPointer m_mainWindow; + + AZ::Entity* m_entity = nullptr; + }; +} diff --git a/Code/Tools/ProjectManager/Source/EngineSettingsScreen.cpp b/Code/Tools/ProjectManager/Source/EngineSettingsScreen.cpp index 6342041da4..cf597745ea 100644 --- a/Code/Tools/ProjectManager/Source/EngineSettingsScreen.cpp +++ b/Code/Tools/ProjectManager/Source/EngineSettingsScreen.cpp @@ -25,7 +25,7 @@ namespace O3DE::ProjectManager EngineSettingsScreen::EngineSettingsScreen(QWidget* parent) : ScreenWidget(parent) { - auto* layout = new QVBoxLayout(this); + auto* layout = new QVBoxLayout(); layout->setAlignment(Qt::AlignTop); setObjectName("engineSettingsScreen"); diff --git a/Code/Tools/ProjectManager/Source/ProjectButtonWidget.cpp b/Code/Tools/ProjectManager/Source/ProjectButtonWidget.cpp index 761572ffa5..3bde0a310d 100644 --- a/Code/Tools/ProjectManager/Source/ProjectButtonWidget.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectButtonWidget.cpp @@ -33,7 +33,7 @@ namespace O3DE::ProjectManager { setObjectName("labelButton"); - QVBoxLayout* vLayout = new QVBoxLayout(this); + QVBoxLayout* vLayout = new QVBoxLayout(); vLayout->setContentsMargins(0, 0, 0, 0); vLayout->setSpacing(5); diff --git a/Code/Tools/ProjectManager/Source/ProjectManagerWindow.cpp b/Code/Tools/ProjectManager/Source/ProjectManagerWindow.cpp index cb1398cc61..59be0aaa35 100644 --- a/Code/Tools/ProjectManager/Source/ProjectManagerWindow.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectManagerWindow.cpp @@ -13,21 +13,11 @@ #include #include -#include -#include -#include -#include -#include - -#include - namespace O3DE::ProjectManager { - ProjectManagerWindow::ProjectManagerWindow(QWidget* parent, const AZ::IO::PathView& engineRootPath, const AZ::IO::PathView& projectPath, ProjectManagerScreen startScreen) + ProjectManagerWindow::ProjectManagerWindow(QWidget* parent, const AZ::IO::PathView& projectPath, ProjectManagerScreen startScreen) : QMainWindow(parent) { - m_pythonBindings = AZStd::make_unique(engineRootPath); - setWindowTitle(tr("O3DE Project Manager")); ScreensCtrl* screensCtrl = new ScreensCtrl(); @@ -44,15 +34,6 @@ namespace O3DE::ProjectManager setCentralWidget(screensCtrl); - // setup stylesheets and hot reloading - QDir rootDir = QString::fromUtf8(engineRootPath.Native().data(), aznumeric_cast(engineRootPath.Native().size())); - const auto pathOnDisk = rootDir.absoluteFilePath("Code/Tools/ProjectManager/Resources"); - const auto qrcPath = QStringLiteral(":/ProjectManager/style"); - AzQtComponents::StyleManager::addSearchPaths("style", pathOnDisk, qrcPath, engineRootPath); - - // set stylesheet after creating the screens or their styles won't get updated - AzQtComponents::StyleManager::setStyleSheet(this, QStringLiteral("style:ProjectManager.qss")); - // always push the projects screen first so we have something to come back to if (startScreen != ProjectManagerScreen::Projects) { @@ -66,10 +47,4 @@ namespace O3DE::ProjectManager emit screensCtrl->NotifyCurrentProject(path); } } - - ProjectManagerWindow::~ProjectManagerWindow() - { - m_pythonBindings.reset(); - } - } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/ProjectManagerWindow.h b/Code/Tools/ProjectManager/Source/ProjectManagerWindow.h index 758af8fc00..db2b1fd304 100644 --- a/Code/Tools/ProjectManager/Source/ProjectManagerWindow.h +++ b/Code/Tools/ProjectManager/Source/ProjectManagerWindow.h @@ -13,7 +13,7 @@ #if !defined(Q_MOC_RUN) #include -#include +#include #include #endif @@ -25,12 +25,8 @@ namespace O3DE::ProjectManager Q_OBJECT public: - explicit ProjectManagerWindow(QWidget* parent, const AZ::IO::PathView& engineRootPath, const AZ::IO::PathView& projectPath, + explicit ProjectManagerWindow(QWidget* parent, const AZ::IO::PathView& projectPath, ProjectManagerScreen startScreen = ProjectManagerScreen::Projects); - ~ProjectManagerWindow(); - - private: - AZStd::unique_ptr m_pythonBindings; }; } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/ProjectSettingsScreen.cpp b/Code/Tools/ProjectManager/Source/ProjectSettingsScreen.cpp index 26711753d4..b198724353 100644 --- a/Code/Tools/ProjectManager/Source/ProjectSettingsScreen.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectSettingsScreen.cpp @@ -37,7 +37,7 @@ namespace O3DE::ProjectManager // if we don't set this in a frame (just use a sub-layout) all the content will align incorrectly horizontally QFrame* projectSettingsFrame = new QFrame(this); projectSettingsFrame->setObjectName("projectSettings"); - m_verticalLayout = new QVBoxLayout(this); + m_verticalLayout = new QVBoxLayout(); // you cannot remove content margins in qss m_verticalLayout->setContentsMargins(0, 0, 0, 0); diff --git a/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp b/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp index 8e41e52643..6633558406 100644 --- a/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp @@ -85,7 +85,7 @@ namespace O3DE::ProjectManager QFrame* frame = new QFrame(this); frame->setObjectName("firstTimeContent"); { - QVBoxLayout* layout = new QVBoxLayout(this); + QVBoxLayout* layout = new QVBoxLayout(); layout->setContentsMargins(0, 0, 0, 0); layout->setAlignment(Qt::AlignTop); frame->setLayout(layout); @@ -100,7 +100,7 @@ namespace O3DE::ProjectManager "available by downloading our sample project.")); layout->addWidget(introLabel); - QHBoxLayout* buttonLayout = new QHBoxLayout(this); + QHBoxLayout* buttonLayout = new QHBoxLayout(); buttonLayout->setAlignment(Qt::AlignLeft); buttonLayout->setSpacing(s_spacerSize); diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.cpp b/Code/Tools/ProjectManager/Source/PythonBindings.cpp index bb6c05a472..0e00319b6b 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.cpp +++ b/Code/Tools/ProjectManager/Source/PythonBindings.cpp @@ -226,7 +226,7 @@ namespace O3DE::ProjectManager PythonBindings::PythonBindings(const AZ::IO::PathView& enginePath) : m_enginePath(enginePath) { - StartPython(); + m_pythonStarted = StartPython(); } PythonBindings::~PythonBindings() @@ -234,6 +234,11 @@ namespace O3DE::ProjectManager StopPython(); } + bool PythonBindings::PythonStarted() + { + return m_pythonStarted && Py_IsInitialized(); + } + bool PythonBindings::StartPython() { if (Py_IsInitialized()) @@ -246,7 +251,7 @@ namespace O3DE::ProjectManager AZStd::string pyBasePath = Platform::GetPythonHomePath(PY_PACKAGE, m_enginePath.c_str()); if (!AZ::IO::SystemFile::Exists(pyBasePath.c_str())) { - AZ_Assert(false, "Python home path must exist. path:%s", pyBasePath.c_str()); + AZ_Error("python", false, "Python home path does not exist: %s", pyBasePath.c_str()); return false; } @@ -351,6 +356,11 @@ namespace O3DE::ProjectManager AZ::Outcome PythonBindings::ExecuteWithLockErrorHandling(AZStd::function executionCallback) { + if (!Py_IsInitialized()) + { + return AZ::Failure("Python is not initialized"); + } + AZStd::lock_guard lock(m_lock); pybind11::gil_scoped_release release; pybind11::gil_scoped_acquire acquire; diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.h b/Code/Tools/ProjectManager/Source/PythonBindings.h index 5700ede850..065867a130 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.h +++ b/Code/Tools/ProjectManager/Source/PythonBindings.h @@ -34,6 +34,8 @@ namespace O3DE::ProjectManager ~PythonBindings() override; // PythonBindings overrides + bool PythonStarted() override; + // Engine AZ::Outcome GetEngineInfo() override; bool SetEngineInfo(const EngineInfo& engineInfo) override; @@ -70,6 +72,8 @@ namespace O3DE::ProjectManager bool StopPython(); + bool m_pythonStarted = false; + AZ::IO::FixedMaxPath m_enginePath; pybind11::handle m_engineTemplate; AZStd::recursive_mutex m_lock; diff --git a/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h b/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h index bc20d8e3f0..6d72bfee0c 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h +++ b/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h @@ -34,6 +34,12 @@ namespace O3DE::ProjectManager IPythonBindings() = default; virtual ~IPythonBindings() = default; + /** + * Get whether Python was started or not. All Python functionality will fail if Python + * failed to start. + * @return true if Python was started successfully, false on failure + */ + virtual bool PythonStarted() = 0; // Engine diff --git a/Code/Tools/ProjectManager/Source/main.cpp b/Code/Tools/ProjectManager/Source/main.cpp index c597b8a729..1f4cadfb14 100644 --- a/Code/Tools/ProjectManager/Source/main.cpp +++ b/Code/Tools/ProjectManager/Source/main.cpp @@ -10,85 +10,26 @@ * */ -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -using namespace O3DE::ProjectManager; +#include +#include int main(int argc, char* argv[]) { - QApplication::setOrganizationName("O3DE"); - QApplication::setOrganizationDomain("o3de.org"); - QCoreApplication::setApplicationName("ProjectManager"); - QCoreApplication::setApplicationVersion("1.0"); - - QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); - QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); - QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); - QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); - AzQtComponents::Utilities::HandleDpiAwareness(AzQtComponents::Utilities::SystemDpiAware); - - AZ::AllocatorInstance::Create(); int runSuccess = 0; + + // Call before using any Qt, or the app may not be able to locate Qt libs + AzQtComponents::PrepareQtPaths(); + + O3DE::ProjectManager::Application application(&argc, &argv); + if (!application.Init()) { - QApplication app(argc, argv); - - // Need to use settings registry to get EngineRootFolder - AZ::IO::FixedMaxPath engineRootPath; - { - AZ::ComponentApplication componentApplication; - auto settingsRegistry = AZ::SettingsRegistry::Get(); - settingsRegistry->Get(engineRootPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder); - } - - AzQtComponents::StyleManager styleManager(&app); - styleManager.initialize(&app, engineRootPath); - - // Get the initial start screen if one is provided via command line - constexpr char optionPrefix[] = "--"; - AZ::CommandLine commandLine(optionPrefix); - commandLine.Parse(argc, argv); - - ProjectManagerScreen startScreen = ProjectManagerScreen::Projects; - if(commandLine.HasSwitch("screen")) - { - QString screenOption = commandLine.GetSwitchValue("screen", 0).c_str(); - ProjectManagerScreen screen = ProjectUtils::GetProjectManagerScreen(screenOption); - if (screen != ProjectManagerScreen::Invalid) - { - startScreen = screen; - } - } - - AZ::IO::FixedMaxPath projectPath; - if (commandLine.HasSwitch("project-path")) - { - projectPath = commandLine.GetSwitchValue("project-path", 0).c_str(); - } - - ProjectManagerWindow window(nullptr, engineRootPath, projectPath, startScreen); - window.show(); - - // somethings is preventing us from moving the window to the center of the - // primary screen - likely an Az style or component helper - constexpr int width = 1200; - constexpr int height = 800; - window.resize(width, height); - - runSuccess = app.exec(); + AZ_Error("ProjectManager", false, "Failed to initialize"); + runSuccess = 1; + } + else + { + runSuccess = application.Run() ? 0 : 1; } - AZ::AllocatorInstance::Destroy(); return runSuccess; } diff --git a/Code/Tools/ProjectManager/project_manager_app_files.cmake b/Code/Tools/ProjectManager/project_manager_app_files.cmake new file mode 100644 index 0000000000..223683ddd9 --- /dev/null +++ b/Code/Tools/ProjectManager/project_manager_app_files.cmake @@ -0,0 +1,17 @@ +# +# 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. +# + +set(FILES + Resources/ProjectManager.rc + Resources/ProjectManager.qrc + Resources/ProjectManager.qss + Source/main.cpp +) diff --git a/Code/Tools/ProjectManager/project_manager_files.cmake b/Code/Tools/ProjectManager/project_manager_files.cmake index 633824f995..587b5907bb 100644 --- a/Code/Tools/ProjectManager/project_manager_files.cmake +++ b/Code/Tools/ProjectManager/project_manager_files.cmake @@ -1,4 +1,5 @@ # +# # All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or # its licensors. # @@ -10,10 +11,8 @@ # set(FILES - Resources/ProjectManager.rc - Resources/ProjectManager.qrc - Resources/ProjectManager.qss - Source/main.cpp + Source/Application.h + Source/Application.cpp Source/ScreenDefs.h Source/ScreenFactory.h Source/ScreenFactory.cpp diff --git a/Code/Tools/ProjectManager/project_manager_tests_files.cmake b/Code/Tools/ProjectManager/project_manager_tests_files.cmake new file mode 100644 index 0000000000..e1e84a43a7 --- /dev/null +++ b/Code/Tools/ProjectManager/project_manager_tests_files.cmake @@ -0,0 +1,17 @@ +# +# 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. +# + +set(FILES + Resources/ProjectManager.qrc + Resources/ProjectManager.qss + tests/ApplicationTests.cpp + tests/main.cpp +) diff --git a/Code/Tools/ProjectManager/tests/ApplicationTests.cpp b/Code/Tools/ProjectManager/tests/ApplicationTests.cpp new file mode 100644 index 0000000000..c98b1a3a6f --- /dev/null +++ b/Code/Tools/ProjectManager/tests/ApplicationTests.cpp @@ -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. +* +*/ + +#include +#include +#include +#include + +namespace O3DE::ProjectManager +{ + class ProjectManagerApplicationTests + : public ::UnitTest::ScopedAllocatorSetupFixture + { + public: + + ProjectManagerApplicationTests() + { + m_application = AZStd::make_unique(); + } + + ~ProjectManagerApplicationTests() + { + m_application.reset(); + } + + AZStd::unique_ptr m_application; + }; + +#if AZ_TRAIT_DISABLE_FAILED_PROJECT_MANAGER_TESTS + TEST_F(ProjectManagerApplicationTests, DISABLED_Application_Init_Succeeds) +#else + TEST_F(ProjectManagerApplicationTests, Application_Init_Succeeds) +#endif // !AZ_TRAIT_DISABLE_FAILED_PROJECT_MANAGER_TESTS + { + // we don't want to interact with actual GUI or display it + EXPECT_TRUE(m_application->Init(/*interactive=*/false)); + } +} diff --git a/Code/Tools/ProjectManager/tests/main.cpp b/Code/Tools/ProjectManager/tests/main.cpp new file mode 100644 index 0000000000..191bef846a --- /dev/null +++ b/Code/Tools/ProjectManager/tests/main.cpp @@ -0,0 +1,35 @@ +/* +* 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 + +DECLARE_AZ_UNIT_TEST_MAIN(); + +int runDefaultRunner(int argc, char* argv[]) +{ + INVOKE_AZ_UNIT_TEST_MAIN(nullptr) + return 0; +} + +int main(int argc, char* argv[]) +{ + if (argc == 1) + { + // if no parameters are provided, add the --unittests parameter + constexpr int defaultArgc = 2; + char unittest_arg[] = "--unittests"; // Conversion from string literal to char* is not allowed per ISO C++11 + char* defaultArgv[defaultArgc] = { argv[0], unittest_arg }; + return runDefaultRunner(defaultArgc, defaultArgv); + } + INVOKE_AZ_UNIT_TEST_MAIN(nullptr); + return 0; +} From 5165f6ad0495cbc310f64c6294a2fe797f84f578 Mon Sep 17 00:00:00 2001 From: Ken Pruiksma Date: Mon, 14 Jun 2021 19:09:27 -0500 Subject: [PATCH 092/116] [ATOM-15769] Setting minimum angle to 0.5 degrees on disk lights to avoid visual artifacts that occur at values closer to 0. Also updating the outer cone angle max to be 90 degrees since it's measured from the center point, not all the way across. (#1260) --- .../Code/Source/CoreLights/EditorAreaLightComponent.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp index 69bec21a6c..992b6319d8 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp @@ -112,13 +112,13 @@ namespace AZ ->DataElement(Edit::UIHandlers::Default, &AreaLightComponentConfig::m_enableShutters, "Enable shutters", "Restrict the light to a specific beam angle depending on shape.") ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::ShuttersMustBeEnabled) ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_innerShutterAngleDegrees, "Inner angle", "The inner angle of the shutters where the light beam begins to be occluded.") - ->Attribute(Edit::Attributes::Min, 0.0f) - ->Attribute(Edit::Attributes::Max, 180.0f) + ->Attribute(Edit::Attributes::Min, 0.5f) + ->Attribute(Edit::Attributes::Max, 90.0f) ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShutters) ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::ShuttersDisabled) ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_outerShutterAngleDegrees, "Outer angle", "The outer angle of the shutters where the light beam is completely occluded.") - ->Attribute(Edit::Attributes::Min, 0.0f) - ->Attribute(Edit::Attributes::Max, 180.0f) + ->Attribute(Edit::Attributes::Min, 0.5f) + ->Attribute(Edit::Attributes::Max, 90.0f) ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShutters) ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::ShuttersDisabled) From 0198f6121ba871022667cfb31e00ca6a1fef864b Mon Sep 17 00:00:00 2001 From: rgba16f <82187279+rgba16f@users.noreply.github.com> Date: Mon, 14 Jun 2021 20:29:37 -0500 Subject: [PATCH 093/116] Rebind the DebugDisplayRequestBus Instance to handle drawing in GameMode. (#1275) --- Code/Sandbox/Editor/EditorViewportWidget.cpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/Code/Sandbox/Editor/EditorViewportWidget.cpp b/Code/Sandbox/Editor/EditorViewportWidget.cpp index 7e087d452b..e627d7d7c0 100644 --- a/Code/Sandbox/Editor/EditorViewportWidget.cpp +++ b/Code/Sandbox/Editor/EditorViewportWidget.cpp @@ -514,18 +514,28 @@ void EditorViewportWidget::Update() // Disable rendering to avoid recursion into Update() PushDisableRendering(); + + //get debug display interface for the viewport + AzFramework::DebugDisplayRequestBus::BusPtr debugDisplayBus; + AzFramework::DebugDisplayRequestBus::Bind(debugDisplayBus, GetViewportId()); + AZ_Assert(debugDisplayBus, "Invalid DebugDisplayRequestBus."); + + AzFramework::DebugDisplayRequests* debugDisplay = + AzFramework::DebugDisplayRequestBus::FindFirstHandler(debugDisplayBus); + + // draw debug visualizations - if (m_debugDisplay) + if (debugDisplay) { - const AZ::u32 prevState = m_debugDisplay->GetState(); - m_debugDisplay->SetState( + const AZ::u32 prevState = debugDisplay->GetState(); + debugDisplay->SetState( e_Mode3D | e_AlphaBlended | e_FillModeSolid | e_CullModeBack | e_DepthWriteOn | e_DepthTestOn); AzFramework::EntityDebugDisplayEventBus::Broadcast( &AzFramework::EntityDebugDisplayEvents::DisplayEntityViewport, - AzFramework::ViewportInfo{ GetViewportId() }, *m_debugDisplay); + AzFramework::ViewportInfo{ GetViewportId() }, *debugDisplay); - m_debugDisplay->SetState(prevState); + debugDisplay->SetState(prevState); } QtViewport::Update(); From de4605d6b72cd3729ae5dfab9880f70c89657c7b Mon Sep 17 00:00:00 2001 From: Doug McDiarmid Date: Mon, 14 Jun 2021 18:31:43 -0700 Subject: [PATCH 094/116] Added comment. --- .../ReflectionScreenSpaceCompositePass.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceCompositePass.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceCompositePass.cpp index fe2030ca7e..ab09d7175a 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceCompositePass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceCompositePass.cpp @@ -42,6 +42,9 @@ namespace AZ if (!passes.empty()) { Render::ReflectionScreenSpaceBlurPass* blurPass = azrtti_cast(passes.front()); + + // compute the max mip level based on the available mips in the previous frame image, and capping it + // to stay within a range that has reasonable data const uint32_t MaxNumRoughnessMips = 8; uint32_t maxMipLevel = AZStd::min(MaxNumRoughnessMips, blurPass->GetNumBlurMips()) - 1; From 1f6bb14ed3680cb721ec7c276b754073cc1a7498 Mon Sep 17 00:00:00 2001 From: Roman <69218254+amzn-rhhong@users.noreply.github.com> Date: Mon, 14 Jun 2021 20:38:37 -0700 Subject: [PATCH 095/116] [EMFX][ATOM] crash during mesh reload (#1301) * Fixed a crash when entering game mode, removing a mesh and re-adding mesh. --- .../Code/Source/SkinnedMesh/SkinnedMeshInputBuffers.cpp | 5 +++++ .../EMotionFXAtom/Code/Source/ActorAsset.cpp | 3 ++- .../EMotionFXAtom/Code/Source/AtomActorInstance.cpp | 3 +-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshInputBuffers.cpp b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshInputBuffers.cpp index 343370ae35..a87d272448 100644 --- a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshInputBuffers.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshInputBuffers.cpp @@ -629,6 +629,11 @@ namespace AZ Data::Asset lodAsset; modelLodCreator.End(lodAsset); + if (!lodAsset.IsReady()) + { + // [GFX TODO] During mesh reload the modelLodCreator could report errors and result in the lodAsset not ready. + return nullptr; + } modelCreator.AddLodAsset(AZStd::move(lodAsset)); lodIndex++; diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/ActorAsset.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/ActorAsset.cpp index 9f68a7d12c..1c4657d8df 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/ActorAsset.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/ActorAsset.cpp @@ -311,7 +311,8 @@ namespace AZ Data::Asset modelAsset = actor->GetMeshAsset(); if (!modelAsset.IsReady()) { - AZ_Error("CreateSkinnedMeshInputFromActor", false, "Attempting to create skinned mesh input buffers for an actor that doesn't have a loaded model."); + AZ_Warning("CreateSkinnedMeshInputFromActor", false, "Check if the actor has a mesh added. Right click the source file in the asset browser, click edit settings, " + "and navigate to the Meshes tab. Add a mesh if it's missing."); return nullptr; } diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp index 532c8720b5..18a21c93a6 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp @@ -456,9 +456,8 @@ namespace AZ void AtomActorInstance::Create() { Destroy(); - m_skinnedMeshInputBuffers = GetRenderActor()->FindOrCreateSkinnedMeshInputBuffers(); - AZ_Error("AtomActorInstance", m_skinnedMeshInputBuffers, "Failed to get SkinnedMeshInputBuffers from Actor."); + AZ_Warning("AtomActorInstance", m_skinnedMeshInputBuffers, "Failed to create SkinnedMeshInputBuffers from Actor. It is likely that this actor doesn't have any meshes"); if (m_skinnedMeshInputBuffers) { m_boneTransforms = CreateBoneTransformBufferFromActorInstance(m_actorInstance, GetSkinningMethod()); From 74e922a4013a367269797f2948143b92c05ce5b8 Mon Sep 17 00:00:00 2001 From: Benjamin Jillich <43751992+amzn-jillich@users.noreply.github.com> Date: Tue, 15 Jun 2021 17:44:57 +0200 Subject: [PATCH 097/116] Compile fix in the editor actor component for release build (#1327) --- .../Integration/Editor/Components/EditorActorComponent.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.cpp index 5c085e96f7..039815fa44 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.cpp @@ -459,8 +459,7 @@ namespace EMotionFX void EditorActorComponent::OnAssetReady(AZ::Data::Asset asset) { m_actorAsset = asset; - Actor* actor = m_actorAsset->GetActor(); - AZ_Assert(m_actorAsset.IsReady() && actor, "Actor asset should be loaded and actor valid."); + AZ_Assert(m_actorAsset.IsReady() && m_actorAsset->GetActor(), "Actor asset should be loaded and actor valid."); CheckActorCreation(); } From cdce00bf3578fda62969d9062babae698c5df7d2 Mon Sep 17 00:00:00 2001 From: galibzon <66021303+galibzon@users.noreply.github.com> Date: Tue, 15 Jun 2021 10:58:09 -0500 Subject: [PATCH 098/116] [ATOM-13770] [Shaders] - Root Constants need to be padded to be 16 byte (#1326) aligned. AZSLc v1.7.22 now has command line option "--pad-root-const": Automatically append padding data to the root constant CB to keep it aligned to 16-byte boundary. Signed-off-by: garrieta --- cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake | 2 +- cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake index f85048d13e..3908d21ecf 100644 --- a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake +++ b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake @@ -26,7 +26,7 @@ ly_associate_package(PACKAGE_NAME lz4-r128-multiplatform ly_associate_package(PACKAGE_NAME expat-2.1.0-multiplatform TARGETS expat PACKAGE_HASH 452256acd1fd699cef24162575b3524fccfb712f5321c83f1df1ce878de5b418) ly_associate_package(PACKAGE_NAME zstd-1.35-multiplatform TARGETS zstd PACKAGE_HASH 45d466c435f1095898578eedde85acf1fd27190e7ea99aeaa9acfd2f09e12665) ly_associate_package(PACKAGE_NAME SQLite-3.32.2-rev3-multiplatform TARGETS SQLite PACKAGE_HASH dd4d3de6cbb4ce3d15fc504ba0ae0587e515dc89a25228037035fc0aef4831f4) -ly_associate_package(PACKAGE_NAME azslc-1.7.21-rev1-multiplatform TARGETS azslc PACKAGE_HASH 772b7a2d9cc68aa1da4f0ee7db57ee1b4e7a8f20b81961fc5849af779582f4df) +ly_associate_package(PACKAGE_NAME azslc-1.7.22-rev1-multiplatform TARGETS azslc PACKAGE_HASH 71b4545d221d4fcd564ccc121c249a8f8f164bcc616faf146f926c3d5c78d527) ly_associate_package(PACKAGE_NAME glad-2.0.0-beta-rev2-multiplatform TARGETS glad PACKAGE_HASH ff97ee9664e97d0854b52a3734c2289329d9f2b4cd69478df6d0ca1f1c9392ee) ly_associate_package(PACKAGE_NAME lux_core-2.2-rev5-multiplatform TARGETS lux_core PACKAGE_HASH c8c13cf7bc351643e1abd294d0841b24dee60e51647dff13db7aec396ad1e0b5) ly_associate_package(PACKAGE_NAME xxhash-0.7.4-rev1-multiplatform TARGETS xxhash PACKAGE_HASH e81f3e6c4065975833996dd1fcffe46c3cf0f9e3a4207ec5f4a1b564ba75861e) diff --git a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake index 1a2cfa4049..19e71f726c 100644 --- a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake +++ b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake @@ -26,7 +26,7 @@ ly_associate_package(PACKAGE_NAME lz4-r128-multiplatform ly_associate_package(PACKAGE_NAME expat-2.1.0-multiplatform TARGETS expat PACKAGE_HASH 452256acd1fd699cef24162575b3524fccfb712f5321c83f1df1ce878de5b418) ly_associate_package(PACKAGE_NAME zstd-1.35-multiplatform TARGETS zstd PACKAGE_HASH 45d466c435f1095898578eedde85acf1fd27190e7ea99aeaa9acfd2f09e12665) ly_associate_package(PACKAGE_NAME SQLite-3.32.2-rev3-multiplatform TARGETS SQLite PACKAGE_HASH dd4d3de6cbb4ce3d15fc504ba0ae0587e515dc89a25228037035fc0aef4831f4) -ly_associate_package(PACKAGE_NAME azslc-1.7.21-rev1-multiplatform TARGETS azslc PACKAGE_HASH 772b7a2d9cc68aa1da4f0ee7db57ee1b4e7a8f20b81961fc5849af779582f4df) +ly_associate_package(PACKAGE_NAME azslc-1.7.22-rev1-multiplatform TARGETS azslc PACKAGE_HASH 71b4545d221d4fcd564ccc121c249a8f8f164bcc616faf146f926c3d5c78d527) ly_associate_package(PACKAGE_NAME glad-2.0.0-beta-rev2-multiplatform TARGETS glad PACKAGE_HASH ff97ee9664e97d0854b52a3734c2289329d9f2b4cd69478df6d0ca1f1c9392ee) ly_associate_package(PACKAGE_NAME lux_core-2.2-rev5-multiplatform TARGETS lux_core PACKAGE_HASH c8c13cf7bc351643e1abd294d0841b24dee60e51647dff13db7aec396ad1e0b5) ly_associate_package(PACKAGE_NAME xxhash-0.7.4-rev1-multiplatform TARGETS xxhash PACKAGE_HASH e81f3e6c4065975833996dd1fcffe46c3cf0f9e3a4207ec5f4a1b564ba75861e) From 0241538c4721cdc3ae91097fcc1c683590fd0ed9 Mon Sep 17 00:00:00 2001 From: Steve Pham <82231385+spham-amzn@users.noreply.github.com> Date: Tue, 15 Jun 2021 09:19:29 -0700 Subject: [PATCH 099/116] Fix Android Startup Error related to bootstrap's project_path being in the target deployed bootstrap path (#1322) * Add '/Amazon/AzCore/Bootstrap/project_path' to setregbuilder.assetprocessor.setreg/Amazon/AssetBuilder/Excludes --- Registry/setregbuilder.assetprocessor.setreg | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Registry/setregbuilder.assetprocessor.setreg b/Registry/setregbuilder.assetprocessor.setreg index 4be46a9d51..5dc6f42446 100644 --- a/Registry/setregbuilder.assetprocessor.setreg +++ b/Registry/setregbuilder.assetprocessor.setreg @@ -22,7 +22,8 @@ // members or entries will be recursively ignored as well. "Excludes": [ - "/Amazon/AzCore/Runtime" + "/Amazon/AzCore/Runtime", + "/Amazon/AzCore/Bootstrap/project_path" ] } } From 62f3c93c684c7cb6a594693f3849d225cba12016 Mon Sep 17 00:00:00 2001 From: Aaron Ruiz Mora Date: Tue, 15 Jun 2021 17:51:15 +0100 Subject: [PATCH 100/116] Fixed HelpPageURL links in physics components (#1328) --- Gems/Blast/Code/Source/Editor/EditorBlastFamilyComponent.cpp | 2 +- Gems/Blast/Code/Source/Editor/EditorBlastMeshDataComponent.cpp | 2 +- Gems/NvCloth/Code/Source/Components/EditorClothComponent.cpp | 2 +- Gems/PhysX/Code/Source/EditorColliderComponent.cpp | 2 +- Gems/PhysX/Code/Source/EditorForceRegionComponent.cpp | 2 +- Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Gems/Blast/Code/Source/Editor/EditorBlastFamilyComponent.cpp b/Gems/Blast/Code/Source/Editor/EditorBlastFamilyComponent.cpp index 873ef7248d..0133690cea 100644 --- a/Gems/Blast/Code/Source/Editor/EditorBlastFamilyComponent.cpp +++ b/Gems/Blast/Code/Source/Editor/EditorBlastFamilyComponent.cpp @@ -44,7 +44,7 @@ namespace Blast ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute( AZ::Edit::Attributes::HelpPageURL, - "https://docs.aws.amazon.com/lumberyard/latest/userguide/component-blast-actor.html") + "https://docs.o3de.org/docs/user-guide/components/reference/blast-family/") ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ->DataElement( AZ::Edit::UIHandlers::Default, &EditorBlastFamilyComponent::m_blastAsset, "Blast asset", diff --git a/Gems/Blast/Code/Source/Editor/EditorBlastMeshDataComponent.cpp b/Gems/Blast/Code/Source/Editor/EditorBlastMeshDataComponent.cpp index 77788b6aee..4a6f41331b 100644 --- a/Gems/Blast/Code/Source/Editor/EditorBlastMeshDataComponent.cpp +++ b/Gems/Blast/Code/Source/Editor/EditorBlastMeshDataComponent.cpp @@ -67,7 +67,7 @@ namespace Blast ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute( AZ::Edit::Attributes::HelpPageURL, - "https://docs.aws.amazon.com/lumberyard/latest/userguide/component-blast-actor.html") + "https://docs.o3de.org/docs/user-guide/components/reference/blast-family-mesh-data/") ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ->DataElement( AZ::Edit::UIHandlers::CheckBox, &EditorBlastMeshDataComponent::m_showMeshAssets, diff --git a/Gems/NvCloth/Code/Source/Components/EditorClothComponent.cpp b/Gems/NvCloth/Code/Source/Components/EditorClothComponent.cpp index 7da677a7eb..7eb07f46d7 100644 --- a/Gems/NvCloth/Code/Source/Components/EditorClothComponent.cpp +++ b/Gems/NvCloth/Code/Source/Components/EditorClothComponent.cpp @@ -52,7 +52,7 @@ namespace NvCloth ->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Cloth.svg") ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Cloth.svg") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://docs.aws.amazon.com/lumberyard/latest/userguide/component-cloth.html") + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://docs.o3de.org/docs/user-guide/components/reference/cloth/") ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ->UIElement(AZ::Edit::UIHandlers::CheckBox, "Simulate in editor", diff --git a/Gems/PhysX/Code/Source/EditorColliderComponent.cpp b/Gems/PhysX/Code/Source/EditorColliderComponent.cpp index 0671e3e77e..3cb931d148 100644 --- a/Gems/PhysX/Code/Source/EditorColliderComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorColliderComponent.cpp @@ -194,7 +194,7 @@ namespace PhysX ->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/PhysXCollider.svg") ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/PhysXCollider.svg") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "http://docs.aws.amazon.com/console/lumberyard/component/physx/collider") + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://docs.o3de.org/docs/user-guide/components/reference/physx-collider/") ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ->DataElement(AZ::Edit::UIHandlers::Default, &EditorColliderComponent::m_configuration, "Collider Configuration", "Configuration of the collider") ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) diff --git a/Gems/PhysX/Code/Source/EditorForceRegionComponent.cpp b/Gems/PhysX/Code/Source/EditorForceRegionComponent.cpp index 770200cda0..b783ea3185 100644 --- a/Gems/PhysX/Code/Source/EditorForceRegionComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorForceRegionComponent.cpp @@ -176,7 +176,7 @@ namespace PhysX ->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/ForceRegion.png") ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/ForceRegion.png") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://docs.aws.amazon.com/console/lumberyard/physx/force-region") + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://docs.o3de.org/docs/user-guide/components/reference/physx-force-region/") ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ->Attribute(AZ::Edit::Attributes::RequiredService, AZ_CRC("PhysXTriggerService", 0x3a117d7b)) ->DataElement(AZ::Edit::UIHandlers::Default, &EditorForceRegionComponent::m_visibleInEditor, "Visible", "Always show the component in viewport") diff --git a/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp b/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp index f68c4d17d8..588b1d918f 100644 --- a/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp @@ -309,7 +309,7 @@ namespace PhysX ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/PhysXRigidBody.svg") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://docs.aws.amazon.com/console/lumberyard/components/physx/rigid-body") + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://docs.o3de.org/docs/user-guide/components/reference/physx-rigid-body-physics/") ->DataElement(0, &EditorRigidBodyComponent::m_config, "Configuration", "Configuration for rigid body physics.") ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorRigidBodyComponent::CreateEditorWorldRigidBody) From 04bf6c3689391a8e02df2617cc10bce2de517ee1 Mon Sep 17 00:00:00 2001 From: puvvadar Date: Tue, 15 Jun 2021 10:14:02 -0700 Subject: [PATCH 101/116] Separate out session validation into its own packet --- .../AutoGen/Multiplayer.AutoPackets.xml | 5 +- .../Source/MultiplayerSystemComponent.cpp | 51 +++++++++++-------- .../Code/Source/MultiplayerSystemComponent.h | 1 + 3 files changed, 34 insertions(+), 23 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/AutoGen/Multiplayer.AutoPackets.xml b/Gems/Multiplayer/Code/Source/AutoGen/Multiplayer.AutoPackets.xml index ce8931107f..3abd2a86d9 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/Multiplayer.AutoPackets.xml +++ b/Gems/Multiplayer/Code/Source/AutoGen/Multiplayer.AutoPackets.xml @@ -9,13 +9,16 @@ - + + + + diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp index e4256a875c..dc86a07945 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp @@ -213,6 +213,8 @@ namespace Multiplayer reinterpret_cast(connection->GetUserData())->SetProviderTicket(config.m_playerSessionId); } + connection->SendReliablePacket(MultiplayerPackets::ValidateSession(config.m_playerSessionId.c_str())); + return true; } @@ -414,22 +416,6 @@ namespace Multiplayer [[maybe_unused]] MultiplayerPackets::Connect& packet ) { - // Validate our session with the provider if any - if (AZ::Interface::Get() != nullptr) - { - AzFramework::PlayerConnectionConfig config; - config.m_playerConnectionId = aznumeric_cast(connection->GetConnectionId()); - config.m_playerSessionId = packet.GetTicket(); - if(!AZ::Interface::Get()->ValidatePlayerJoinSession(config)) - { - auto visitor = [](IConnection& connection) { connection.Disconnect(DisconnectReason::TerminatedByUser, TerminationEndpoint::Local); }; - m_networkInterface->GetConnectionSet().VisitConnections(visitor); - return true; - } - - reinterpret_cast(connection->GetUserData())->SetProviderTicket(packet.GetTicket().c_str()); - } - if (connection->SendReliablePacket(MultiplayerPackets::Accept(InvalidHostId, sv_map))) { // Sync our console @@ -455,6 +441,32 @@ namespace Multiplayer return true; } + bool MultiplayerSystemComponent::HandleRequest + ( + [[maybe_unused]] AzNetworking::IConnection* connection, + [[maybe_unused]] const IPacketHeader& packetHeader, + [[maybe_unused]] MultiplayerPackets::ValidateSession& packet + ) + { + // Validate our session with the provider if any + if (AZ::Interface::Get() != nullptr) + { + AzFramework::PlayerConnectionConfig config; + config.m_playerConnectionId = aznumeric_cast(connection->GetConnectionId()); + config.m_playerSessionId = packet.GetTicket(); + if(!AZ::Interface::Get()->ValidatePlayerJoinSession(config)) + { + auto visitor = [](IConnection& connection) { connection.Disconnect(DisconnectReason::TerminatedByUser, TerminationEndpoint::Local); }; + m_networkInterface->GetConnectionSet().VisitConnections(visitor); + return false; + } + + reinterpret_cast(connection->GetUserData())->SetProviderTicket(packet.GetTicket().c_str()); + } + + return true; + } + bool MultiplayerSystemComponent::HandleRequest ( AzNetworking::IConnection* connection, @@ -587,12 +599,7 @@ namespace Multiplayer if (connection->GetConnectionRole() == ConnectionRole::Connector) { AZLOG_INFO("New outgoing connection to remote address: %s", connection->GetRemoteAddress().GetString().c_str()); - AZ::CVarFixedString providerTicket; - if (connection->GetUserData() != nullptr) - { - providerTicket = reinterpret_cast(connection->GetUserData())->GetProviderTicket(); - } - connection->SendReliablePacket(MultiplayerPackets::Connect(0, providerTicket)); + connection->SendReliablePacket(MultiplayerPackets::Connect(0)); } else { diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h index 0efef3ebe4..2a3fe73ff4 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h @@ -82,6 +82,7 @@ namespace Multiplayer bool HandleRequest(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, MultiplayerPackets::Connect& packet); bool HandleRequest(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, MultiplayerPackets::Accept& packet); + bool HandleRequest(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, MultiplayerPackets::ValidateSession& packet); bool HandleRequest(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, MultiplayerPackets::ReadyForEntityUpdates& packet); bool HandleRequest(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, MultiplayerPackets::SyncConsole& packet); bool HandleRequest(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, MultiplayerPackets::ConsoleCommand& packet); From aade48e7513bd91cc7e71f678ee3cb286702ceec Mon Sep 17 00:00:00 2001 From: yuriy0 Date: Tue, 15 Jun 2021 13:36:35 -0400 Subject: [PATCH 102/116] Allow smaller values and increments for editor camera speed, allow custom speed values --- Code/Sandbox/Editor/ViewportTitleDlg.cpp | 3 ++- Code/Sandbox/Editor/ViewportTitleDlg.h | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Code/Sandbox/Editor/ViewportTitleDlg.cpp b/Code/Sandbox/Editor/ViewportTitleDlg.cpp index 48075597cd..2c4b29773d 100644 --- a/Code/Sandbox/Editor/ViewportTitleDlg.cpp +++ b/Code/Sandbox/Editor/ViewportTitleDlg.cpp @@ -181,7 +181,8 @@ void CViewportTitleDlg::SetupCameraDropdownMenu() auto comboBoxTextChanged = static_cast(&QComboBox::currentTextChanged); SetSpeedComboBox(cameraMoveSpeed); - m_cameraSpeed->setInsertPolicy(QComboBox::NoInsert); + m_cameraSpeed->setInsertPolicy(QComboBox::InsertAtBottom); + m_cameraSpeed->setDuplicatesEnabled(false); connect(m_cameraSpeed, comboBoxTextChanged, this, &CViewportTitleDlg::OnUpdateMoveSpeedText); connect(m_cameraSpeed->lineEdit(), &QLineEdit::returnPressed, this, &CViewportTitleDlg::OnSpeedComboBoxEnter); diff --git a/Code/Sandbox/Editor/ViewportTitleDlg.h b/Code/Sandbox/Editor/ViewportTitleDlg.h index 255354dcbb..7978277ce0 100644 --- a/Code/Sandbox/Editor/ViewportTitleDlg.h +++ b/Code/Sandbox/Editor/ViewportTitleDlg.h @@ -117,11 +117,11 @@ protected: // Speed combobox/lineEdit settings double m_minSpeed = 0.01; double m_maxSpeed = 100.0; - double m_speedStep = 0.01; + double m_speedStep = 0.001; int m_numDecimals = 3; // Speed presets - float m_speedPresetValues[3] = { 0.1f, 1.0f, 10.0f }; + float m_speedPresetValues[4] = { 0.01f, 0.1f, 1.0f, 10.0f }; double m_fieldWidthMultiplier = 1.8; From 2f5cffe67969a4cc2902ac49c9d278ab4153f93b Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Tue, 15 Jun 2021 13:46:53 -0400 Subject: [PATCH 103/116] Added r_ViewportPos cvar for set the position of a viewport of a game/server launchers --- Code/LauncherUnified/Launcher.cpp | 5 +++++ .../Platform/Android/Launcher_Android.cpp | 2 ++ .../LauncherUnified/Platform/Linux/Launcher_Linux.cpp | 2 ++ Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm | 2 ++ .../Platform/Windows/Launcher_Windows.cpp | 11 +++++++++++ Code/LauncherUnified/Platform/iOS/Launcher_iOS.mm | 2 ++ 6 files changed, 24 insertions(+) diff --git a/Code/LauncherUnified/Launcher.cpp b/Code/LauncherUnified/Launcher.cpp index c73cdd1981..48747b50a7 100644 --- a/Code/LauncherUnified/Launcher.cpp +++ b/Code/LauncherUnified/Launcher.cpp @@ -46,6 +46,8 @@ extern "C" void CreateStaticModules(AZStd::vector& modulesOut); # define REMOTE_ASSET_PROCESSOR #endif +void CVar_OnViewportPosition(const AZ::Vector2& value); + namespace { void OnViewportResize(const AZ::Vector2& value); @@ -60,6 +62,9 @@ namespace AzFramework::WindowSize newSize = AzFramework::WindowSize(aznumeric_cast(value.GetX()), aznumeric_cast(value.GetY())); AzFramework::WindowRequestBus::Broadcast(&AzFramework::WindowRequestBus::Events::ResizeClientArea, newSize); } + + AZ_CVAR(AZ::Vector2, r_viewportPos, AZ::Vector2::CreateZero(), CVar_OnViewportPosition, AZ::ConsoleFunctorFlags::DontReplicate, + "The default position for the launcher viewport, 0 0 means top left corner of your main desktop"); void ExecuteConsoleCommandFile(AzFramework::Application& application) { diff --git a/Code/LauncherUnified/Platform/Android/Launcher_Android.cpp b/Code/LauncherUnified/Platform/Android/Launcher_Android.cpp index 6455373e58..fa26b9d204 100644 --- a/Code/LauncherUnified/Platform/Android/Launcher_Android.cpp +++ b/Code/LauncherUnified/Platform/Android/Launcher_Android.cpp @@ -433,3 +433,5 @@ void android_main(android_app* appState) MAIN_EXIT_FAILURE(appState, GetReturnCodeString(status)); } } + +void CVar_OnViewportPosition([[maybe_unused]] const AZ::Vector2& value) {} diff --git a/Code/LauncherUnified/Platform/Linux/Launcher_Linux.cpp b/Code/LauncherUnified/Platform/Linux/Launcher_Linux.cpp index 0c422877b1..3d283ce77f 100644 --- a/Code/LauncherUnified/Platform/Linux/Launcher_Linux.cpp +++ b/Code/LauncherUnified/Platform/Linux/Launcher_Linux.cpp @@ -113,3 +113,5 @@ int main(int argc, char** argv) return static_cast(status); } + +void CVar_OnViewportPosition([[maybe_unused]] const AZ::Vector2& value) {} diff --git a/Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm b/Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm index 1a491d66ad..2886bb16b1 100644 --- a/Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm +++ b/Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm @@ -63,3 +63,5 @@ int main(int argc, char* argv[]) } #endif // AZ_TESTS_ENABLED + +void CVar_OnViewportPosition([[maybe_unused]] const AZ::Vector2& value) {} diff --git a/Code/LauncherUnified/Platform/Windows/Launcher_Windows.cpp b/Code/LauncherUnified/Platform/Windows/Launcher_Windows.cpp index 8f8d310475..494779dcf8 100644 --- a/Code/LauncherUnified/Platform/Windows/Launcher_Windows.cpp +++ b/Code/LauncherUnified/Platform/Windows/Launcher_Windows.cpp @@ -69,3 +69,14 @@ int APIENTRY WinMain([[maybe_unused]] HINSTANCE hInstance, [[maybe_unused]] HINS return static_cast(status); } + +void CVar_OnViewportPosition(const AZ::Vector2& value) +{ + if (HWND windowHandle = GetActiveWindow()) + { + SetWindowPos(windowHandle, nullptr, + value.GetX(), + value.GetY(), + 0, 0, SWP_NOOWNERZORDER | SWP_NOSIZE); + } +} diff --git a/Code/LauncherUnified/Platform/iOS/Launcher_iOS.mm b/Code/LauncherUnified/Platform/iOS/Launcher_iOS.mm index 52c616fe64..05857842a7 100644 --- a/Code/LauncherUnified/Platform/iOS/Launcher_iOS.mm +++ b/Code/LauncherUnified/Platform/iOS/Launcher_iOS.mm @@ -23,3 +23,5 @@ int main(int argc, char* argv[]) [pool release]; return 0; } + +void CVar_OnViewportPosition([[maybe_unused]] const AZ::Vector2& value) {} From a446d397c62f81e7d6ade5655b673fcdae2b8baa Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Tue, 15 Jun 2021 14:05:35 -0400 Subject: [PATCH 104/116] Minor name refactoring --- Code/LauncherUnified/Launcher.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Code/LauncherUnified/Launcher.cpp b/Code/LauncherUnified/Launcher.cpp index 48747b50a7..09a9e2f990 100644 --- a/Code/LauncherUnified/Launcher.cpp +++ b/Code/LauncherUnified/Launcher.cpp @@ -50,12 +50,12 @@ void CVar_OnViewportPosition(const AZ::Vector2& value); namespace { - void OnViewportResize(const AZ::Vector2& value); + void CVar_OnViewportResize(const AZ::Vector2& value); - AZ_CVAR(AZ::Vector2, r_viewportSize, AZ::Vector2::CreateZero(), OnViewportResize, AZ::ConsoleFunctorFlags::DontReplicate, + AZ_CVAR(AZ::Vector2, r_viewportSize, AZ::Vector2::CreateZero(), CVar_OnViewportResize, AZ::ConsoleFunctorFlags::DontReplicate, "The default size for the launcher viewport, 0 0 means full screen"); - void OnViewportResize(const AZ::Vector2& value) + void CVar_OnViewportResize(const AZ::Vector2& value) { AzFramework::NativeWindowHandle windowHandle = nullptr; AzFramework::WindowSystemRequestBus::BroadcastResult(windowHandle, &AzFramework::WindowSystemRequestBus::Events::GetDefaultWindowHandle); From adc09435f48ac2b6adfbfb6b288b9ca9d0134ff4 Mon Sep 17 00:00:00 2001 From: puvvadar Date: Tue, 15 Jun 2021 11:08:59 -0700 Subject: [PATCH 105/116] Cleanup validation failure logic --- Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp index dc86a07945..aa5e0d7467 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp @@ -456,8 +456,7 @@ namespace Multiplayer config.m_playerSessionId = packet.GetTicket(); if(!AZ::Interface::Get()->ValidatePlayerJoinSession(config)) { - auto visitor = [](IConnection& connection) { connection.Disconnect(DisconnectReason::TerminatedByUser, TerminationEndpoint::Local); }; - m_networkInterface->GetConnectionSet().VisitConnections(visitor); + connection->Disconnect(DisconnectReason::TerminatedByServer, TerminationEndpoint::Local); return false; } From a9c55c1070dff2fbfd7c0c5d5afc03a40362bca2 Mon Sep 17 00:00:00 2001 From: yuriy0 Date: Tue, 15 Jun 2021 14:09:30 -0400 Subject: [PATCH 106/116] Update actor render bounding box (#991) * Extend MeshFeatureProcessor to allow changing the mesh bbox, which requires re-compute the culling data for that mesh * Update actor mesh bbox when EMFX actor instance bbox changes. Also use the actor instance global bbox to compute the local bbox for the skinned render mesh, instead of the using the static bounds based bbox, as not every actor instance is going to be using the static bounds bbox. * Store per-instance mesh AABB in the right place. In the MeshInstanceData, which is unique per instance, instead of in the Model, which is shared between all instances. For greater clarity, also remove Model::m_aabb and the corresponding getter and setter, as it isn't immediately obvious whether this gets the model asset bbox or the mesh instance bbox. Callers should instead be explicit about which bbox they want. * Bug fix: model asset is not necessarily ready in AcquireMesh * Remove now-unused forward declaration * Update MockMeshFeatureProcessor with SetLocalAabb/GetLocalAabb --- .../Atom/Feature/Mesh/MeshFeatureProcessor.h | 5 ++++ .../Mesh/MeshFeatureProcessorInterface.h | 4 +++ .../Code/Mocks/MockMeshFeatureProcessor.h | 2 ++ .../Code/Source/Mesh/MeshFeatureProcessor.cpp | 30 +++++++++++++++++-- .../Include/Atom/RPI.Public/Model/Model.h | 5 +--- .../Code/Source/RPI.Public/Model/Model.cpp | 16 +++++----- .../Source/RPI.Public/Model/ModelLodUtils.cpp | 2 +- .../Source/Mesh/MeshComponentController.cpp | 6 ++-- .../Code/Source/AtomActorInstance.cpp | 12 ++++++-- 9 files changed, 62 insertions(+), 20 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h index 0d61ef82d1..24c0658c61 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h @@ -95,6 +95,8 @@ namespace AZ TransformServiceFeatureProcessorInterface::ObjectId m_objectId; + Aabb m_aabb = Aabb::CreateNull(); + bool m_cullBoundsNeedsUpdate = false; bool m_cullableNeedsRebuild = false; bool m_objectSrgNeedsUpdate = true; @@ -160,6 +162,9 @@ namespace AZ Transform GetTransform(const MeshHandle& meshHandle) override; Vector3 GetNonUniformScale(const MeshHandle& meshHandle) override; + void SetLocalAabb(const MeshHandle& meshHandle, const AZ::Aabb& localAabb) override; + AZ::Aabb GetLocalAabb(const MeshHandle& meshHandle) const override; + void SetSortKey(const MeshHandle& meshHandle, RHI::DrawItemSortKey sortKey) override; RHI::DrawItemSortKey GetSortKey(const MeshHandle& meshHandle) override; diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h index fb5bff5584..fdc6ea3cc8 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h @@ -86,6 +86,10 @@ namespace AZ virtual Transform GetTransform(const MeshHandle& meshHandle) = 0; //! Gets the non-uniform scale for a given mesh handle. virtual Vector3 GetNonUniformScale(const MeshHandle& meshHandle) = 0; + //! Sets the local space bbox for a given mesh handle. You don't need to call this for static models, only skinned/animated models + virtual void SetLocalAabb(const MeshHandle& meshHandle, const AZ::Aabb& localAabb) = 0; + //! Gets the local space bbox for a given mesh handle. Unless SetLocalAabb has been called before, this will be the bbox of the model asset + virtual AZ::Aabb GetLocalAabb(const MeshHandle& meshHandle) const = 0; //! Sets the sort key for a given mesh handle. virtual void SetSortKey(const MeshHandle& meshHandle, RHI::DrawItemSortKey sortKey) = 0; //! Gets the sort key for a given mesh handle. diff --git a/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h index 418ee0cfb8..e6635906e9 100644 --- a/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h @@ -33,6 +33,8 @@ namespace UnitTest MOCK_METHOD2(SetMaterialAssignmentMap, void(const MeshHandle&, const AZ::Render::MaterialAssignmentMap&)); MOCK_METHOD1(GetTransform, AZ::Transform(const MeshHandle&)); MOCK_METHOD1(GetNonUniformScale, AZ::Vector3(const MeshHandle&)); + MOCK_METHOD2(SetLocalAabb, void(const MeshHandle&, const AZ::Aabb&)); + MOCK_CONST_METHOD1(GetLocalAabb, AZ::Aabb(const MeshHandle&)); MOCK_METHOD2(SetSortKey, void (const MeshHandle&, AZ::RHI::DrawItemSortKey)); MOCK_METHOD1(GetSortKey, AZ::RHI::DrawItemSortKey(const MeshHandle&)); MOCK_METHOD2(SetLodOverride, void(const MeshHandle&, AZ::RPI::Cullable::LodOverride)); diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp index b087269089..6fe6cf1f88 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp @@ -304,6 +304,30 @@ namespace AZ } } + void MeshFeatureProcessor::SetLocalAabb(const MeshHandle& meshHandle, const AZ::Aabb& localAabb) + { + if (meshHandle.IsValid()) + { + MeshDataInstance& meshData = *meshHandle; + meshData.m_aabb = localAabb; + meshData.m_cullBoundsNeedsUpdate = true; + meshData.m_objectSrgNeedsUpdate = true; + } + }; + + AZ::Aabb MeshFeatureProcessor::GetLocalAabb(const MeshHandle& meshHandle) const + { + if (meshHandle.IsValid()) + { + return meshHandle->m_aabb; + } + else + { + AZ_Assert(false, "Invalid mesh handle"); + return Aabb::CreateNull(); + } + } + Transform MeshFeatureProcessor::GetTransform(const MeshHandle& meshHandle) { if (meshHandle.IsValid()) @@ -603,6 +627,8 @@ namespace AZ SetRayTracingData(); } + m_aabb = model->GetModelAsset()->GetAabb(); + m_cullableNeedsRebuild = true; m_cullBoundsNeedsUpdate = true; m_objectSrgNeedsUpdate = true; @@ -996,7 +1022,7 @@ namespace AZ RPI::Cullable::CullData& cullData = m_cullable.m_cullData; RPI::Cullable::LodData& lodData = m_cullable.m_lodData; - const Aabb& localAabb = m_model->GetAabb(); + const Aabb& localAabb = m_aabb; lodData.m_lodSelectionRadius = 0.5f*localAabb.GetExtents().GetMaxElement(); const size_t modelLodCount = m_model->GetLodCount(); @@ -1077,7 +1103,7 @@ namespace AZ Vector3 center; float radius; - Aabb localAabb = m_model->GetAabb(); + Aabb localAabb = m_aabb; localAabb.MultiplyByScale(nonUniformScale); localAabb.GetTransformedAabb(localToWorld).GetAsSphere(center, radius); diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/Model.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/Model.h index 514e3e37a5..b403a86f00 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/Model.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/Model.h @@ -32,6 +32,7 @@ namespace AZ : public Data::InstanceData { friend class ModelSystem; + public: AZ_INSTANCE_DATA(Model, "{C30F5522-B381-4B38-BBAF-6E0B1885C8B9}"); AZ_CLASS_ALLOCATOR(Model, AZ::SystemAllocator, 0); @@ -53,8 +54,6 @@ namespace AZ //! Returns whether a buffer upload is pending. bool IsUploadPending() const; - const AZ::Aabb& GetAabb() const; - const Data::Asset& GetModelAsset() const; //! Checks a ray for intersection against this model. The ray must be in the same coordinate space as the model. @@ -105,8 +104,6 @@ namespace AZ // Tracks whether buffers have all been streamed up to the GPU. bool m_isUploadPending = false; - - AZ::Aabb m_aabb; }; } // namespace RPI } // namespace AZ diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Model/Model.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Model/Model.cpp index 17ff2c64c8..8809225150 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Model/Model.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Model/Model.cpp @@ -62,8 +62,6 @@ namespace AZ { AZ_PROFILE_FUNCTION(Debug::ProfileCategory::AzRender); - m_aabb = modelAsset.GetAabb(); - m_lods.resize(modelAsset.GetLodAssets().size()); for (size_t lodIndex = 0; lodIndex < m_lods.size(); ++lodIndex) @@ -127,11 +125,6 @@ namespace AZ return m_isUploadPending; } - const AZ::Aabb& Model::GetAabb() const - { - return m_aabb; - } - const Data::Asset& Model::GetModelAsset() const { return m_modelAsset; @@ -140,9 +133,16 @@ namespace AZ bool Model::LocalRayIntersection(const AZ::Vector3& rayStart, const AZ::Vector3& rayDir, float& distanceNormalized, AZ::Vector3& normal) const { AZ_PROFILE_FUNCTION(Debug::ProfileCategory::AzRender); + + if (!GetModelAsset()) + { + AZ_Assert(false, "Invalid Model - not created from a ModelAsset?"); + return false; + } + float start; float end; - const int result = Intersect::IntersectRayAABB2(rayStart, rayDir.GetReciprocal(), m_aabb, start, end); + const int result = Intersect::IntersectRayAABB2(rayStart, rayDir.GetReciprocal(), GetModelAsset()->GetAabb(), start, end); if (Intersect::ISECT_RAY_AABB_NONE != result) { if (ModelAsset* modelAssetPtr = m_modelAsset.Get()) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Model/ModelLodUtils.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Model/ModelLodUtils.cpp index b213e84bca..a4e5d1ba10 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Model/ModelLodUtils.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Model/ModelLodUtils.cpp @@ -49,7 +49,7 @@ namespace AZ With that percentage we can determine which Lod we want to use. */ - Aabb modelAabb = model.GetAabb(); + Aabb modelAabb = model.GetModelAsset()->GetAabb(); modelAabb.Translate(position); Vector3 center; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp index e7eecd3c7f..90d3763067 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp @@ -460,10 +460,10 @@ namespace AZ Aabb MeshComponentController::GetLocalBounds() { - const Data::Instance model = GetModel(); - if (model) + if (m_meshHandle.IsValid() && m_meshFeatureProcessor) { - Aabb aabb = model->GetAabb(); + Aabb aabb = m_meshFeatureProcessor->GetLocalAabb(m_meshHandle); + aabb.MultiplyByScale(m_cachedNonUniformScale); return aabb; } diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp index 532c8720b5..ff4b82ce92 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp @@ -83,12 +83,20 @@ namespace AZ void AtomActorInstance::UpdateBounds() { // Update RenderActorInstance world bounding box - // The bounding box is moving with the actor instance. It is static in the way that it does not change shape. + // The bounding box is moving with the actor instance. // The entity and actor transforms are kept in sync already. m_worldAABB = AZ::Aabb::CreateFromMinMax(m_actorInstance->GetAABB().GetMin(), m_actorInstance->GetAABB().GetMax()); // Update RenderActorInstance local bounding box - m_localAABB = AZ::Aabb::CreateFromMinMax(m_actorInstance->GetStaticBasedAABB().GetMin(), m_actorInstance->GetStaticBasedAABB().GetMax()); + // NB: computing the local bbox from the world bbox makes the local bbox artifically larger than it should be + // instead EMFX should support getting the local bbox from the actor instance directly + m_localAABB = m_worldAABB.GetTransformedAabb(m_transformInterface->GetWorldTM().GetInverse()); + + // Update bbox on mesh instance if it exists + if (m_meshFeatureProcessor && m_meshHandle && m_meshHandle->IsValid() && m_skinnedMeshInstance) + { + m_meshFeatureProcessor->SetLocalAabb(*m_meshHandle, m_localAABB); + } AZ::Interface::Get()->RefreshEntityLocalBoundsUnion(m_entityId); } From cac210f25bc7b071903e38a9f15265e4c605c006 Mon Sep 17 00:00:00 2001 From: jromnoa Date: Tue, 15 Jun 2021 11:28:58 -0700 Subject: [PATCH 107/116] add check for files in a given path before creating full paths to the files, add output when json.loads() call fails --- scripts/build/tools/upload_to_s3.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/build/tools/upload_to_s3.py b/scripts/build/tools/upload_to_s3.py index 132929d83e..3694014056 100755 --- a/scripts/build/tools/upload_to_s3.py +++ b/scripts/build/tools/upload_to_s3.py @@ -84,12 +84,14 @@ def get_files_to_upload(base_dir, regex, search_subdirectories): # ('C:\path\to\base_dir\', ['Subfolder1', 'Subfolder2'], ['file1', 'file2']) subdirectory_file_path = subdirectory[0] subdirectory_files = subdirectory[2] - subdirectory_file_paths = _build_file_paths(subdirectory_file_path, subdirectory_files) - files.extend(subdirectory_file_paths) + if subdirectory_files: + subdirectory_file_paths = _build_file_paths(subdirectory_file_path, subdirectory_files) + files.extend(subdirectory_file_paths) try: regex = json.loads(regex) # strip the surround quotes, if they exist except: + print(f'WARNING: failed to call json.loads() for regex: "{regex}"') pass # Get all file names matching the regular expression, those file will be uploaded to S3 regex_files_to_upload = [x for x in files if re.match(regex, x)] From 04f045bfd2cc592629860fb621f540e181ee5978 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Tue, 15 Jun 2021 15:58:16 -0400 Subject: [PATCH 108/116] Recoding parts of old Networking that used Bullet external physics code --- .../Replica/Interest/BvDynamicTree.cpp | 1277 ------------ .../GridMate/Replica/Interest/BvDynamicTree.h | 878 -------- .../Interest/ProximityInterestHandler.cpp | 597 ------ .../Interest/ProximityInterestHandler.h | 314 --- .../GridMate/GridMate/gridmate_files.cmake | 4 - Code/Framework/GridMate/Tests/Interest.cpp | 1823 ----------------- .../GridMate/Tests/gridmate_test_files.cmake | 1 - 7 files changed, 4894 deletions(-) delete mode 100644 Code/Framework/GridMate/GridMate/Replica/Interest/BvDynamicTree.cpp delete mode 100644 Code/Framework/GridMate/GridMate/Replica/Interest/BvDynamicTree.h delete mode 100644 Code/Framework/GridMate/GridMate/Replica/Interest/ProximityInterestHandler.cpp delete mode 100644 Code/Framework/GridMate/GridMate/Replica/Interest/ProximityInterestHandler.h delete mode 100644 Code/Framework/GridMate/Tests/Interest.cpp diff --git a/Code/Framework/GridMate/GridMate/Replica/Interest/BvDynamicTree.cpp b/Code/Framework/GridMate/GridMate/Replica/Interest/BvDynamicTree.cpp deleted file mode 100644 index e72bd9b12c..0000000000 --- a/Code/Framework/GridMate/GridMate/Replica/Interest/BvDynamicTree.cpp +++ /dev/null @@ -1,1277 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -// Modifications copyright Amazon.com, Inc. or its affiliates. - -///BvDynamicTree implementation by Nathanael Presson -#include - -namespace GridMate -{ - // - struct btDbvtNodeEnumerator : BvDynamicTree::ICollideCollector - { - BvDynamicTree::ConstNodeArrayType nodes; - void Process(const BvDynamicTree::NodeType* n) { nodes.push_back(n); } - }; - - // - static AZ_FORCE_INLINE int indexof(const BvDynamicTree::NodeType* node) - { - return (node->m_parent->m_childs[1]==node); - } - - // - static AZ_FORCE_INLINE BvDynamicTree::VolumeType merge( const BvDynamicTree::VolumeType& a, const BvDynamicTree::VolumeType& b) - { - BvDynamicTree::VolumeType res; - Merge(a,b,res); - return res; - } - - // volume+edge lengths - static AZ_FORCE_INLINE float size(const BvDynamicTree::VolumeType& a) - { - const AZ::Vector3 edges = a.GetExtents(); - return edges.GetX()*edges.GetY()*edges.GetZ() + edges.Dot(AZ::Vector3::CreateOne()); - } - - // - static void getmaxdepth(const BvDynamicTree::NodeType* node,int depth,int& maxdepth) - { - if(node->IsInternal()) - { - getmaxdepth(node->m_childs[0],depth+1,maxdepth); - getmaxdepth(node->m_childs[0],depth+1,maxdepth); - } - else - maxdepth= AZ::GetMax(maxdepth,depth); - } - - - - //========================================================================= - // insertleaf - // [3/4/2009] - //========================================================================= - void - BvDynamicTree::insertleaf( NodeType* root, NodeType* leaf) - { - if(!m_root) - { - m_root = leaf; - leaf->m_parent = 0; - } - else - { - if(!root->IsLeaf()) - { - do { - root=root->m_childs[Select( leaf->m_volume, - root->m_childs[0]->m_volume, - root->m_childs[1]->m_volume)]; - } while(!root->IsLeaf()); - } - NodeType* prev = root->m_parent; - NodeType* node = createnode(prev,leaf->m_volume,root->m_volume,0); - if(prev) - { - prev->m_childs[indexof(root)] = node; - node->m_childs[0] = root;root->m_parent=node; - node->m_childs[1] = leaf;leaf->m_parent=node; - do { - if(!prev->m_volume.Contains(node->m_volume)) - Merge(prev->m_childs[0]->m_volume,prev->m_childs[1]->m_volume,prev->m_volume); - else - break; - node=prev; - } while(0!=(prev=node->m_parent)); - } - else - { - node->m_childs[0] = root;root->m_parent=node; - node->m_childs[1] = leaf;leaf->m_parent=node; - m_root = node; - } - } - } - - //========================================================================= - // removeleaf - // [3/4/2009] - //========================================================================= - BvDynamicTree::NodeType* - BvDynamicTree::removeleaf( NodeType* leaf) - { - if(leaf==m_root) - { - m_root=0; - return 0; - } - else - { - NodeType* parent=leaf->m_parent; - NodeType* prev=parent->m_parent; - NodeType* sibling=parent->m_childs[1-indexof(leaf)]; - if(prev) - { - prev->m_childs[indexof(parent)]=sibling; - sibling->m_parent=prev; - deletenode(parent); - while(prev) - { - const VolumeType pb=prev->m_volume; - Merge(prev->m_childs[0]->m_volume,prev->m_childs[1]->m_volume,prev->m_volume); - if(NotEqual(pb,prev->m_volume)) - { - prev=prev->m_parent; - } else break; - } - return prev?prev:m_root; - } - else - { - m_root=sibling; - sibling->m_parent=0; - deletenode(parent); - return m_root; - } - } - } - - - //========================================================================= - // fetchleaves - // [3/4/2009] - //========================================================================= - void - BvDynamicTree::fetchleaves(NodeType* root,NodeArrayType& leaves,int depth) - { - if(root->IsInternal()&&depth) - { - fetchleaves(root->m_childs[0],leaves,depth-1); - fetchleaves(root->m_childs[1],leaves,depth-1); - deletenode(root); - } - else - { - leaves.push_back(root); - } - } - - //========================================================================= - // split - // [3/4/2009] - //========================================================================= - void - BvDynamicTree::split(const NodeArrayType& leaves, NodeArrayType& left, NodeArrayType& right, const AZ::Vector3& org, const AZ::Vector3& axis) - { - left.resize(0); - right.resize(0); - for(size_t i = 0, ni = leaves.size(); i < ni; ++i) - { - if (axis.Dot(leaves[i]->m_volume.GetCenter() - org) < 0.0f) - { - left.push_back(leaves[i]); - } - else - { - right.push_back(leaves[i]); - } - } - } - - //========================================================================= - // bounds - // [3/4/2009] - //========================================================================= - BvDynamicTree::VolumeType - BvDynamicTree::bounds(const NodeArrayType& leaves) - { - VolumeType volume=leaves[0]->m_volume; - for(size_t i=1,ni=leaves.size();im_volume,volume); - } - return volume; - } - - //========================================================================= - // bottomup - // [3/4/2009] - //========================================================================= - void - BvDynamicTree::bottomup( NodeArrayType& leaves ) - { - while(leaves.size()>1) - { - float minsize = std::numeric_limits::max(); - int minidx[2]={-1,-1}; - for(unsigned int i=0;im_volume,leaves[j]->m_volume)); - if(szm_volume,n[1]->m_volume,0); - p->m_childs[0] = n[0]; - p->m_childs[1] = n[1]; - n[0]->m_parent = p; - n[1]->m_parent = p; - leaves[minidx[0]] = p; - //leaves.swap(minidx[1],leaves.size()-1); - leaves[minidx[1]] = leaves.back(); - leaves.pop_back(); - } - } - - //========================================================================= - // topdown - // [3/4/2009] - //========================================================================= - BvDynamicTree::NodeType* - BvDynamicTree::topdown(NodeArrayType& leaves,int bu_treshold) - { - static const AZ::Vector3 axis[]= { AZ::Vector3(1.0f,0.0f,0.0f), AZ::Vector3(0.0f,1.0f,0.0f), AZ::Vector3(0.0f,0.0f,1.0f)}; - if(leaves.size()>1) - { - if(leaves.size()>(unsigned int)bu_treshold) - { - const VolumeType vol=bounds(leaves); - const AZ::Vector3 org=vol.GetCenter(); - NodeArrayType sets[2]; - int bestaxis=-1; - int bestmidp=(int)leaves.size(); - int splitcount[3][2]={{0,0},{0,0},{0,0}}; - - for(unsigned int i=0;im_volume.GetCenter()-org; - for(int j=0;j<3;++j) - { - ++splitcount[j][x.Dot(axis[j]) > 0.0f ? 1 : 0]; - } - } - for(unsigned int i=0;i<3;++i) - { - if((splitcount[i][0]>0)&&(splitcount[i][1]>0)) - { - // todo just remove the sign bit... - const int midp = (int)fabsf((float)(splitcount[i][0]-splitcount[i][1])); - if(midp=0) - { - sets[0].reserve(splitcount[bestaxis][0]); - sets[1].reserve(splitcount[bestaxis][1]); - split(leaves,sets[0],sets[1],org,axis[bestaxis]); - } - else - { - sets[0].reserve(leaves.size()/2+1); - sets[1].reserve(leaves.size()/2); - for(size_t i=0,ni=leaves.size();im_childs[0] = topdown(sets[0],bu_treshold); - node->m_childs[1] = topdown(sets[1],bu_treshold); - node->m_childs[0]->m_parent=node; - node->m_childs[1]->m_parent=node; - return(node); - } - else - { - bottomup(leaves); - return(leaves[0]); - } - } - return(leaves[0]); - } - - //========================================================================= - // sort - // [3/4/2009] - //========================================================================= - AZ_FORCE_INLINE BvDynamicTree::NodeType* - BvDynamicTree::sort(NodeType* n,NodeType*& r) - { - BvDynamicTree::NodeType* p=n->m_parent; - AZ_Assert(n->IsInternal(), "We can call this only for internal nodes!"); - if(p>n) - { - const int i=indexof(n); - const int j=1-i; - NodeType* s=p->m_childs[j]; - NodeType* q=p->m_parent; - AZ_Assert(n==p->m_childs[i], ""); - if(q) q->m_childs[indexof(p)]=n; else r=n; - s->m_parent=n; - p->m_parent=n; - n->m_parent=q; - p->m_childs[0]=n->m_childs[0]; - p->m_childs[1]=n->m_childs[1]; - n->m_childs[0]->m_parent=p; - n->m_childs[1]->m_parent=p; - n->m_childs[i]=p; - n->m_childs[j]=s; - AZStd::swap(p->m_volume,n->m_volume); - return(p); - } - return(n); - } - - #if 0 - static DBVT_INLINE NodeType* walkup(NodeType* n,int count) - { - while(n&&(count--)) n=n->parent; - return(n); - } - #endif - - // - // Api - // - - // - BvDynamicTree::BvDynamicTree() - { - m_root = 0; - m_free = 0; - m_lkhd = -1; - m_leaves = 0; - m_opath = 0; - } - - // - BvDynamicTree::~BvDynamicTree() - { - Clear(); - } - - // - void BvDynamicTree::Clear() - { - if(m_root) recursedeletenode(m_root); - delete m_free; - m_free=0; - } - - // - void BvDynamicTree::OptimizeBottomUp() - { - if(m_root) - { - NodeArrayType leaves; - leaves.reserve(m_leaves); - fetchleaves(m_root,leaves); - bottomup(leaves); - m_root=leaves[0]; - } - } - - // - void - BvDynamicTree::OptimizeTopDown(int bu_treshold) - { - if(m_root) - { - NodeArrayType leaves; - leaves.reserve(m_leaves); - fetchleaves(m_root,leaves); - m_root=topdown(leaves,bu_treshold); - } - } - - // - void - BvDynamicTree::OptimizeIncremental(int passes) - { - if(passes<0) passes=m_leaves; - if(m_root&&(passes>0)) - { - do { - NodeType* node=m_root; - unsigned bit=0; - while(node->IsInternal()) - { - node=sort(node,m_root)->m_childs[(m_opath>>bit)&1]; - bit=(bit+1)&(sizeof(unsigned)*8-1); - } - Update(node); - ++m_opath; - } while(--passes); - } - } - - // - BvDynamicTree::NodeType* - BvDynamicTree::Insert(const VolumeType& volume,void* data) - { - NodeType* leaf=createnode(0,volume,data); - insertleaf(m_root,leaf); - ++m_leaves; - return(leaf); - } - - // - void - BvDynamicTree::Update(NodeType* leaf,int lookahead) - { - NodeType* root=removeleaf(leaf); - if(root) - { - if(lookahead>=0) - { - for(int i=0;(im_parent;++i) - { - root=root->m_parent; - } - } else root=m_root; - } - insertleaf(root,leaf); - } - - // - void - BvDynamicTree::Update(NodeType* leaf,VolumeType& volume) - { - NodeType* root=removeleaf(leaf); - if(root) - { - if(m_lkhd>=0) - { - for(int i=0;(im_parent;++i) - { - root=root->m_parent; - } - } else root=m_root; - } - leaf->m_volume=volume; - insertleaf(root,leaf); - } - - // - bool - BvDynamicTree::Update(NodeType* leaf,VolumeType& volume,const AZ::Vector3& velocity,const float margin) - { - if(leaf->m_volume.Contains(volume)) return(false); - volume.Expand(AZ::Vector3(margin)); - volume.SignedExpand(velocity); - Update(leaf,volume); - return(true); - } - - // - bool - BvDynamicTree::Update(NodeType* leaf,VolumeType& volume,const AZ::Vector3& velocity) - { - if(leaf->m_volume.Contains(volume)) return(false); - volume.SignedExpand(velocity); - Update(leaf,volume); - return(true); - } - - // - bool - BvDynamicTree::Update(NodeType* leaf,VolumeType& volume,const float margin) - { - if(leaf->m_volume.Contains(volume)) return(false); - volume.Expand(AZ::Vector3(margin)); - Update(leaf,volume); - return(true); - } - - // - void - BvDynamicTree::Remove(NodeType* leaf) - { - removeleaf(leaf); - deletenode(leaf); - --m_leaves; - } - - template - int findLinearSearch(BvDynamicTree::ConstNodeArrayType& arr, const T& key) - { - size_t numElements = arr.size(); - int index = (int)numElements; - - for(size_t i=0;iPrepare(m_root,(unsigned int)nodes.nodes.size()); - for(unsigned int i=0;i<(unsigned int)nodes.nodes.size();++i) - { - const NodeType* n=nodes.nodes[i]; - int p=-1; - if(n->m_parent) p = findLinearSearch(nodes.nodes,n->m_parent); - if(n->IsInternal()) - { - const int c0=findLinearSearch(nodes.nodes,n->m_childs[0]); - const int c1=findLinearSearch(nodes.nodes,n->m_childs[1]); - iwriter->WriteNode(n,i,p,c0,c1); - } - else - { - iwriter->WriteLeaf(n,i,p); - } - } - } - - // - void - BvDynamicTree::Clone(BvDynamicTree& dest,IClone* iclone) const - { - dest.Clear(); - if(m_root!=0) - { - vector stack; - stack.reserve(m_leaves); - stack.push_back(sStkCLN(m_root,0)); - do { - const size_t i=stack.size()-1; - const sStkCLN e=stack[i]; - NodeType* n= dest.createnode(e.parent,e.node->m_volume,e.node->m_data); - stack.pop_back(); - if(e.parent!=0) - e.parent->m_childs[i&1]=n; - else - dest.m_root=n; - if(e.node->IsInternal()) - { - stack.push_back(sStkCLN(e.node->m_childs[0],n)); - stack.push_back(sStkCLN(e.node->m_childs[1],n)); - } - else - { - iclone->CloneLeaf(n); - } - } while(!stack.empty()); - } - } - - // - int - BvDynamicTree::GetMaxDepth(const NodeType* node) - { - int depth=0; - if(node) getmaxdepth(node,1,depth); - return depth ; - } - - // - int - BvDynamicTree::CountLeaves(const NodeType* node) - { - if(node->IsInternal()) - return(CountLeaves(node->m_childs[0])+CountLeaves(node->m_childs[1])); - else - return(1); - } - - // - void - BvDynamicTree::ExtractLeaves(const NodeType* node,vector& leaves) - { - if(node->IsInternal()) - { - ExtractLeaves(node->m_childs[0],leaves); - ExtractLeaves(node->m_childs[1],leaves); - } - else - { - leaves.push_back(node); - } - } - - // - #if DBVT_ENABLE_BENCHMARK - - #include - #include - #include - - /* - q6600,2.4ghz - - /Ox /Ob2 /Oi /Ot /I "." /I "..\.." /I "..\..\src" /D "NDEBUG" /D "_LIB" /D "_WINDOWS" /D "_CRT_SECURE_NO_DEPRECATE" /D "_CRT_NONSTDC_NO_DEPRECATE" /D "WIN32" - /GF /FD /MT /GS- /Gy /arch:SSE2 /Zc:wchar_t- /Fp"..\..\out\release8\build\libbulletcollision\libbulletcollision.pch" - /Fo"..\..\out\release8\build\libbulletcollision\\" - /Fd"..\..\out\release8\build\libbulletcollision\bulletcollision.pdb" - /W3 /nologo /c /Wp64 /Zi /errorReport:prompt - - Benchmarking dbvt... - World scale: 100.000000 - Extents base: 1.000000 - Extents range: 4.000000 - Leaves: 8192 - sizeof(VolumeType): 32 bytes - sizeof(NodeType): 44 bytes - [1] VolumeType intersections: 3499 ms (-1%) - [2] VolumeType merges: 1934 ms (0%) - [3] BvDynamicTree::collideTT: 5485 ms (-21%) - [4] BvDynamicTree::collideTT self: 2814 ms (-20%) - [5] BvDynamicTree::collideTT xform: 7379 ms (-1%) - [6] BvDynamicTree::collideTT xform,self: 7270 ms (-2%) - [7] BvDynamicTree::rayTest: 6314 ms (0%),(332143 r/s) - [8] insert/remove: 2093 ms (0%),(1001983 ir/s) - [9] updates (teleport): 1879 ms (-3%),(1116100 u/s) - [10] updates (jitter): 1244 ms (-4%),(1685813 u/s) - [11] optimize (incremental): 2514 ms (0%),(1668000 o/s) - [12] VolumeType notequal: 3659 ms (0%) - [13] culling(OCL+fullsort): 2218 ms (0%),(461 t/s) - [14] culling(OCL+qsort): 3688 ms (5%),(2221 t/s) - [15] culling(KDOP+qsort): 1139 ms (-1%),(7192 t/s) - [16] insert/remove batch(256): 5092 ms (0%),(823704 bir/s) - [17] VolumeType select: 3419 ms (0%) - */ - - struct btDbvtBenchmark - { - struct NilPolicy : BvDynamicTree::ICollide - { - NilPolicy() : m_pcount(0),m_depth(-SIMD_INFINITY),m_checksort(true) {} - void Process(const NodeType*,const NodeType*) { ++m_pcount; } - void Process(const NodeType*) { ++m_pcount; } - void Process(const NodeType*,btScalar depth) - { - ++m_pcount; - if(m_checksort) - { if(depth>=m_depth) m_depth=depth; else printf("wrong depth: %f (should be >= %f)\r\n",depth,m_depth); } - } - int m_pcount; - btScalar m_depth; - bool m_checksort; - }; - struct P14 : BvDynamicTree::ICollide - { - struct Node - { - const NodeType* leaf; - btScalar depth; - }; - void Process(const NodeType* leaf,btScalar depth) - { - Node n; - n.leaf = leaf; - n.depth = depth; - } - static int sortfnc(const Node& a,const Node& b) - { - if(a.depthb.depth) return(-1); - return(0); - } - btAlignedObjectArray m_nodes; - }; - struct P15 : BvDynamicTree::ICollide - { - struct Node - { - const NodeType* leaf; - btScalar depth; - }; - void Process(const NodeType* leaf) - { - Node n; - n.leaf = leaf; - n.depth = dot(leaf->volume.GetCenter(),m_axis); - } - static int sortfnc(const Node& a,const Node& b) - { - if(a.depthb.depth) return(-1); - return(0); - } - btAlignedObjectArray m_nodes; - btAZ::Vector3 m_axis; - }; - static btScalar RandUnit() - { - return(rand()/(btScalar)RAND_MAX); - } - static btAZ::Vector3 RandAZ::Vector3() - { - return(btAZ::Vector3(RandUnit(),RandUnit(),RandUnit())); - } - static btAZ::Vector3 RandAZ::Vector3(btScalar cs) - { - return(RandAZ::Vector3()*cs-btAZ::Vector3(cs,cs,cs)/2); - } - static VolumeType RandVolume(btScalar cs,btScalar eb,btScalar es) - { - return(VolumeType::FromCE(RandAZ::Vector3(cs),btAZ::Vector3(eb,eb,eb)+RandAZ::Vector3()*es)); - } - static btTransform RandTransform(btScalar cs) - { - btTransform t; - t.setOrigin(RandAZ::Vector3(cs)); - t.setRotation(btQuaternion(RandUnit()*SIMD_PI*2,RandUnit()*SIMD_PI*2,RandUnit()*SIMD_PI*2).normalized()); - return(t); - } - static void RandTree(btScalar cs,btScalar eb,btScalar es,int leaves,BvDynamicTree& dbvt) - { - dbvt.clear(); - for(int i=0;i volumes; - btAlignedObjectArray results; - volumes.resize(cfgLeaves); - results.resize(cfgLeaves); - for(int i=0;i volumes; - btAlignedObjectArray results; - volumes.resize(cfgLeaves); - results.resize(cfgLeaves); - for(int i=0;i transforms; - btDbvtBenchmark::NilPolicy policy; - transforms.resize(cfgBenchmark5_Iterations); - for(int i=0;i transforms; - btDbvtBenchmark::NilPolicy policy; - transforms.resize(cfgBenchmark6_Iterations); - for(int i=0;i rayorg; - btAlignedObjectArray raydir; - btDbvtBenchmark::NilPolicy policy; - rayorg.resize(cfgBenchmark7_Iterations); - raydir.resize(cfgBenchmark7_Iterations); - for(int i=0;i leaves; - btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt); - dbvt.optimizeTopDown(); - dbvt.extractLeaves(dbvt.m_root,leaves); - printf("[9] updates (teleport): "); - wallclock.reset(); - for(int i=0;i(leaves[rand()%cfgLeaves]), - btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale)); - } - } - const int time=(int)wallclock.getTimeMilliseconds(); - const int up=cfgBenchmark9_Passes*cfgBenchmark9_Iterations; - printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark9_Reference)*100/time,up*1000/time); - } - if(cfgBenchmark10_Enable) - {// Benchmark 10 - srand(380843); - BvDynamicTree dbvt; - btAlignedObjectArray leaves; - btAlignedObjectArray vectors; - vectors.resize(cfgBenchmark10_Iterations); - for(int i=0;i(leaves[rand()%cfgLeaves]); - VolumeType v=VolumeType::FromMM(l->volume.GetMin()+d,l->volume.GetMax()+d); - dbvt.update(l,v); - } - } - const int time=(int)wallclock.getTimeMilliseconds(); - const int up=cfgBenchmark10_Passes*cfgBenchmark10_Iterations; - printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark10_Reference)*100/time,up*1000/time); - } - if(cfgBenchmark11_Enable) - {// Benchmark 11 - srand(380843); - BvDynamicTree dbvt; - btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt); - dbvt.optimizeTopDown(); - printf("[11] optimize (incremental): "); - wallclock.reset(); - for(int i=0;i volumes; - btAlignedObjectArray results; - volumes.resize(cfgLeaves); - results.resize(cfgLeaves); - for(int i=0;i vectors; - btDbvtBenchmark::NilPolicy policy; - vectors.resize(cfgBenchmark13_Iterations); - for(int i=0;i vectors; - btDbvtBenchmark::P14 policy; - vectors.resize(cfgBenchmark14_Iterations); - for(int i=0;i vectors; - btDbvtBenchmark::P15 policy; - vectors.resize(cfgBenchmark15_Iterations); - for(int i=0;i batch; - btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt); - dbvt.optimizeTopDown(); - batch.reserve(cfgBenchmark16_BatchCount); - printf("[16] Insert/remove batch(%u): ",cfgBenchmark16_BatchCount); - wallclock.reset(); - for(int i=0;i volumes; - btAlignedObjectArray results; - btAlignedObjectArray indices; - volumes.resize(cfgLeaves); - results.resize(cfgLeaves); - indices.resize(cfgLeaves); - for(int i=0;i -#include -#include - -#include -#include - -namespace GridMate -{ - namespace Internal - { - /** - * - */ - class DynamicTreeAabb : public AZ::Aabb - { - public: - GM_CLASS_ALLOCATOR(DynamicTreeAabb); - - AZ_FORCE_INLINE explicit DynamicTreeAabb() {} - AZ_FORCE_INLINE DynamicTreeAabb(const AZ::Aabb& aabb) : AZ::Aabb(aabb) {} - AZ_FORCE_INLINE explicit DynamicTreeAabb(const AZ::Vector3& min,const AZ::Vector3& max) : AZ::Aabb(AZ::Aabb::CreateFromMinMax(min,max)) {} - - AZ_FORCE_INLINE static DynamicTreeAabb CreateFromFacePoints(const AZ::Vector3& a, const AZ::Vector3& b, const AZ::Vector3& c) - { - DynamicTreeAabb vol(a,a); - vol.AddPoint(b); - vol.AddPoint(c); - return vol; - } - - AZ_FORCE_INLINE void SignedExpand(const AZ::Vector3& e) - { - AZ::Vector3 zero = AZ::Vector3::CreateZero(); - AZ::Vector3 mxE = m_max + e; - AZ::Vector3 miE = m_min + e; - m_max = AZ::Vector3::CreateSelectCmpGreater(e,zero,mxE,m_max ); - m_min = AZ::Vector3::CreateSelectCmpGreater(e,zero,m_min,miE); - } - AZ_FORCE_INLINE int Classify(const AZ::Vector3& n,const float o,int s) const - { - AZ::Vector3 pi, px; - switch(s) - { - case (0+0+0): px=m_min; - pi=m_max; break; - case (1+0+0): px=AZ::Vector3(m_max.GetX(),m_min.GetY(),m_min.GetZ()); - pi=AZ::Vector3(m_min.GetX(),m_max.GetY(),m_max.GetZ());break; - case (0+2+0): px=AZ::Vector3(m_min.GetX(),m_max.GetY(),m_min.GetZ()); - pi=AZ::Vector3(m_max.GetX(),m_min.GetY(),m_max.GetZ());break; - case (1+2+0): px=AZ::Vector3(m_max.GetX(),m_max.GetY(),m_min.GetZ()); - pi=AZ::Vector3(m_min.GetX(),m_min.GetY(),m_max.GetZ());break; - case (0+0+4): px=AZ::Vector3(m_min.GetX(),m_min.GetY(),m_max.GetZ()); - pi=AZ::Vector3(m_max.GetX(),m_max.GetY(),m_min.GetZ());break; - case (1+0+4): px=AZ::Vector3(m_max.GetX(),m_min.GetY(),m_max.GetZ()); - pi=AZ::Vector3(m_min.GetX(),m_max.GetY(),m_min.GetZ());break; - case (0+2+4): px=AZ::Vector3(m_min.GetX(),m_max.GetY(),m_max.GetZ()); - pi=AZ::Vector3(m_max.GetX(),m_min.GetY(),m_min.GetZ());break; - case (1+2+4): px=m_max; - pi=m_min;break; - } - - if (n.Dot(px) + o < 0.0f) - { - return -1; - } - if (n.Dot(pi) + o > 0.0f) - { - return 1; - } - - return 0; - } - AZ_FORCE_INLINE float ProjectMinimum(const AZ::Vector3& v, unsigned signs) const - { - const AZ::Vector3* b[]={&m_max,&m_min}; - const AZ::Vector3 p( b[(signs>>0)&1]->GetX(),b[(signs>>1)&1]->GetY(),b[(signs>>2)&1]->GetZ()); - return p.Dot(v); - } - - // Move the code here - AZ_FORCE_INLINE friend bool IntersectAabbAabb(const DynamicTreeAabb& a,const DynamicTreeAabb& b); - AZ_FORCE_INLINE friend bool IntersectAabbPoint(const DynamicTreeAabb& a, const AZ::Vector3& b); - AZ_FORCE_INLINE friend bool IntersectAabbPlane(const DynamicTreeAabb& a, const AZ::Plane& b); - AZ_FORCE_INLINE friend float Proximity(const DynamicTreeAabb& a, const DynamicTreeAabb& b); - AZ_FORCE_INLINE friend int Select(const DynamicTreeAabb& o, const DynamicTreeAabb& a, const DynamicTreeAabb& b); - AZ_FORCE_INLINE friend void Merge(const DynamicTreeAabb& a, const DynamicTreeAabb& b, DynamicTreeAabb& r); - AZ_FORCE_INLINE friend bool NotEqual(const DynamicTreeAabb& a, const DynamicTreeAabb& b); - private: - AZ_FORCE_INLINE void AddSpan(const AZ::Vector3& d, float& smi, float& smx) const - { - AZ::Vector3 vecZero = AZ::Vector3::CreateZero(); - AZ::Vector3 mxD = m_max*d; - AZ::Vector3 miD = m_min*d; - AZ::Vector3 smiAdd = AZ::Vector3::CreateSelectCmpGreater(vecZero,d,mxD,miD); - AZ::Vector3 smxAdd = AZ::Vector3::CreateSelectCmpGreater(vecZero,d,miD,mxD); - AZ::Vector3 vecOne = AZ::Vector3::CreateOne(); - // sum components - smi += smiAdd.Dot(vecOne); - smx += smxAdd.Dot(vecOne); - } - }; - - // - AZ_FORCE_INLINE bool IntersectAabbAabb(const DynamicTreeAabb& a, const DynamicTreeAabb& b) - { - return a.Overlaps(b); - } - - AZ_FORCE_INLINE bool IntersectAabbPlane(const DynamicTreeAabb& a, const AZ::Plane& b) - { - //use plane normal to quickly select the nearest corner of the aabb - AZ::Vector3 testPoint = AZ::Vector3::CreateSelectCmpGreater(b.GetNormal(), AZ::Vector3::CreateZero(), a.GetMin(), a.GetMax()); - //test if nearest point is inside the plane - return b.GetPointDist(testPoint) <= 0.0f; - } - - // - AZ_FORCE_INLINE float Proximity(const DynamicTreeAabb& a, const DynamicTreeAabb& b) - { - const AZ::Vector3 d=(a.m_min+a.m_max)-(b.m_min+b.m_max); - // get abs and sum - return d.GetAbs().Dot(AZ::Vector3::CreateOne()); - } - - // - AZ_FORCE_INLINE int Select( const DynamicTreeAabb& o, const DynamicTreeAabb& a, const DynamicTreeAabb& b) - { - return Proximity(o,a) < Proximity(o,b); - } - - // - AZ_FORCE_INLINE void Merge(const DynamicTreeAabb& a, const DynamicTreeAabb& b, DynamicTreeAabb& r) - { - r.m_min = AZ::Vector3::CreateSelectCmpGreater(b.m_min,a.m_min,a.m_min,b.m_min); - r.m_max = AZ::Vector3::CreateSelectCmpGreater(a.m_max,b.m_max,a.m_max,b.m_max); - } - - // - AZ_FORCE_INLINE bool NotEqual( const DynamicTreeAabb& a, const DynamicTreeAabb& b) - { - return (a.m_min != b.m_min || a.m_max != b.m_max); - } - - - /* NodeType */ - struct DynamicTreeNode - { - GM_CLASS_ALLOCATOR(DynamicTreeNode); - - DynamicTreeAabb m_volume; - DynamicTreeNode* m_parent; - AZ_FORCE_INLINE bool IsLeaf() const { return(m_childs[1]==0); } - AZ_FORCE_INLINE bool IsInternal() const { return(!IsLeaf()); } - union - { - DynamicTreeNode* m_childs[2]; - void* m_data; - int m_dataAsInt; - }; - }; - } - - /** - * Implementation of dynamic aabb tree, based on the bullet dynamic tree (btDbvt). - * - * The BvDynamicTree class implements a fast dynamic bounding volume tree based on axis aligned bounding boxes (aabb tree). - * This BvDynamicTree is used for soft body collision detection and for the btDbvtBroadphase. It has a fast insert, remove and update of nodes. - * Unlike the BvTreeQuantized, nodes can be dynamically moved around, which allows for change in topology of the underlying data structure. - */ - class BvDynamicTree - { - public: - using Ptr = AZStd::intrusive_ptr; - - GM_CLASS_ALLOCATOR(BvDynamicTree); - - typedef Internal::DynamicTreeAabb VolumeType; - typedef Internal::DynamicTreeNode NodeType; - - typedef vector NodeArrayType; - typedef vector ConstNodeArrayType; - - private: - - /* Stack element */ - struct sStkNN - { - const NodeType* a; - const NodeType* b; - sStkNN() {} - sStkNN(const NodeType* na,const NodeType* nb) : a(na), b(nb) {} - }; - struct sStkNP - { - const NodeType* node; - int mask; - sStkNP(const NodeType* n, unsigned m) : node(n), mask(m) {} - }; - struct sStkNPS - { - const NodeType* node; - int mask; - float value; - sStkNPS() {} - sStkNPS(const NodeType* n, unsigned m, const float v) : node(n), mask(m), value(v) {} - }; - struct sStkCLN - { - const NodeType* node; - NodeType* parent; - sStkCLN(const NodeType* n, NodeType* p) : node(n), parent(p) {} - }; - - public: - /* ICollideCollector templated collectors should implement this functions or inherit from this class */ - struct ICollideCollector - { - void Process(const NodeType*, const NodeType*) {} - void Process(const NodeType*) {} - void Process(const NodeType* n, const float) { Process(n); } - bool Descent(const NodeType*) { return true; } - bool AllLeaves(const NodeType*) { return true; } - }; - - /* IWriter */ - struct IWriter - { - virtual ~IWriter() {} - virtual void Prepare(const NodeType* root,int numnodes) = 0; - virtual void WriteNode(const NodeType*, int index, int parent, int child0, int child1) = 0; - virtual void WriteLeaf(const NodeType*, int index, int parent) = 0; - }; - /* IClone */ - struct IClone - { - virtual ~IClone() {} - virtual void CloneLeaf(NodeType*) {} - }; - - // Constants - enum - { - SIMPLE_STACKSIZE = 64, - DOUBLE_STACKSIZE = SIMPLE_STACKSIZE * 2 - }; - - // Methods - BvDynamicTree(); - ~BvDynamicTree(); - - NodeType* GetRoot() const { return m_root; } - void Clear(); - bool Empty() const { return 0 == m_root; } - int GetNumLeaves() const { return m_leaves; } - void OptimizeBottomUp(); - void OptimizeTopDown(int bu_treshold = 128); - void OptimizeIncremental(int passes); - NodeType* Insert(const VolumeType& box,void* data); - void Update(NodeType* leaf, int lookahead=-1); - void Update(NodeType* leaf, VolumeType& volume); - bool Update(NodeType* leaf, VolumeType& volume, const AZ::Vector3& velocity, const float margin); - bool Update(NodeType* leaf, VolumeType& volume, const AZ::Vector3& velocity); - bool Update(NodeType* leaf, VolumeType& volume, const float margin); - void Remove(NodeType* leaf); - void Write(IWriter* iwriter) const; - void Clone(BvDynamicTree& dest, IClone* iclone=0) const; - static int GetMaxDepth(const NodeType* node); - static int CountLeaves(const NodeType* node); - static void ExtractLeaves(const NodeType* node, /*btAlignedObjectArray&*/vector& leaves); - #if DBVT_ENABLE_BENCHMARK - static void Benchmark(); - #else - static void Benchmark(){} - #endif - /** - * Collector should inherit from ICollide - */ - template - static inline void enumNodes( const NodeType* root, Collector& collector) - { - collector.Process(root); - if(root->IsInternal()) - { - enumNodes(root->m_childs[0],collector); - enumNodes(root->m_childs[1],collector); - } - } - template - static void enumLeaves( const NodeType* root,Collector& collector) - { - if(root->IsInternal()) - { - enumLeaves(root->m_childs[0],collector); - enumLeaves(root->m_childs[1],collector); - } - else - { - collector.Process(root); - } - } - template - void collideTT( const NodeType* root0,const NodeType* root1,Collector& collector) const - { - if(root0&&root1) - { - size_t depth=1; - size_t treshold=DOUBLE_STACKSIZE-4; - vector stkStack; - stkStack.resize(DOUBLE_STACKSIZE); - stkStack[0]=sStkNN(root0,root1); - do { - sStkNN p=stkStack[--depth]; - if(depth>treshold) - { - stkStack.resize(stkStack.size()*2); - treshold=stkStack.size()-4; - } - if(p.a==p.b) - { - if(p.a->IsInternal()) - { - stkStack[depth++]=sStkNN(p.a->m_childs[0],p.a->m_childs[0]); - stkStack[depth++]=sStkNN(p.a->m_childs[1],p.a->m_childs[1]); - stkStack[depth++]=sStkNN(p.a->m_childs[0],p.a->m_childs[1]); - } - } - else if(IntersectAabbAabb(p.a->m_volume,p.b->m_volume)) - { - if(p.a->IsInternal()) - { - if(p.b->IsInternal()) - { - stkStack[depth++]=sStkNN(p.a->m_childs[0],p.b->m_childs[0]); - stkStack[depth++]=sStkNN(p.a->m_childs[1],p.b->m_childs[0]); - stkStack[depth++]=sStkNN(p.a->m_childs[0],p.b->m_childs[1]); - stkStack[depth++]=sStkNN(p.a->m_childs[1],p.b->m_childs[1]); - } - else - { - stkStack[depth++]=sStkNN(p.a->m_childs[0],p.b); - stkStack[depth++]=sStkNN(p.a->m_childs[1],p.b); - } - } - else - { - if(p.b->IsInternal()) - { - stkStack[depth++]=sStkNN(p.a,p.b->m_childs[0]); - stkStack[depth++]=sStkNN(p.a,p.b->m_childs[1]); - } - else - { - collector.Process(p.a,p.b); - } - } - } - } while(depth); - } - } - template - void collideTTpersistentStack( const NodeType* root0, const NodeType* root1,Collector& collector) - { - if(root0&&root1) - { - size_t depth=1; - size_t treshold=DOUBLE_STACKSIZE-4; - - m_stkStack.resize(DOUBLE_STACKSIZE); - m_stkStack[0]=sStkNN(root0,root1); - do - { - sStkNN p=m_stkStack[--depth]; - if(depth>treshold) - { - m_stkStack.resize(m_stkStack.size()*2); - treshold=m_stkStack.size()-4; - } - if(p.a==p.b) - { - if(p.a->IsInternal()) - { - m_stkStack[depth++]=sStkNN(p.a->m_childs[0],p.a->m_childs[0]); - m_stkStack[depth++]=sStkNN(p.a->m_childs[1],p.a->m_childs[1]); - m_stkStack[depth++]=sStkNN(p.a->m_childs[0],p.a->m_childs[1]); - } - } - else if(IntersectAabbAabb(p.a->m_volume,p.b->m_volume)) - { - if(p.a->IsInternal()) - { - if(p.b->IsInternal()) - { - m_stkStack[depth++]=sStkNN(p.a->m_childs[0],p.b->m_childs[0]); - m_stkStack[depth++]=sStkNN(p.a->m_childs[1],p.b->m_childs[0]); - m_stkStack[depth++]=sStkNN(p.a->m_childs[0],p.b->m_childs[1]); - m_stkStack[depth++]=sStkNN(p.a->m_childs[1],p.b->m_childs[1]); - } - else - { - m_stkStack[depth++]=sStkNN(p.a->m_childs[0],p.b); - m_stkStack[depth++]=sStkNN(p.a->m_childs[1],p.b); - } - } - else - { - if(p.b->IsInternal()) - { - m_stkStack[depth++]=sStkNN(p.a,p.b->m_childs[0]); - m_stkStack[depth++]=sStkNN(p.a,p.b->m_childs[1]); - } - else - { - collector.Process(p.a,p.b); - } - } - } - } while(depth); - } - } - template - void collideTV( const NodeType* root, const VolumeType& volume, Collector& collector) const - { - if(root) - { -// ATTRIBUTE_ALIGNED16(VolumeType) volume(vol); -// btAlignedObjectArray stack; - AZStd::fixed_vector stack; - //stack.reserve(SIMPLE_STACKSIZE); - stack.push_back(root); - do { - const NodeType* n=stack[stack.size()-1]; - stack.pop_back(); - if(IntersectAabbAabb(n->m_volume,volume)) - { - if(n->IsInternal()) - { - stack.push_back(n->m_childs[0]); - stack.push_back(n->m_childs[1]); - } - else - { - collector.Process(n); - } - } - } while(!stack.empty()); - } - } - - template - void collideTP(const NodeType* root, const AZ::Plane& plane, Collector& collector) const - { - if (root) - { - AZStd::fixed_vector stack; - stack.push_back(root); - do - { - const NodeType* n=stack[stack.size()-1]; - stack.pop_back(); - if (IntersectAabbPlane(n->m_volume, plane)) - { - if(n->IsInternal()) - { - stack.push_back(n->m_childs[0]); - stack.push_back(n->m_childs[1]); - } - else - { - collector.Process(n); - } - } - } while (!stack.empty()); - } - } - - ///rayTest is a re-entrant ray test, and can be called in parallel as long as the btAlignedAlloc is thread-safe (uses locking etc) - ///rayTest is slower than rayTestInternal, because it builds a local stack, using memory allocations, and it recomputes signs/rayDirectionInverses each time - template - static void rayTest( const NodeType* root, const AZ::Vector3& rayFrom, const AZ::Vector3& rayTo, Collector& collector) - { - if(root) - { - AZ::Vector3 ray = rayTo-rayFrom; - AZ::Vector3 rayDir = ray.GetNormalized(); - - ///what about division by zero? --> just set rayDirection[i] to INF/1e30 - AZ::Vector3 rayDirectionInverse = AZ::Vector3::CreateSelectCmpEqual(rayDir,AZ::Vector3::CreateZero(),AZ::Vector3(1e30),rayDir.GetReciprocal()); - - unsigned int signs[3];// = { rayDirectionInverse[0] < 0.0f, rayDirectionInverse[1] < 0.0f, rayDirectionInverse[2] < 0.0f }; - signs[0] = rayDirectionInverse.GetX() < 0.0f; - signs[1] = rayDirectionInverse.GetY() < 0.0f; - signs[2] = rayDirectionInverse.GetZ() < 0.0f; - - //float lambda_max = rayDir.Dot(ray); - - AZ::Vector3 resultNormal; - - //btAlignedObjectArray stack; - vector stack; - - int depth=1; - int treshold=DOUBLE_STACKSIZE-2; - - stack.resize(DOUBLE_STACKSIZE); - stack[0]=root; - AZ::Vector3 bounds[2]; - do { - const NodeType* node=stack[--depth]; - - bounds[0] = node->m_volume.GetMin(); - bounds[1] = node->m_volume.GetMax(); - - //float tmin = 1.0f; - //float lambda_min = 0.0f; - // todo.. - unsigned int result1 = /*btRayAabb2(rayFrom,rayDirectionInverse,signs,bounds,tmin,lambda_min,lambda_max)*/0; -#ifdef COMPARE_BTRAY_AABB2 - float param = 1.0f; - bool result2 = /*btRayAabb(rayFrom,rayTo,node->volume.GetMin(),node->volume.GetMax(),param,resultNormal)*/0; - AZ_Assert(result1 == result2, ""); -#endif //TEST_BTRAY_AABB2 - if(result1) - { - if(node->IsInternal()) - { - if(depth>treshold) - { - stack.resize(stack.size()*2); - treshold=stack.size()-2; - } - stack[depth++]=node->m_childs[0]; - stack[depth++]=node->m_childs[1]; - } - else - { - collector.Process(node); - } - } - } while(depth); - - } - } - - ///rayTestInternal is faster than rayTest, because it uses a persistent stack (to reduce dynamic memory allocations to a minimum) and it uses precomputed signs/rayInverseDirections - ///rayTestInternal is used by btDbvtBroadphase to accelerate world ray casts - template - void rayTestInternal(const NodeType* root, const AZ::Vector3& rayFrom, const AZ::Vector3& rayTo, const AZ::Vector3& rayDirectionInverse, unsigned int signs[3], const float lambda_max, const AZ::Vector3& aabbMin, const AZ::Vector3& aabbMax, Collector& collector) const - { - (void)rayFrom;(void)rayTo;(void)rayDirectionInverse;(void)signs;(void)lambda_max; - if(root) - { - AZ::Vector3 resultNormal; - - int depth=1; - int treshold=DOUBLE_STACKSIZE-2; - vector stack; - stack.resize(DOUBLE_STACKSIZE); - stack[0]=root; - AZ::Vector3 bounds[2]; - do - { - const NodeType* node=stack[--depth]; - bounds[0] = node->m_volume.GetMin()+aabbMin; - bounds[1] = node->m_volume.GetMax()+aabbMax; - - //float tmin = 1.0f; - //float lambda_min = 0.0f; - unsigned int result1=false; - // todo... - result1 = /*btRayAabb2(rayFrom,rayDirectionInverse,signs,bounds,tmin,lambda_min,lambda_max)*/false; - if(result1) - { - if(node->IsInternal()) - { - if(depth>treshold) - { - stack.resize(stack.size()*2); - treshold=stack.size()-2; - } - stack[depth++]=node->m_childs[0]; - stack[depth++]=node->m_childs[1]; - } - else - { - collector.Process(node); - } - } - } while(depth); - } - } - - template - static void collideKDOP(const NodeType* root, const AZ::Vector3* normals, const float* offsets, int count, Collector& collector) - { - (void)root;(void)normals;(void)offsets;(void)count;(void)collector; -/* if(root) - { - const int inside=(1< stack; - int signs[sizeof(unsigned)*8]; - btAssert(count=0)?1:0)+ - ((normals[i].y()>=0)?2:0)+ - ((normals[i].z()>=0)?4:0); - } - stack.reserve(SIMPLE_STACKSIZE); - stack.push_back(sStkNP(root,0)); - do { - sStkNP se=stack[stack.size()-1]; - bool out=false; - stack.pop_back(); - for(int i=0,j=1;(!out)&&(ivolume.Classify(normals[i],offsets[i],signs[i]); - switch(side) - { - case -1: out=true;break; - case +1: se.mask|=j;break; - } - } - } - if(!out) - { - if((se.mask!=inside)&&(se.node->isinternal())) - { - stack.push_back(sStkNP(se.node->childs[0],se.mask)); - stack.push_back(sStkNP(se.node->childs[1],se.mask)); - } - else - { - if(policy.AllLeaves(se.node)) enumLeaves(se.node,policy); - } - } - } while(!stack.empty()); - }*/ - } - template - static void collideOCL( const NodeType* root, const AZ::Vector3* normals, const float* offsets, const AZ::Vector3& sortaxis, int count, Collector& collector, bool fullsort=true) - { - (void)root;(void)normals;(void)offsets;(void)sortaxis;(void)count;(void)offsets;(void)collector;(void)fullsort; -/* if(root) - { - const unsigned srtsgns=(sortaxis[0]>=0?1:0)+ - (sortaxis[1]>=0?2:0)+ - (sortaxis[2]>=0?4:0); - const int inside=(1< stock; - btAlignedObjectArray ifree; - btAlignedObjectArray stack; - int signs[sizeof(unsigned)*8]; - btAssert(count=0)?1:0)+ - ((normals[i].y()>=0)?2:0)+ - ((normals[i].z()>=0)?4:0); - } - stock.reserve(SIMPLE_STACKSIZE); - stack.reserve(SIMPLE_STACKSIZE); - ifree.reserve(SIMPLE_STACKSIZE); - stack.push_back(allocate(ifree,stock,sStkNPS(root,0,root->volume.ProjectMinimum(sortaxis,srtsgns)))); - do { - const int id=stack[stack.size()-1]; - sStkNPS se=stock[id]; - stack.pop_back();ifree.push_back(id); - if(se.mask!=inside) - { - bool out=false; - for(int i=0,j=1;(!out)&&(ivolume.Classify(normals[i],offsets[i],signs[i]); - switch(side) - { - case -1: out=true;break; - case +1: se.mask|=j;break; - } - } - } - if(out) continue; - } - if(policy.Descent(se.node)) - { - if(se.node->isinternal()) - { - const NodeType* pns[]={ se.node->childs[0],se.node->childs[1]}; - sStkNPS nes[]={ sStkNPS(pns[0],se.mask,pns[0]->volume.ProjectMinimum(sortaxis,srtsgns)), - sStkNPS(pns[1],se.mask,pns[1]->volume.ProjectMinimum(sortaxis,srtsgns))}; - const int q=nes[0].value0)) - { - // Insert 0 - j=nearest(&stack[0],&stock[0],nes[q].value,0,stack.size()); - stack.push_back(0); -#if DBVT_USE_MEMMOVE - memmove(&stack[j+1],&stack[j],sizeof(int)*(stack.size()-j-1)); -#else - for(int k=stack.size()-1;k>j;--k) stack[k]=stack[k-1]; -#endif - stack[j]=allocate(ifree,stock,nes[q]); - // Insert 1 - j=nearest(&stack[0],&stock[0],nes[1-q].value,j,stack.size()); - stack.push_back(0); -#if DBVT_USE_MEMMOVE - memmove(&stack[j+1],&stack[j],sizeof(int)*(stack.size()-j-1)); -#else - for(int k=stack.size()-1;k>j;--k) stack[k]=stack[k-1]; -#endif - stack[j]=allocate(ifree,stock,nes[1-q]); - } - else - { - stack.push_back(allocate(ifree,stock,nes[q])); - stack.push_back(allocate(ifree,stock,nes[1-q])); - } - } - else - { - policy.Process(se.node,se.value); - } - } - } while(stack.size()); - }*/ - } - - template - static void collideTU(const NodeType* root, Collector& collector) - { - (void)root;(void)collector; -/* if(root) - { - btAlignedObjectArray stack; - stack.reserve(SIMPLE_STACKSIZE); - stack.push_back(root); - do { - const NodeType* n=stack[stack.size()-1]; - stack.pop_back(); - if(policy.Descent(n)) - { - if(n->isinternal()) - { stack.push_back(n->childs[0]);stack.push_back(n->childs[1]); } - else - { policy.Process(n); } - } - } while(stack.size()>0); - }*/ - } - - private: - BvDynamicTree(const BvDynamicTree&) {} - - // Helpers - //static AZ_FORCE_INLINE int nearest(const int* i,const BvDynamicTree::sStkNPS* a,const float& v,int l,int h) - //{ - // int m=0; - // while(l>1; - // if(a[i[m]].value>=v) l=m+1; else h=m; - // } - // return h; - //} - //static AZ_FORCE_INLINE int allocate( int_fixed_stack_type& ifree, stknps_fixed_stack_type& stock, const sStkNPS& value) - //{ - // int i; - // if( !ifree.empty() ) - // { - // i=ifree[ifree.size()-1]; - // ifree.pop_back(); - // stock[i]=value; - // } - // else - // { - // i=stock.size(); - // stock.push_back(value); - // } - // return i; - //} - // - - AZ_FORCE_INLINE void deletenode( NodeType* node) - { - //btAlignedFree(pdbvt->m_free); - delete m_free; - m_free=node; - } - - void recursedeletenode( NodeType* node) - { - if(!node->IsLeaf()) - { - recursedeletenode(node->m_childs[0]); - recursedeletenode(node->m_childs[1]); - } - - if( node == m_root ) m_root=0; - deletenode(node); - } - - - AZ_FORCE_INLINE NodeType* createnode( NodeType* parent, void* data) - { - NodeType* node; - if(m_free) - { node=m_free;m_free=0; } - else - { node = aznew NodeType(); } - node->m_parent = parent; - node->m_data = data; - node->m_childs[1] = 0; - return node; - } - AZ_FORCE_INLINE NodeType* createnode( BvDynamicTree::NodeType* parent, const VolumeType& volume, void* data) - { - NodeType* node = createnode(parent,data); - node->m_volume=volume; - return node; - } - // - AZ_FORCE_INLINE NodeType* createnode( BvDynamicTree::NodeType* parent, const VolumeType& volume0, const VolumeType& volume1, void* data) - { - NodeType* node = createnode(parent,data); - Merge(volume0,volume1,node->m_volume); - return node; - } - void insertleaf( NodeType* root, NodeType* leaf); - NodeType* removeleaf( NodeType* leaf); - void fetchleaves(NodeType* root,NodeArrayType& leaves,int depth=-1); - void split(const NodeArrayType& leaves,NodeArrayType& left,NodeArrayType& right,const AZ::Vector3& org,const AZ::Vector3& axis); - VolumeType bounds(const NodeArrayType& leaves); - void bottomup( NodeArrayType& leaves ); - NodeType* topdown(NodeArrayType& leaves,int bu_treshold); - AZ_FORCE_INLINE NodeType* sort(NodeType* n,NodeType*& r); - - NodeType* m_root; - NodeType* m_free; - int m_lkhd; - int m_leaves; - unsigned m_opath; - - //btAlignedObjectArray m_stkStack; - // Profile and choose static or dynamic vector. - typedef AZStd::fixed_vector stknn_fixed_stack_type; - typedef AZStd::fixed_vector int_fixed_stack_type; - typedef AZStd::fixed_vector stknps_fixed_stack_type; - - stknn_fixed_stack_type m_stkStack; - }; -} - -#endif // RR_DYNAMIC_BOUNDING_VOLUME_TREE_H -#pragma once diff --git a/Code/Framework/GridMate/GridMate/Replica/Interest/ProximityInterestHandler.cpp b/Code/Framework/GridMate/GridMate/Replica/Interest/ProximityInterestHandler.cpp deleted file mode 100644 index 13a0151bc7..0000000000 --- a/Code/Framework/GridMate/GridMate/Replica/Interest/ProximityInterestHandler.cpp +++ /dev/null @@ -1,597 +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 - -#include -#include -#include - -#include -#include - -// for highly verbose internal debugging -//#define INTERNAL_DEBUG_PROXIMITY - -namespace GridMate -{ - - void ProximityInterestChunk::OnReplicaActivate(const ReplicaContext& rc) - { - m_interestHandler = static_cast(rc.m_rm->GetUserContext(AZ_CRC("ProximityInterestHandler", 0x3a90b3e4))); - AZ_Warning("GridMate", m_interestHandler, "No proximity interest handler in the user context"); - - if (m_interestHandler) - { - m_interestHandler->OnNewRulesChunk(this, rc.m_peer); - } - } - - void ProximityInterestChunk::OnReplicaDeactivate(const ReplicaContext& rc) - { - if (rc.m_peer && m_interestHandler) - { - m_interestHandler->OnDeleteRulesChunk(this, rc.m_peer); - } - } - - bool ProximityInterestChunk::AddRuleFn(RuleNetworkId netId, AZ::Aabb bbox, const RpcContext& ctx) - { - if (IsProxy()) - { - auto rulePtr = m_interestHandler->CreateRule(ctx.m_sourcePeer); - rulePtr->Set(bbox); - m_rules.insert(AZStd::make_pair(netId, rulePtr)); - } - - return true; - } - - bool ProximityInterestChunk::RemoveRuleFn(RuleNetworkId netId, const RpcContext&) - { - if (IsProxy()) - { - m_rules.erase(netId); - } - - return true; - } - - bool ProximityInterestChunk::UpdateRuleFn(RuleNetworkId netId, AZ::Aabb bbox, const RpcContext&) - { - if (IsProxy()) - { - auto it = m_rules.find(netId); - if (it != m_rules.end()) - { - it->second->Set(bbox); - } - } - - return true; - } - - bool ProximityInterestChunk::AddRuleForPeerFn(RuleNetworkId netId, PeerId peerId, AZ::Aabb bbox, const RpcContext&) - { - ProximityInterestChunk* peerChunk = m_interestHandler->FindRulesChunkByPeerId(peerId); - if (peerChunk) - { - auto it = peerChunk->m_rules.find(netId); - if (it == peerChunk->m_rules.end()) - { - auto rulePtr = m_interestHandler->CreateRule(peerId); - peerChunk->m_rules.insert(AZStd::make_pair(netId, rulePtr)); - rulePtr->Set(bbox); - } - } - return false; - } - /////////////////////////////////////////////////////////////////////////// - - - /* - * ProximityInterest - */ - ProximityInterest::ProximityInterest(ProximityInterestHandler* handler) - : m_handler(handler) - , m_bbox(AZ::Aabb::CreateNull()) - { - AZ_Assert(m_handler, "Invalid interest handler"); - } - /////////////////////////////////////////////////////////////////////////// - - - /* - * ProximityInterestRule - */ - void ProximityInterestRule::Set(const AZ::Aabb& bbox) - { - m_bbox = bbox; - m_handler->UpdateRule(this); - } - - void ProximityInterestRule::Destroy() - { - m_handler->DestroyRule(this); - } - /////////////////////////////////////////////////////////////////////////// - - - /* - * ProximityInterestAttribute - */ - void ProximityInterestAttribute::Set(const AZ::Aabb& bbox) - { - m_bbox = bbox; - m_handler->UpdateAttribute(this); - } - - void ProximityInterestAttribute::Destroy() - { - m_handler->DestroyAttribute(this); - } - /////////////////////////////////////////////////////////////////////////// - - - /* - * ProximityInterestHandler - */ - ProximityInterestHandler::ProximityInterestHandler() - : m_im(nullptr) - , m_rm(nullptr) - , m_lastRuleNetId(0) - , m_rulesReplica(nullptr) - { - m_attributeWorld = AZStd::make_unique(); - AZ_Assert(m_attributeWorld, "Out of memory"); - } - - ProximityInterestRule::Ptr ProximityInterestHandler::CreateRule(PeerId peerId) - { - ProximityInterestRule* rulePtr = aznew ProximityInterestRule(this, peerId, GetNewRuleNetId()); - if (m_rm && peerId == m_rm->GetLocalPeerId()) - { - m_rulesReplica->AddRuleRpc(rulePtr->GetNetworkId(), rulePtr->Get()); - } - - CreateAndInsertIntoSpatialStructure(rulePtr); - - return rulePtr; - } - - ProximityInterestAttribute::Ptr ProximityInterestHandler::CreateAttribute(ReplicaId replicaId) - { - auto newAttribute = aznew ProximityInterestAttribute(this, replicaId); - AZ_Assert(newAttribute, "Out of memory"); - - CreateAndInsertIntoSpatialStructure(newAttribute); - - return newAttribute; - } - - void ProximityInterestHandler::FreeRule(ProximityInterestRule* rule) - { - //TODO: should be pool-allocated - delete rule; - } - - void ProximityInterestHandler::DestroyRule(ProximityInterestRule* rule) - { - if (m_rm && rule->GetPeerId() == m_rm->GetLocalPeerId()) - { - m_rulesReplica->RemoveRuleRpc(rule->GetNetworkId()); - } - - MarkAttributesDirtyInRule(rule); - - rule->m_bbox = AZ::Aabb::CreateNull(); - m_removedRules.insert(rule); - m_localRules.erase(rule); - } - - void ProximityInterestHandler::UpdateRule(ProximityInterestRule* rule) - { - if (m_rm && rule->GetPeerId() == m_rm->GetLocalPeerId()) - { - m_rulesReplica->UpdateRuleRpc(rule->GetNetworkId(), rule->Get()); - } - - m_dirtyRules.insert(rule); - } - - void ProximityInterestHandler::FreeAttribute(ProximityInterestAttribute* attrib) - { - delete attrib; - } - - void ProximityInterestHandler::DestroyAttribute(ProximityInterestAttribute* attrib) - { - RemoveFromSpatialStructure(attrib); - - m_attributes.erase(attrib); - m_removedAttributes.insert(attrib); - } - - void ProximityInterestHandler::RemoveFromSpatialStructure(ProximityInterestAttribute* attribute) - { - attribute->m_bbox = AZ::Aabb::CreateNull(); - m_attributeWorld->Remove(attribute->GetNode()); - attribute->SetNode(nullptr); - } - - void ProximityInterestHandler::UpdateAttribute(ProximityInterestAttribute* attrib) - { - auto node = attrib->GetNode(); - AZ_Assert(node, "Attribute wasn't created correctly"); - node->m_volume = attrib->Get(); - m_attributeWorld->Update(node); - - m_dirtyAttributes.insert(attrib); - } - - void ProximityInterestHandler::OnNewRulesChunk(ProximityInterestChunk* chunk, ReplicaPeer* peer) - { - if (chunk != m_rulesReplica) // non-local - { - m_peerChunks.insert(AZStd::make_pair(peer->GetId(), chunk)); - - for (auto& rule : m_localRules) - { - chunk->AddRuleForPeerRpc(rule->GetNetworkId(), rule->GetPeerId(), rule->Get()); - } - } - } - - void ProximityInterestHandler::OnDeleteRulesChunk(ProximityInterestChunk* chunk, ReplicaPeer* peer) - { - (void)chunk; - m_peerChunks.erase(peer->GetId()); - } - - RuleNetworkId ProximityInterestHandler::GetNewRuleNetId() - { - ++m_lastRuleNetId; - - if (m_rulesReplica) - { - return m_rulesReplica->GetReplicaId() | (static_cast(m_lastRuleNetId) << 32); - } - - return (static_cast(m_lastRuleNetId) << 32); - } - - ProximityInterestChunk* ProximityInterestHandler::FindRulesChunkByPeerId(PeerId peerId) - { - auto it = m_peerChunks.find(peerId); - if (it == m_peerChunks.end()) - { - return nullptr; - } - - return it->second; - } - - const InterestMatchResult& ProximityInterestHandler::GetLastResult() - { - return m_resultCache; - } - - ProximityInterestHandler::RuleSet& ProximityInterestHandler::GetAffectedRules() - { - /* - * The expectation that lots of attributes will change frequently, - * so there is no point in trying to optimize cases - * where only a few attributes have changed. - */ - if (m_dirtyAttributes.empty() && !m_dirtyRules.empty()) - { - return m_dirtyRules; - } - - /* - * Assuming all rules might have been affected. - * - * There is an optimization chance here if the number of rules is large, as in 1,000+ rules. - * To handle such scale we would need another spatial structure for rules. - */ - return m_localRules; - } - - void ProximityInterestHandler::GetAttributesWithinRule(ProximityInterestRule* rule, SpatialIndex::NodeCollector& nodes) - { - m_attributeWorld->Query(rule->Get(), nodes); - } - - void ProximityInterestHandler::ClearDirtyState() - { - m_dirtyAttributes.clear(); - m_dirtyRules.clear(); - } - - void ProximityInterestHandler::CreateAndInsertIntoSpatialStructure(ProximityInterestAttribute* attribute) - { - m_attributes.insert(attribute); - SpatialIndex::Node* node = m_attributeWorld->Insert(attribute->Get(), attribute); - attribute->SetNode(node); - } - - void ProximityInterestHandler::CreateAndInsertIntoSpatialStructure(ProximityInterestRule* rule) - { - m_localRules.insert(rule); - } - - void ProximityInterestHandler::UpdateInternal(InterestMatchResult& result) - { - /* - * The goal is to return all dirty attributes that were either dirty because: - * 1) they changed which rules have apply to - * 2) rules have changed and no longer apply to those attributes - * and thus resulted in different peer(s) associated with a given replica. - */ - - const RuleSet& rules = GetAffectedRules(); - - for (auto& dirtyAttribute : m_dirtyAttributes) - { - result.insert(dirtyAttribute->GetReplicaId()); - } - - /* - * The exectation is to have a lot more attributes than rules. - * The amount of rules should grow linear with amount of peers, - * so it should be OK to iterate through all rules each update. - */ - for (auto& rule : rules) - { - CheckChangesForRule(rule, result); - } - - for (auto& removedRule : m_removedRules) - { - FreeRule(removedRule); - } - m_removedRules.clear(); - - // mark removed attribute as having no peers - for (auto& removedAttribute : m_removedAttributes) - { - result.insert(removedAttribute->GetReplicaId()); - FreeAttribute(removedAttribute); - } - m_removedAttributes.clear(); - } - - void ProximityInterestHandler::CheckChangesForRule(ProximityInterestRule* rule, InterestMatchResult& result) - { - SpatialIndex::NodeCollector collector; - GetAttributesWithinRule(rule, collector); - - auto peerId = rule->GetPeerId(); - for (ProximityInterestAttribute* attr : collector.GetNodes()) - { - AZ_Assert(attr, "bad node?"); - - auto findIt = result.find(attr->GetReplicaId()); - if (findIt != result.end()) - { - findIt->second.insert(peerId); - } - else - { - auto resultIt = result.insert(attr->GetReplicaId()); - AZ_Assert(resultIt.second, "Successfully inserted"); - resultIt.first->second.insert(peerId); - } - } - } - - void ProximityInterestHandler::MarkAttributesDirtyInRule(ProximityInterestRule* rule) - { - SpatialIndex::NodeCollector collector; - GetAttributesWithinRule(rule, collector); - - for (ProximityInterestAttribute* attr : collector.GetNodes()) - { - AZ_Assert(attr, "bad node?"); - - UpdateAttribute(attr); - } - } - - void ProximityInterestHandler::ProduceChanges(const InterestMatchResult& before, const InterestMatchResult& after) - { - m_resultCache.clear(); - -#if defined(INTERNAL_DEBUG_PROXIMITY) - before.PrintMatchResult("before"); - after.PrintMatchResult("after"); -#endif - - /* - * 'after' contains only the stuff that might have changed - */ - for (auto& possiblyDirty : after) - { - ReplicaId repId = possiblyDirty.first; - const InterestPeerSet& peerSet = possiblyDirty.second; - - auto foundInBefore = before.find(repId); - if (foundInBefore != before.end()) - { - if (!HasSamePeers(foundInBefore->second, peerSet)) - { - // was in the last calculation but has a different peer set now - m_resultCache.insert(AZStd::make_pair(repId, peerSet)); - } - } - else - { - // since it wasn't present during last calculation - m_resultCache.insert(AZStd::make_pair(repId, peerSet)); - } - } - - // Mark attributes (replicas) for removal that have not moved but a rule (clients) no longer sees it - for (auto& possiblyDirty : before) - { - ReplicaId repId = possiblyDirty.first; - - const auto foundInAfter = after.find(repId); - /* - * If the prior state was a replica A present on peer X: "A{X}", and now A should no longer be present on any peer: "A{}" - * then by the rules of InterestHandlers interacting with InterestManager, we should return in @m_resultCache the following: - * - * A{} - indicating that replica A must be removed all peers. - * - * On the next pass, the prior state would be: "A{}" and the current state would be "A{}" as well. At that point, we have - * already sent the update to remove A from X, so @m_resultCache should no longer mention A at all. - */ - if (foundInAfter == after.end() && !possiblyDirty.second.empty() /* "not A{}" see the above comment */) - { - m_resultCache.insert(AZStd::make_pair(repId, InterestPeerSet())); - } - } - -#if defined(INTERNAL_DEBUG_PROXIMITY) - m_resultCache.PrintMatchResult("changes"); -#endif - - } - - bool ProximityInterestHandler::HasSamePeers(const InterestPeerSet& one, const InterestPeerSet& another) - { - if (one.size() != another.size()) - { - return false; - } - - for (auto& peerFromOne : one) - { - if (another.find(peerFromOne) == another.end()) - { - return false; - } - } - - // Safe to assume it's the same sets since all entries are unique in a peer sets - return true; - } - - void ProximityInterestHandler::Update() - { - InterestMatchResult newResult; - - UpdateInternal(newResult); - ProduceChanges(m_lastResult, newResult); - - m_lastResult = std::move(newResult); - ClearDirtyState(); - } - - void ProximityInterestHandler::OnRulesHandlerRegistered(InterestManager* manager) - { - AZ_Assert(m_im == nullptr, "Handler is already registered with manager %p (%p)\n", m_im, manager); - AZ_Assert(m_rulesReplica == nullptr, "Rules replica is already created\n"); - AZ_TracePrintf("GridMate", "Proximity interest handler is registered\n"); - m_im = manager; - m_rm = m_im->GetReplicaManager(); - m_rm->RegisterUserContext(AZ_CRC("ProximityInterestHandler", 0x3a90b3e4), this); - - auto replica = Replica::CreateReplica("ProximityInterestHandlerRules"); - m_rulesReplica = CreateAndAttachReplicaChunk(replica); - m_rm->AddPrimary(replica); - } - - void ProximityInterestHandler::OnRulesHandlerUnregistered(InterestManager* manager) - { - (void)manager; - AZ_Assert(m_im == manager, "Handler was not registered with manager %p (%p)\n", manager, m_im); - AZ_TracePrintf("GridMate", "Proximity interest handler is unregistered\n"); - m_rulesReplica = nullptr; - m_im = nullptr; - m_rm->UnregisterUserContext(AZ_CRC("ProximityInterestHandler", 0x3a90b3e4)); - m_rm = nullptr; - - for (auto& chunk : m_peerChunks) - { - chunk.second->m_interestHandler = nullptr; - } - m_peerChunks.clear(); - - ClearDirtyState(); - DestroyAll(); - - m_resultCache.clear(); - } - - void ProximityInterestHandler::DestroyAll() - { - for (ProximityInterestRule* rule : m_localRules) - { - FreeRule(rule); - } - m_localRules.clear(); - - for (ProximityInterestAttribute* attr : m_attributes) - { - FreeAttribute(attr); - } - m_attributes.clear(); - - for (auto& removedRule : m_removedRules) - { - FreeRule(removedRule); - } - m_removedRules.clear(); - - for (auto& removedAttribute : m_removedAttributes) - { - FreeAttribute(removedAttribute); - } - m_removedAttributes.clear(); - } - - /////////////////////////////////////////////////////////////////////////// - ProximityInterestHandler::~ProximityInterestHandler() - { - /* - * If a handler was registered with a InterestManager, then InterestManager ought to have called OnRulesHandlerUnregistered - * but this is a safety pre-caution. - */ - DestroyAll(); - } - - SpatialIndex::SpatialIndex() - { - m_tree.reset(aznew GridMate::BvDynamicTree()); - } - - void SpatialIndex::Remove(Node* node) - { - m_tree->Remove(node); - } - - void SpatialIndex::Update(Node* node) - { - m_tree->Update(node); - } - - SpatialIndex::Node* SpatialIndex::Insert(const AZ::Aabb& get, ProximityInterestAttribute* attribute) - { - return m_tree->Insert(get, attribute); - } - - void SpatialIndex::Query(const AZ::Aabb& shape, NodeCollector& nodes) - { - m_tree->collideTV(m_tree->GetRoot(), shape, nodes); - } -} diff --git a/Code/Framework/GridMate/GridMate/Replica/Interest/ProximityInterestHandler.h b/Code/Framework/GridMate/GridMate/Replica/Interest/ProximityInterestHandler.h deleted file mode 100644 index 6659d44f44..0000000000 --- a/Code/Framework/GridMate/GridMate/Replica/Interest/ProximityInterestHandler.h +++ /dev/null @@ -1,314 +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. -* -*/ - -#ifndef GM_REPLICA_PROXIMITYINTERESTHANDLER_H -#define GM_REPLICA_PROXIMITYINTERESTHANDLER_H - -#include -#include -#include -#include -#include - -#include -#include - -namespace GridMate -{ - class ProximityInterestHandler; - class ProximityInterestAttribute; - - /* - * Base interest - */ - class ProximityInterest - { - friend class ProximityInterestHandler; - - public: - const AZ::Aabb& Get() const { return m_bbox; } - - protected: - explicit ProximityInterest(ProximityInterestHandler* handler); - - ProximityInterestHandler* m_handler; - AZ::Aabb m_bbox; - }; - /////////////////////////////////////////////////////////////////////////// - - - /* - * Proximity rule - */ - class ProximityInterestRule - : public InterestRule - , public ProximityInterest - { - friend class ProximityInterestHandler; - - public: - using Ptr = AZStd::intrusive_ptr; - - GM_CLASS_ALLOCATOR(ProximityInterestRule); - - void Set(const AZ::Aabb& bbox); - - private: - - // Intrusive ptr - template - friend struct AZStd::IntrusivePtrCountPolicy; - unsigned int m_refCount = 0; - AZ_FORCE_INLINE void add_ref() { ++m_refCount; } - AZ_FORCE_INLINE void release() { --m_refCount; if (!m_refCount) Destroy(); } - AZ_FORCE_INLINE bool IsDeleted() const { return m_refCount == 0; } - /////////////////////////////////////////////////////////////////////////// - - ProximityInterestRule(ProximityInterestHandler* handler, PeerId peerId, RuleNetworkId netId) - : InterestRule(peerId, netId) - , ProximityInterest(handler) - {} - - void Destroy(); - }; - /////////////////////////////////////////////////////////////////////////// - - class SpatialIndex - { - public: - typedef Internal::DynamicTreeNode Node; - - class NodeCollector - { - typedef AZStd::vector Type; - - public: - void Process(const Internal::DynamicTreeNode* node) - { - m_nodes.push_back(reinterpret_cast(node->m_data)); - } - - const Type& GetNodes() const - { - return m_nodes; - } - - private: - Type m_nodes; - }; - - SpatialIndex(); - ~SpatialIndex() = default; - - AZ_FORCE_INLINE void Remove(Node* node); - AZ_FORCE_INLINE void Update(Node* node); - AZ_FORCE_INLINE Node* Insert(const AZ::Aabb& get, ProximityInterestAttribute* attribute); - AZ_FORCE_INLINE void Query(const AZ::Aabb& get, NodeCollector& nodes); - - private: - AZStd::unique_ptr m_tree; - }; - - /* - * Proximity attribute - */ - class ProximityInterestAttribute - : public InterestAttribute - , public ProximityInterest - { - friend class ProximityInterestHandler; - template friend class InterestPtr; - - public: - using Ptr = AZStd::intrusive_ptr; - - GM_CLASS_ALLOCATOR(ProximityInterestAttribute); - - void Set(const AZ::Aabb& bbox); - - private: - - // Intrusive ptr - template - friend struct AZStd::IntrusivePtrCountPolicy; - unsigned int m_refCount = 0; - AZ_FORCE_INLINE void add_ref() { ++m_refCount; } - AZ_FORCE_INLINE void release() { Destroy(); } - AZ_FORCE_INLINE bool IsDeleted() const { return m_refCount == 0; } - /////////////////////////////////////////////////////////////////////////// - - ProximityInterestAttribute(ProximityInterestHandler* handler, ReplicaId repId) - : InterestAttribute(repId) - , ProximityInterest(handler) - , m_worldNode(nullptr) - {} - - void Destroy(); - - void SetNode(SpatialIndex::Node* node) { m_worldNode = node; } - SpatialIndex::Node* GetNode() const { return m_worldNode; } - SpatialIndex::Node* m_worldNode; ///< non-owning pointer - }; - /////////////////////////////////////////////////////////////////////////// - - class ProximityInterestChunk - : public ReplicaChunk - { - public: - GM_CLASS_ALLOCATOR(ProximityInterestChunk); - - // ReplicaChunk - typedef AZStd::intrusive_ptr Ptr; - bool IsReplicaMigratable() override { return false; } - bool IsBroadcast() override { return true; } - static const char* GetChunkName() { return "ProximityInterestChunk"; } - - ProximityInterestChunk() - : AddRuleRpc("AddRule") - , RemoveRuleRpc("RemoveRule") - , UpdateRuleRpc("UpdateRule") - , AddRuleForPeerRpc("AddRuleForPeerRpc") - , m_interestHandler(nullptr) - { - } - - void OnReplicaActivate(const ReplicaContext& rc) override; - void OnReplicaDeactivate(const ReplicaContext& rc) override; - - bool AddRuleFn(RuleNetworkId netId, AZ::Aabb bbox, const RpcContext& ctx); - bool RemoveRuleFn(RuleNetworkId netId, const RpcContext&); - bool UpdateRuleFn(RuleNetworkId netId, AZ::Aabb bbox, const RpcContext&); - bool AddRuleForPeerFn(RuleNetworkId netId, PeerId peerId, AZ::Aabb bbox, const RpcContext&); - - Rpc, RpcArg>::BindInterface AddRuleRpc; - Rpc>::BindInterface RemoveRuleRpc; - Rpc, RpcArg>::BindInterface UpdateRuleRpc; - - Rpc, RpcArg, RpcArg>::BindInterface AddRuleForPeerRpc; - - unordered_map m_rules; - ProximityInterestHandler* m_interestHandler; - }; - - /* - * Rules handler - */ - class ProximityInterestHandler - : public BaseRulesHandler - { - friend class ProximityInterestRule; - friend class ProximityInterestAttribute; - friend class ProximityInterestChunk; - - public: - - typedef unordered_set AttributeSet; - typedef unordered_set RuleSet; - - GM_CLASS_ALLOCATOR(ProximityInterestHandler); - - ProximityInterestHandler(); - ~ProximityInterestHandler(); - - /* - * Creates new proximity rule and binds it to the peer. - * Note: the lifetime of the created rule is tied to the lifetime of this handler. - */ - ProximityInterestRule::Ptr CreateRule(PeerId peerId); - - /* - * Creates new proximity attribute and binds it to the replica. - * Note: the lifetime of the created attribute is tied to the lifetime of this handler. - */ - ProximityInterestAttribute::Ptr CreateAttribute(ReplicaId replicaId); - - // Calculates rules and attributes matches - void Update() override; - - // Returns last recalculated results - const InterestMatchResult& GetLastResult() override; - - // Returns the manager it's bound to - InterestManager* GetManager() override { return m_im; } - - // Rules that this handler is aware of - const RuleSet& GetLocalRules() const { return m_localRules; } - - private: - - // BaseRulesHandler - void OnRulesHandlerRegistered(InterestManager* manager) override; - void OnRulesHandlerUnregistered(InterestManager* manager) override; - - void DestroyRule(ProximityInterestRule* rule); - void FreeRule(ProximityInterestRule* rule); - void UpdateRule(ProximityInterestRule* rule); - - void DestroyAttribute(ProximityInterestAttribute* attrib); - void FreeAttribute(ProximityInterestAttribute* attrib); - void UpdateAttribute(ProximityInterestAttribute* attrib); - - void OnNewRulesChunk(ProximityInterestChunk* chunk, ReplicaPeer* peer); - void OnDeleteRulesChunk(ProximityInterestChunk* chunk, ReplicaPeer* peer); - - RuleNetworkId GetNewRuleNetId(); - - ProximityInterestChunk* FindRulesChunkByPeerId(PeerId peerId); - - void DestroyAll(); - - InterestManager* m_im; - ReplicaManager* m_rm; - - AZ::u32 m_lastRuleNetId; - - unordered_map m_peerChunks; - - RuleSet m_localRules; - RuleSet m_removedRules; - RuleSet m_dirtyRules; - - AttributeSet m_attributes; - AttributeSet m_removedAttributes; - AttributeSet m_dirtyAttributes; - - ProximityInterestChunk* m_rulesReplica; - - // collection of all known attributes - AZStd::unique_ptr m_attributeWorld; - - InterestMatchResult m_resultCache; - - /////////////////////////////////////////////////////////////////////////////////////////////////// - // internal processing helpers - AZ_FORCE_INLINE RuleSet& GetAffectedRules(); - AZ_FORCE_INLINE void GetAttributesWithinRule(ProximityInterestRule* rule, SpatialIndex::NodeCollector& nodes); - AZ_FORCE_INLINE void ClearDirtyState(); - - AZ_FORCE_INLINE void CreateAndInsertIntoSpatialStructure(ProximityInterestAttribute* attribute); - AZ_FORCE_INLINE void RemoveFromSpatialStructure(ProximityInterestAttribute* attribute); - AZ_FORCE_INLINE void CreateAndInsertIntoSpatialStructure(ProximityInterestRule* rule); - - void UpdateInternal(InterestMatchResult& result); - void CheckChangesForRule(ProximityInterestRule* rule, InterestMatchResult& result); - void MarkAttributesDirtyInRule(ProximityInterestRule* rule); - - static bool HasSamePeers(const InterestPeerSet& one, const InterestPeerSet& another); - void ProduceChanges(const InterestMatchResult& before, const InterestMatchResult& after); - - InterestMatchResult m_lastResult; - /////////////////////////////////////////////////////////////////////////////////////////////////// - }; - /////////////////////////////////////////////////////////////////////////// -} - -#endif // GM_REPLICA_PROXIMITYINTERESTHANDLER_H diff --git a/Code/Framework/GridMate/GridMate/gridmate_files.cmake b/Code/Framework/GridMate/GridMate/gridmate_files.cmake index 7cc65ff69a..615ce53027 100644 --- a/Code/Framework/GridMate/GridMate/gridmate_files.cmake +++ b/Code/Framework/GridMate/GridMate/gridmate_files.cmake @@ -100,14 +100,10 @@ set(FILES Replica/Tasks/ReplicaPriorityPolicy.h Replica/Interest/BitmaskInterestHandler.cpp Replica/Interest/BitmaskInterestHandler.h - Replica/Interest/ProximityInterestHandler.cpp - Replica/Interest/ProximityInterestHandler.h Replica/Interest/InterestDefs.h Replica/Interest/InterestManager.cpp Replica/Interest/InterestManager.h Replica/Interest/InterestQueryResult.h - Replica/Interest/BvDynamicTree.cpp - Replica/Interest/BvDynamicTree.h Replica/Interest/RulesHandler.h Serialize/Buffer.cpp Serialize/Buffer.h diff --git a/Code/Framework/GridMate/Tests/Interest.cpp b/Code/Framework/GridMate/Tests/Interest.cpp deleted file mode 100644 index c449c92083..0000000000 --- a/Code/Framework/GridMate/Tests/Interest.cpp +++ /dev/null @@ -1,1823 +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 "Tests.h" -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace GridMate; - -// An easy switch to use an old brute force ProximityInterestHandler for performance comparison. -#if 0 -namespace GridMate -{ - /* - * Base interest - */ - class ProximityInterest - { - friend class ProximityInterestHandler; - - public: - const AZ::Aabb& Get() const { return m_bbox; } - - protected: - explicit ProximityInterest(ProximityInterestHandler* handler); - - ProximityInterestHandler* m_handler; - AZ::Aabb m_bbox; - }; - /////////////////////////////////////////////////////////////////////////// - - - /* - * Proximity rule - */ - class ProximityInterestRule - : public InterestRule - , public ProximityInterest - { - friend class ProximityInterestHandler; - - public: - using Ptr = AZStd::intrusive_ptr; - - GM_CLASS_ALLOCATOR(ProximityInterestRule); - - void Set(const AZ::Aabb& bbox); - - private: - - // Intrusive ptr - template - friend struct AZStd::IntrusivePtrCountPolicy; - unsigned int m_refCount = 0; - AZ_FORCE_INLINE void add_ref() { ++m_refCount; } - AZ_FORCE_INLINE void release() { --m_refCount; if (!m_refCount) Destroy(); } - AZ_FORCE_INLINE bool IsDeleted() const { return m_refCount == 0; } - /////////////////////////////////////////////////////////////////////////// - - ProximityInterestRule(ProximityInterestHandler* handler, PeerId peerId, RuleNetworkId netId) - : InterestRule(peerId, netId) - , ProximityInterest(handler) - {} - - void Destroy(); - }; - /////////////////////////////////////////////////////////////////////////// - - - /* - * Proximity attribute - */ - class ProximityInterestAttribute - : public InterestAttribute - , public ProximityInterest - { - friend class ProximityInterestHandler; - template friend class InterestPtr; - - public: - using Ptr = AZStd::intrusive_ptr; - - GM_CLASS_ALLOCATOR(ProximityInterestAttribute); - - void Set(const AZ::Aabb& bbox); - - private: - - // Intrusive ptr - template - friend struct AZStd::IntrusivePtrCountPolicy; - unsigned int m_refCount = 0; - AZ_FORCE_INLINE void add_ref() { ++m_refCount; } - AZ_FORCE_INLINE void release() { Destroy(); } - AZ_FORCE_INLINE bool IsDeleted() const { return m_refCount == 0; } - /////////////////////////////////////////////////////////////////////////// - - ProximityInterestAttribute(ProximityInterestHandler* handler, ReplicaId repId) - : InterestAttribute(repId) - , ProximityInterest(handler) - {} - - void Destroy(); - }; - /////////////////////////////////////////////////////////////////////////// - - - /* - * Rules handler - */ - class ProximityInterestHandler - : public BaseRulesHandler - { - friend class ProximityInterestRule; - friend class ProximityInterestAttribute; - friend class ProximityInterestChunk; - - public: - - typedef unordered_set AttributeSet; - typedef unordered_set RuleSet; - - GM_CLASS_ALLOCATOR(ProximityInterestHandler); - - ProximityInterestHandler(); - - // Creates new proximity rule and binds it to the peer - ProximityInterestRule::Ptr CreateRule(PeerId peerId); - - // Creates new proximity attribute and binds it to the replica - ProximityInterestAttribute::Ptr CreateAttribute(ReplicaId replicaId); - - // Calculates rules and attributes matches - void Update() override; - - // Returns last recalculated results - const InterestMatchResult& GetLastResult() override; - - // Returns manager its bound with - InterestManager* GetManager() override { return m_im; } - - const RuleSet& GetLocalRules() { return m_localRules; } - - private: - void UpdateInternal(InterestMatchResult& result); - - // BaseRulesHandler - void OnRulesHandlerRegistered(InterestManager* manager) override; - void OnRulesHandlerUnregistered(InterestManager* manager) override; - - void DestroyRule(ProximityInterestRule* rule); - void FreeRule(ProximityInterestRule* rule); - void UpdateRule(ProximityInterestRule* rule); - - void DestroyAttribute(ProximityInterestAttribute* attrib); - void FreeAttribute(ProximityInterestAttribute* attrib); - void UpdateAttribute(ProximityInterestAttribute* attrib); - - - void OnNewRulesChunk(ProximityInterestChunk* chunk, ReplicaPeer* peer); - void OnDeleteRulesChunk(ProximityInterestChunk* chunk, ReplicaPeer* peer); - - RuleNetworkId GetNewRuleNetId(); - - ProximityInterestChunk* FindRulesChunkByPeerId(PeerId peerId); - - InterestManager* m_im; - ReplicaManager* m_rm; - - AZ::u32 m_lastRuleNetId; - - unordered_map m_peerChunks; - RuleSet m_localRules; - - AttributeSet m_attributes; - RuleSet m_rules; - - ProximityInterestChunk* m_rulesReplica; - - InterestMatchResult m_resultCache; - }; - /////////////////////////////////////////////////////////////////////////// - - class ProximityInterestChunk - : public ReplicaChunk - { - public: - GM_CLASS_ALLOCATOR(ProximityInterestChunk); - - // ReplicaChunk - typedef AZStd::intrusive_ptr Ptr; - bool IsReplicaMigratable() override { return false; } - static const char* GetChunkName() { return "ProximityInterestChunk"; } - bool IsBroadcast() { return true; } - /////////////////////////////////////////////////////////////////////////// - - - ProximityInterestChunk() - : m_interestHandler(nullptr) - , AddRuleRpc("AddRule") - , RemoveRuleRpc("RemoveRule") - , UpdateRuleRpc("UpdateRule") - , AddRuleForPeerRpc("AddRuleForPeerRpc") - { - - } - - void OnReplicaActivate(const ReplicaContext& rc) override - { - m_interestHandler = static_cast(rc.m_rm->GetUserContext(AZ_CRC("ProximityInterestHandler", 0x3a90b3e4))); - AZ_Assert(m_interestHandler, "No proximity interest handler in the user context"); - - if (m_interestHandler) - { - m_interestHandler->OnNewRulesChunk(this, rc.m_peer); - } - } - - void OnReplicaDeactivate(const ReplicaContext& rc) override - { - if (rc.m_peer && m_interestHandler) - { - m_interestHandler->OnDeleteRulesChunk(this, rc.m_peer); - } - } - - bool AddRuleFn(RuleNetworkId netId, AZ::Aabb bbox, const RpcContext& ctx) - { - if (IsProxy()) - { - auto rulePtr = m_interestHandler->CreateRule(ctx.m_sourcePeer); - rulePtr->Set(bbox); - m_rules.insert(AZStd::make_pair(netId, rulePtr)); - } - - return true; - } - - bool RemoveRuleFn(RuleNetworkId netId, const RpcContext&) - { - if (IsProxy()) - { - m_rules.erase(netId); - } - - return true; - } - - bool UpdateRuleFn(RuleNetworkId netId, AZ::Aabb bbox, const RpcContext&) - { - if (IsProxy()) - { - auto it = m_rules.find(netId); - if (it != m_rules.end()) - { - it->second->Set(bbox); - } - } - - return true; - } - - bool AddRuleForPeerFn(RuleNetworkId netId, PeerId peerId, AZ::Aabb bbox, const RpcContext&) - { - ProximityInterestChunk* peerChunk = m_interestHandler->FindRulesChunkByPeerId(peerId); - if (peerChunk) - { - auto it = peerChunk->m_rules.find(netId); - if (it == peerChunk->m_rules.end()) - { - auto rulePtr = m_interestHandler->CreateRule(peerId); - peerChunk->m_rules.insert(AZStd::make_pair(netId, rulePtr)); - rulePtr->Set(bbox); - } - } - return false; - } - - Rpc, RpcArg>::BindInterface AddRuleRpc; - Rpc>::BindInterface RemoveRuleRpc; - Rpc, RpcArg>::BindInterface UpdateRuleRpc; - - Rpc, RpcArg, RpcArg>::BindInterface AddRuleForPeerRpc; - - ProximityInterestHandler* m_interestHandler; - unordered_map m_rules; - }; - /////////////////////////////////////////////////////////////////////////// - - - /* - * ProximityInterest - */ - ProximityInterest::ProximityInterest(ProximityInterestHandler* handler) - : m_bbox(AZ::Aabb::CreateNull()) - , m_handler(handler) - { - AZ_Assert(m_handler, "Invalid interest handler"); - } - /////////////////////////////////////////////////////////////////////////// - - - /* - * ProximityInterestRule - */ - void ProximityInterestRule::Set(const AZ::Aabb& bbox) - { - m_bbox = bbox; - m_handler->UpdateRule(this); - } - - void ProximityInterestRule::Destroy() - { - m_handler->DestroyRule(this); - } - /////////////////////////////////////////////////////////////////////////// - - - /* - * ProximityInterestAttribute - */ - void ProximityInterestAttribute::Set(const AZ::Aabb& bbox) - { - m_bbox = bbox; - m_handler->UpdateAttribute(this); - } - - void ProximityInterestAttribute::Destroy() - { - m_handler->DestroyAttribute(this); - } - /////////////////////////////////////////////////////////////////////////// - - - /* - * ProximityInterestHandler - */ - ProximityInterestHandler::ProximityInterestHandler() - : m_im(nullptr) - , m_rm(nullptr) - , m_lastRuleNetId(0) - , m_rulesReplica(nullptr) - { - if (!ReplicaChunkDescriptorTable::Get().FindReplicaChunkDescriptor(ReplicaChunkClassId(ProximityInterestChunk::GetChunkName()))) - { - ReplicaChunkDescriptorTable::Get().RegisterChunkType(); - } - } - - ProximityInterestRule::Ptr ProximityInterestHandler::CreateRule(PeerId peerId) - { - ProximityInterestRule* rulePtr = aznew ProximityInterestRule(this, peerId, GetNewRuleNetId()); - if (peerId == m_rm->GetLocalPeerId()) - { - m_rulesReplica->AddRuleRpc(rulePtr->GetNetworkId(), rulePtr->Get()); - m_localRules.insert(rulePtr); - } - - return rulePtr; - } - - void ProximityInterestHandler::FreeRule(ProximityInterestRule* rule) - { - //TODO: should be pool-allocated - delete rule; - } - - void ProximityInterestHandler::DestroyRule(ProximityInterestRule* rule) - { - if (m_rm && rule->GetPeerId() == m_rm->GetLocalPeerId()) - { - m_rulesReplica->RemoveRuleRpc(rule->GetNetworkId()); - } - - rule->m_bbox = AZ::Aabb::CreateNull(); - m_rules.insert(rule); - m_localRules.erase(rule); - } - - void ProximityInterestHandler::UpdateRule(ProximityInterestRule* rule) - { - if (rule->GetPeerId() == m_rm->GetLocalPeerId()) - { - m_rulesReplica->UpdateRuleRpc(rule->GetNetworkId(), rule->Get()); - } - - m_rules.insert(rule); - } - - ProximityInterestAttribute::Ptr ProximityInterestHandler::CreateAttribute(ReplicaId replicaId) - { - return aznew ProximityInterestAttribute(this, replicaId); - } - - void ProximityInterestHandler::FreeAttribute(ProximityInterestAttribute* attrib) - { - //TODO: should be pool-allocated - delete attrib; - } - - void ProximityInterestHandler::DestroyAttribute(ProximityInterestAttribute* attrib) - { - attrib->m_bbox = AZ::Aabb::CreateNull(); - m_attributes.insert(attrib); - } - - void ProximityInterestHandler::UpdateAttribute(ProximityInterestAttribute* attrib) - { - m_attributes.insert(attrib); - } - - void ProximityInterestHandler::OnNewRulesChunk(ProximityInterestChunk* chunk, ReplicaPeer* peer) - { - if (chunk != m_rulesReplica) // non-local - { - m_peerChunks.insert(AZStd::make_pair(peer->GetId(), chunk)); - - for (auto& rule : m_localRules) - { - chunk->AddRuleForPeerRpc(rule->GetNetworkId(), rule->GetPeerId(), rule->Get()); - } - } - } - - void ProximityInterestHandler::OnDeleteRulesChunk(ProximityInterestChunk* chunk, ReplicaPeer* peer) - { - (void)chunk; - m_peerChunks.erase(peer->GetId()); - } - - RuleNetworkId ProximityInterestHandler::GetNewRuleNetId() - { - ++m_lastRuleNetId; - return m_rulesReplica->GetReplicaId() | (static_cast(m_lastRuleNetId) << 32); - } - - ProximityInterestChunk* ProximityInterestHandler::FindRulesChunkByPeerId(PeerId peerId) - { - auto it = m_peerChunks.find(peerId); - if (it == m_peerChunks.end()) - { - return nullptr; - } - else - { - return it->second; - } - } - - const InterestMatchResult& ProximityInterestHandler::GetLastResult() - { - return m_resultCache; - } - - void ProximityInterestHandler::UpdateInternal(InterestMatchResult& result) - { - ////////////////////////////////////////////// - // just recalculating the whole state for now - for (auto attrIt = m_attributes.begin(); attrIt != m_attributes.end(); ) - { - ProximityInterestAttribute* attr = *attrIt; - - auto resultIt = result.insert(attr->GetReplicaId()); - for (auto ruleIt = m_rules.begin(); ruleIt != m_rules.end(); ++ruleIt) - { - ProximityInterestRule* rule = *ruleIt; - if (rule->m_bbox.Overlaps(attr->m_bbox)) - { - resultIt.first->second.insert(rule->GetPeerId()); - } - } - - if ((*attrIt)->IsDeleted()) - { - attrIt = m_attributes.erase(attrIt); - delete attr; - } - else - { - ++attrIt; - } - } - - for (auto ruleIt = m_rules.begin(); ruleIt != m_rules.end(); ) - { - ProximityInterestRule* rule = *ruleIt; - - if (rule->IsDeleted()) - { - ruleIt = m_rules.erase(ruleIt); - delete rule; - } - else - { - ++ruleIt; - } - } - ////////////////////////////////////////////// - } - - void ProximityInterestHandler::Update() - { - m_resultCache.clear(); - - UpdateInternal(m_resultCache); - } - - void ProximityInterestHandler::OnRulesHandlerRegistered(InterestManager* manager) - { - AZ_Assert(m_im == nullptr, "Handler is already registered with manager %p (%p)\n", m_im, manager); - AZ_Assert(m_rulesReplica == nullptr, "Rules replica is already created\n"); - AZ_TracePrintf("GridMate", "Proximity interest handler is registered\n"); - m_im = manager; - m_rm = m_im->GetReplicaManager(); - m_rm->RegisterUserContext(AZ_CRC("ProximityInterestHandler", 0x3a90b3e4), this); - - auto replica = Replica::CreateReplica("ProximityInterestHandlerRules"); - m_rulesReplica = CreateAndAttachReplicaChunk(replica); - m_rm->AddPrimary(replica); - } - - void ProximityInterestHandler::OnRulesHandlerUnregistered(InterestManager* manager) - { - (void)manager; - AZ_Assert(m_im == manager, "Handler was not registered with manager %p (%p)\n", manager, m_im); - AZ_TracePrintf("GridMate", "Proximity interest handler is unregistered\n"); - m_rulesReplica = nullptr; - m_im = nullptr; - m_rm->UnregisterUserContext(AZ_CRC("ProximityInterestHandler", 0x3a90b3e4)); - m_rm = nullptr; - - for (auto& chunk : m_peerChunks) - { - chunk.second->m_interestHandler = nullptr; - } - m_peerChunks.clear(); - m_localRules.clear(); - - for (ProximityInterestRule* rule : m_rules) - { - delete rule; - } - - for (ProximityInterestAttribute* attr : m_attributes) - { - delete attr; - } - - m_attributes.clear(); - m_rules.clear(); - - m_resultCache.clear(); - } - /////////////////////////////////////////////////////////////////////////// -} -#else -// Optimized spatial handler. -#include "GridMate/Replica/Interest/ProximityInterestHandler.h" -#endif - -namespace UnitTest { - -/* - * Helper class to capture performance of various Interest Managers - */ -class PerfForInterestManager -{ -public: - void Reset(); - - void PreUpdate(); - void PostUpdate(); - - AZ::u32 GetTotalFrames() const; - float GetAverageFrame() const; - float GetWorstFrame() const; - float GetBestFrame() const; - -private: - AZ::Debug::Timer m_timer; - AZ::u32 m_frameCount = 0; - float m_totalUpdateTime = 0.f; - float m_fastestFrame = 100.f; - float m_slowestFrame = 0.f; -}; - -PerfForInterestManager g_PerfIM = PerfForInterestManager(); -PerfForInterestManager g_PerfUpdatingAttributes = PerfForInterestManager(); - -/* -* Utility function to tick the replica manager -*/ -static void UpdateReplicas(ReplicaManager* replicaManager, InterestManager* interestManager) -{ - if (interestManager) - { - // Measuring time it takes to execute an update. - g_PerfIM.PreUpdate(); - interestManager->Update(); - g_PerfIM.PostUpdate(); - } - - if (replicaManager) - { - replicaManager->Unmarshal(); - replicaManager->UpdateFromReplicas(); - replicaManager->UpdateReplicas(); - replicaManager->Marshal(); - } -} - -class Integ_InterestTest - : public GridMateMPTestFixture -{ - /////////////////////////////////////////////////////////////////// - class InterestTestChunk - : public ReplicaChunk - { - public: - GM_CLASS_ALLOCATOR(InterestTestChunk); - - InterestTestChunk() - : m_data("Data", 0) - , m_bitmaskAttributeData("BitmaskAttributeData") - , m_attribute(nullptr) - { - } - - /////////////////////////////////////////////////////////////////// - typedef AZStd::intrusive_ptr Ptr; - static const char* GetChunkName() { return "InterestTestChunk"; } - bool IsReplicaMigratable() override { return false; } - bool IsBroadcast() override - { - return false; - } - /////////////////////////////////////////////////////////////////// - - void OnReplicaActivate(const ReplicaContext& rc) override - { - AZ_Printf("GridMate", "InterestTestChunk::OnReplicaActivate repId=%08X(%s) fromPeerId=%08X localPeerId=%08X\n", - GetReplicaId(), - IsPrimary() ? "primary" : "proxy", - rc.m_peer ? rc.m_peer->GetId() : 0, - rc.m_rm->GetLocalPeerId()); - - BitmaskInterestHandler* ih = static_cast(rc.m_rm->GetUserContext(AZ_CRC("BitmaskInterestHandler", 0x5bf5d75b))); - if (ih) - { - m_attribute = ih->CreateAttribute(GetReplicaId()); - m_attribute->Set(m_bitmaskAttributeData.Get()); - } - } - - void OnReplicaDeactivate(const ReplicaContext& rc) override - { - AZ_Printf("GridMate", "InterestTestChunk::OnReplicaDeactivate repId=%08X(%s) fromPeerId=%08X localPeerId=%08X\n", - GetReplicaId(), - IsPrimary() ? "primary" : "proxy", - rc.m_peer ? rc.m_peer->GetId() : 0, - rc.m_rm->GetLocalPeerId()); - - m_attribute = nullptr; - } - - void BitmaskHandler(const InterestBitmask& bitmask, const TimeContext&) - { - if (m_attribute) - { - m_attribute->Set(bitmask); - } - } - - DataSet m_data; - DataSet::BindInterface m_bitmaskAttributeData; - BitmaskInterestAttribute::Ptr m_attribute; - }; - /////////////////////////////////////////////////////////////////// - - class TestPeerInfo - : public SessionEventBus::Handler - { - public: - TestPeerInfo() - : m_gridMate(nullptr) - , m_lanSearch(nullptr) - , m_session(nullptr) - , m_im(nullptr) - , m_bitmaskHandler(nullptr) - , m_num(0) - { - GridMate::ReplicaChunkDescriptorTable::Get().RegisterChunkType(); - GridMate::ReplicaChunkDescriptorTable::Get().RegisterChunkType(); - } - - void CreateTestReplica() - { - m_im = aznew InterestManager(); - InterestManagerDesc desc; - desc.m_rm = m_session->GetReplicaMgr(); - - m_im->Init(desc); - - m_bitmaskHandler = aznew BitmaskInterestHandler(); - m_im->RegisterHandler(m_bitmaskHandler); - - m_rule = m_bitmaskHandler->CreateRule(m_session->GetReplicaMgr()->GetLocalPeerId()); - m_rule->Set(1 << m_num); - - auto r = Replica::CreateReplica("InterestTestReplica"); - m_replica = CreateAndAttachReplicaChunk(r); - - // Initializing attribute - // Shifing all by one - peer0 will recv from peer1, peer2 will recv from peer2, peer2 will recv from peer0 - unsigned i = (m_num + 2) % Integ_InterestTest::k_numMachines; - m_replica->m_data.Set(m_num); - m_replica->m_bitmaskAttributeData.Set(1 << i); - - m_session->GetReplicaMgr()->AddPrimary(r); - } - - void UpdateAttribute() - { - // Shifing all by one - peer0 will recv from peer2, peer1 will recv from peer0, peer2 will recv from peer1 - unsigned i = (m_num + 1) % Integ_InterestTest::k_numMachines; - m_replica->m_bitmaskAttributeData.Set(1 << i); - m_replica->m_attribute->Set(1 << i); - } - - void DeleteAttribute() - { - m_replica->m_attribute = nullptr; - } - - void UpdateRule() - { - m_rule->Set(0xffff); - } - - void DeleteRule() - { - m_rule = nullptr; - } - - void CreateRule() - { - m_rule = m_bitmaskHandler->CreateRule(m_session->GetReplicaMgr()->GetLocalPeerId()); - m_rule->Set(0xffff); - } - - void OnSessionCreated(GridSession* session) override - { - m_session = session; - if (m_session->IsHost()) - { - CreateTestReplica(); - } - } - - void OnSessionJoined(GridSession* session) override - { - m_session = session; - CreateTestReplica(); - } - - void OnSessionDelete(GridSession* session) override - { - if (session == m_session) - { - m_rule = nullptr; - m_session = nullptr; - m_im->UnregisterHandler(m_bitmaskHandler); - delete m_bitmaskHandler; - delete m_im; - m_im = nullptr; - m_bitmaskHandler = nullptr; - } - } - - void OnSessionError(GridSession* session, const string& errorMsg) override - { - (void)session; - (void)errorMsg; - AZ_TracePrintf("GridMate", "Session error: %s\n", errorMsg.c_str()); - } - - IGridMate* m_gridMate; - GridSearch* m_lanSearch; - GridSession* m_session; - InterestManager* m_im; - BitmaskInterestHandler* m_bitmaskHandler; - - BitmaskInterestRule::Ptr m_rule; - unsigned m_num; - InterestTestChunk::Ptr m_replica; - }; - -public: - Integ_InterestTest() - { - ReplicaChunkDescriptorTable::Get().RegisterChunkType(); - - ////////////////////////////////////////////////////////////////////////// - // Create all grid mates - m_peers[0].m_gridMate = m_gridMate; - m_peers[0].SessionEventBus::Handler::BusConnect(m_peers[0].m_gridMate); - m_peers[0].m_num = 0; - for (int i = 1; i < k_numMachines; ++i) - { - GridMateDesc desc; - m_peers[i].m_gridMate = GridMateCreate(desc); - AZ_TEST_ASSERT(m_peers[i].m_gridMate); - - m_peers[i].m_num = i; - m_peers[i].SessionEventBus::Handler::BusConnect(m_peers[i].m_gridMate); - } - ////////////////////////////////////////////////////////////////////////// - - for (int i = 0; i < k_numMachines; ++i) - { - // start the multiplayer service (session mgr, extra allocator, etc.) - StartGridMateService(m_peers[i].m_gridMate, SessionServiceDesc()); - AZ_TEST_ASSERT(LANSessionServiceBus::FindFirstHandler(m_peers[i].m_gridMate) != nullptr); - } - } - virtual ~Integ_InterestTest() - { - StopGridMateService(m_peers[0].m_gridMate); - - for (int i = 1; i < k_numMachines; ++i) - { - if (m_peers[i].m_gridMate) - { - m_peers[i].SessionEventBus::Handler::BusDisconnect(); - GridMateDestroy(m_peers[i].m_gridMate); - } - } - - // this will stop the first IGridMate which owns the memory allocators. - m_peers[0].SessionEventBus::Handler::BusDisconnect(); - } - - void run() - { - TestCarrierDesc carrierDesc; - carrierDesc.m_enableDisconnectDetection = false;// true; - carrierDesc.m_threadUpdateTimeMS = 10; - carrierDesc.m_familyType = Driver::BSD_AF_INET; - - - LANSessionParams sp; - sp.m_topology = ST_PEER_TO_PEER; - sp.m_numPublicSlots = 64; - sp.m_port = k_hostPort; - EBUS_EVENT_ID_RESULT(m_peers[k_host].m_session, m_peers[k_host].m_gridMate, LANSessionServiceBus, HostSession, sp, carrierDesc); - m_peers[k_host].m_session->GetReplicaMgr()->SetAutoBroadcast(false); - - int listenPort = k_hostPort; - for (int i = 0; i < k_numMachines; ++i) - { - if (i == k_host) - { - continue; - } - - LANSearchParams searchParams; - searchParams.m_serverPort = k_hostPort; - searchParams.m_listenPort = listenPort == k_hostPort ? 0 : ++listenPort; // first client will use ephemeral port, the rest specify return ports - searchParams.m_familyType = Driver::BSD_AF_INET; - EBUS_EVENT_ID_RESULT(m_peers[i].m_lanSearch, m_peers[i].m_gridMate, LANSessionServiceBus, StartGridSearch, searchParams); - } - - - static const int maxNumUpdates = 300; - int numUpdates = 0; - TimeStamp time = AZStd::chrono::system_clock::now(); - - while (numUpdates <= maxNumUpdates) - { - if (numUpdates == 100) - { - // Checking everybody received only one replica: - // peer0 -> rep1, peer1 -> rep2, peer2 -> rep0 - for (int i = 0; i < k_numMachines; ++i) - { - ReplicaId repId = m_peers[(i + 1) % k_numMachines].m_replica->GetReplicaId(); - auto repRecv = m_peers[i].m_session->GetReplicaMgr()->FindReplica(repId); - AZ_TEST_ASSERT(repRecv != nullptr); - - repId = m_peers[(i + 2) % k_numMachines].m_replica->GetReplicaId(); - auto repNotRecv = m_peers[i].m_session->GetReplicaMgr()->FindReplica(repId); - AZ_TEST_ASSERT(repNotRecv == nullptr); - - // rotating mask left - m_peers[i].UpdateAttribute(); - } - } - - if (numUpdates == 150) - { - // Checking everybody received only one replica: - // peer0 -> rep2, peer1 -> rep0, peer2 -> rep1 - for (int i = 0; i < k_numMachines; ++i) - { - ReplicaId repId = m_peers[(i + 2) % k_numMachines].m_replica->GetReplicaId(); - auto repRecv = m_peers[i].m_session->GetReplicaMgr()->FindReplica(repId); - AZ_TEST_ASSERT(repRecv != nullptr); - - repId = m_peers[(i + 1) % k_numMachines].m_replica->GetReplicaId(); - auto repNotRecv = m_peers[i].m_session->GetReplicaMgr()->FindReplica(repId); - AZ_TEST_ASSERT(repNotRecv == nullptr); - - // setting rules to accept all replicas - m_peers[i].UpdateRule(); - } - } - - if (numUpdates == 200) - { - // Checking everybody received all replicas - for (int i = 0; i < k_numMachines; ++i) - { - for (int j = 0; j < k_numMachines; ++j) - { - ReplicaId repId = m_peers[j].m_replica->GetReplicaId(); - auto rep = m_peers[i].m_session->GetReplicaMgr()->FindReplica(repId); - AZ_TEST_ASSERT(rep); - } - - // Deleting all attributes - m_peers[i].DeleteAttribute(); - } - } - - if (numUpdates == 250) - { - // Checking everybody lost all replicas (except primary) - for (int i = 0; i < k_numMachines; ++i) - { - for (int j = 0; j < k_numMachines; ++j) - { - if (i == j) - { - continue; - } - - ReplicaId repId = m_peers[j].m_replica->GetReplicaId(); - auto rep = m_peers[i].m_session->GetReplicaMgr()->FindReplica(repId); - AZ_TEST_ASSERT(rep == nullptr); - } - - // deleting all rules - m_peers[i].DeleteRule(); - } - } - - ////////////////////////////////////////////////////////////////////////// - for (int i = 0; i < k_numMachines; ++i) - { - if (m_peers[i].m_gridMate) - { - m_peers[i].m_gridMate->Update(); - if (m_peers[i].m_session) - { - UpdateReplicas(m_peers[i].m_session->GetReplicaMgr(), m_peers[i].m_im); - } - } - } - Update(); - ////////////////////////////////////////////////////////////////////////// - - for (int i = 0; i < k_numMachines; ++i) - { - if (m_peers[i].m_lanSearch && m_peers[i].m_lanSearch->IsDone()) - { - AZ_TEST_ASSERT(m_peers[i].m_lanSearch->GetNumResults() == 1); - JoinParams jp; - EBUS_EVENT_ID_RESULT(m_peers[i].m_session, m_peers[i].m_gridMate, LANSessionServiceBus, JoinSessionBySearchInfo, static_cast(*m_peers[i].m_lanSearch->GetResult(0)), jp, carrierDesc); - m_peers[i].m_session->GetReplicaMgr()->SetAutoBroadcast(false); - - m_peers[i].m_lanSearch->Release(); - m_peers[i].m_lanSearch = nullptr; - } - } - - ////////////////////////////////////////////////////////////////////////// - // Debug Info - TimeStamp now = AZStd::chrono::system_clock::now(); - if (AZStd::chrono::milliseconds(now - time).count() > 1000) - { - time = now; - for (int i = 0; i < k_numMachines; ++i) - { - if (m_peers[i].m_session == nullptr) - { - continue; - } - - if (m_peers[i].m_session->IsHost()) - { - AZ_Printf("GridMate", "------ Host %d ------\n", i); - } - else - { - AZ_Printf("GridMate", "------ Client %d ------\n", i); - } - - AZ_Printf("GridMate", "Session %s Members: %d Host: %s Clock: %d\n", m_peers[i].m_session->GetId().c_str(), m_peers[i].m_session->GetNumberOfMembers(), m_peers[i].m_session->IsHost() ? "yes" : "no", m_peers[i].m_session->GetTime()); - for (unsigned int iMember = 0; iMember < m_peers[i].m_session->GetNumberOfMembers(); ++iMember) - { - GridMember* member = m_peers[i].m_session->GetMemberByIndex(iMember); - AZ_Printf("GridMate", " Member: %s(%s) Host: %s Local: %s\n", member->GetName().c_str(), member->GetId().ToString().c_str(), member->IsHost() ? "yes" : "no", member->IsLocal() ? "yes" : "no"); - } - AZ_Printf("GridMate", "\n"); - } - } - ////////////////////////////////////////////////////////////////////////// - - AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds(30)); - numUpdates++; - } - } - - static const int k_numMachines = 3; - static const int k_host = 0; - static const int k_hostPort = 5450; - - TestPeerInfo m_peers[k_numMachines]; -}; - -/* - * Testing worse case performance of thousands of replicas and a few peers where all replicas/attributes change every frame - * and peers/rules change every frame as well. - */ -class LargeWorldTest - : public GridMateMPTestFixture -{ - /////////////////////////////////////////////////////////////////// - class LargeWorldTestChunk - : public ReplicaChunk - { - public: - GM_CLASS_ALLOCATOR(LargeWorldTestChunk); - - LargeWorldTestChunk() - : m_data("Data", 0) - , m_proximityAttributeData("LargeWorldAttributeData") - , m_attribute(nullptr) - { - } - - /////////////////////////////////////////////////////////////////// - typedef AZStd::intrusive_ptr Ptr; - static const char* GetChunkName() { return "LargeWorldTestChunk"; } - bool IsReplicaMigratable() override { return false; } - bool IsBroadcast() override - { - return false; - } - /////////////////////////////////////////////////////////////////// - - void OnReplicaActivate(const ReplicaContext& rc) override - { - /*if (!IsPrimary())*/ - /*{ - AZ_Printf("GridMate", "LargeWorldTestChunk::OnReplicaActivate repId=%08X(%s) fromPeerId=%08X localPeerId=%08X\n", - GetReplicaId(), - IsPrimary() ? "primary" : "proxy", - rc.m_peer ? rc.m_peer->GetId() : 0, - rc.m_rm->GetLocalPeerId()); - }*/ - - if (ProximityInterestHandler* ih = static_cast(rc.m_rm->GetUserContext(AZ_CRC("ProximityInterestHandler", 0x3a90b3e4)))) - { - m_attribute = ih->CreateAttribute(GetReplicaId()); - m_attribute->Set(m_proximityAttributeData.Get()); - } - } - - void OnReplicaDeactivate(const ReplicaContext& /*rc*/) override - { - m_attribute = nullptr; - } - - void ProximityHandler(const AZ::Aabb& bounds, const TimeContext&) - { - if (m_attribute) - { - m_attribute->Set(bounds); - } - } - - DataSet m_data; - DataSet::BindInterface m_proximityAttributeData; - ProximityInterestAttribute::Ptr m_attribute; - }; - /////////////////////////////////////////////////////////////////// - - struct LargeWorldParams - { - AZ::u32 index = 0; - - const float commonSize = 50; - const AZ::Aabb box = AZ::Aabb::CreateFromMinMax( - AZ::Vector3::CreateZero(), - AZ::Vector3::CreateOne() * commonSize); - const float commonStep = commonSize + 1; - }; - - static LargeWorldParams& GetWorldParams() - { - static LargeWorldParams worldParams; - return worldParams; - } - - /* - * Create a chain of boxes in spaces along X axis - */ - static AZ::Aabb CreateNextRuleSpace() - { - auto offset = GetWorldParams().commonStep * aznumeric_cast(GetWorldParams().index); - - float min[] = { offset, 0, 0 }; - float max[] = { - GetWorldParams().commonSize + offset, - GetWorldParams().commonSize, - GetWorldParams().commonSize }; - - auto bounds = AZ::Aabb::CreateFromMinMax( - AZ::Vector3::CreateFromFloat3(min), - AZ::Vector3::CreateFromFloat3(max)); - - GetWorldParams().index++; - return bounds; - } - - class LargeWorldTestPeerInfo - : public SessionEventBus::Handler - { - public: - LargeWorldTestPeerInfo() - : m_gridMate(nullptr) - , m_lanSearch(nullptr) - , m_session(nullptr) - , m_im(nullptr) - , m_proximityHandler(nullptr) - , m_num(0) - { - GridMate::ReplicaChunkDescriptorTable::Get().RegisterChunkType(); - GridMate::ReplicaChunkDescriptorTable::Get().RegisterChunkType(); - } - - ~LargeWorldTestPeerInfo() - { - SessionEventBus::Handler::BusDisconnect(); - } - - void CreateHostRuleHandler() - { - m_im = aznew InterestManager(); - InterestManagerDesc desc; - desc.m_rm = m_session->GetReplicaMgr(); - - m_im->Init(desc); - - m_proximityHandler = aznew ProximityInterestHandler(); - m_im->RegisterHandler(m_proximityHandler); - - m_rule = m_proximityHandler->CreateRule(m_session->GetReplicaMgr()->GetLocalPeerId()); - m_rule->Set(AZ::Aabb::CreateNull()); // host rule doesn't matter in this test - } - - void CreateRuleHandler() - { - m_im = aznew InterestManager(); - InterestManagerDesc desc; - desc.m_rm = m_session->GetReplicaMgr(); - - m_im->Init(desc); - - m_proximityHandler = aznew ProximityInterestHandler(); - m_im->RegisterHandler(m_proximityHandler); - - m_rule = m_proximityHandler->CreateRule(m_session->GetReplicaMgr()->GetLocalPeerId()); - m_rule->Set(CreateNextRuleSpace()); - } - - void CreateTestReplica(const AZ::Aabb& bounds) - { - auto r = Replica::CreateReplica("LargeWorldTestReplica"); - auto replica = CreateAndAttachReplicaChunk(r); - - // Initializing attribute - replica->m_data.Set(m_num); - replica->m_proximityAttributeData.Set(bounds); - - m_replicas.push_back(replica); - - m_session->GetReplicaMgr()->AddPrimary(r); - } - - void PopulateWorld() - { - AZ_Printf("GridMate", "LargeWorldTestChunk::PopulateWorld() starting...\n"); - - const float worldSizeInBoxes = 50; - const auto oneBox = AZ::Vector3::CreateOne(); - const auto thickness = 1; - for (float dx = 0; dx < worldSizeInBoxes; ++dx) - { - for (float dy = 0; dy < thickness; ++dy) - { - for (float dz = 0; dz < thickness; ++dz) - { - auto aabb = AZ::Aabb::CreateFromMinMax( - AZ::Vector3(50 * dx + 5, dy, dz), - AZ::Vector3(50 * dx + 5, dy, dz) + oneBox); - - CreateTestReplica(aabb); - } - } - } - - AZ_Printf("GridMate", "LargeWorldTestChunk::PopulateWorld() ... DONE\n"); - } - - void UpdateAttribute(LargeWorldTestChunk::Ptr replica) - { - if (replica && replica->m_attribute) - { - auto sameValue = replica->m_attribute->Get(); - - replica->m_proximityAttributeData.Set(sameValue); - replica->m_attribute->Set(sameValue); - } - } - - void UpdateRule() - { - // just make it dirty for now - if (m_rule) - { - auto sameValue = m_rule->Get(); - m_rule->Set(sameValue); - } - } - - void DeleteRule() - { - m_rule = nullptr; - } - - void OnSessionCreated(GridSession* session) override - { - m_session = session; - if (m_session->IsHost()) - { - CreateHostRuleHandler(); - PopulateWorld(); - } - } - - void OnSessionJoined(GridSession* session) override - { - m_session = session; - CreateRuleHandler(); - } - - void OnSessionDelete(GridSession* session) override - { - if (session == m_session) - { - m_rule = nullptr; - m_session = nullptr; - m_im->UnregisterHandler(m_proximityHandler); - delete m_proximityHandler; - delete m_im; - m_im = nullptr; - m_proximityHandler = nullptr; - } - } - - void OnSessionError(GridSession* session, const string& errorMsg) override - { - (void)session; - (void)errorMsg; - AZ_TracePrintf("GridMate", "Session error: %s\n", errorMsg.c_str()); - } - - IGridMate* m_gridMate; - GridSearch* m_lanSearch; - GridSession* m_session; - InterestManager* m_im; - ProximityInterestHandler* m_proximityHandler; - - ProximityInterestRule::Ptr m_rule; - unsigned m_num; - - AZStd::vector m_replicas; - }; - -public: - LargeWorldTest() : UnitTest::GridMateMPTestFixture(500u * 1024u * 1024u) // 500Mb - { - ReplicaChunkDescriptorTable::Get().RegisterChunkType(); - - ////////////////////////////////////////////////////////////////////////// - // Create all grid mates - m_peers[0].m_gridMate = m_gridMate; - m_peers[0].SessionEventBus::Handler::BusConnect(m_peers[0].m_gridMate); - m_peers[0].m_num = 0; - for (int i = 1; i < k_numMachines; ++i) - { - GridMateDesc desc; - m_peers[i].m_gridMate = GridMateCreate(desc); - AZ_TEST_ASSERT(m_peers[i].m_gridMate); - - m_peers[i].m_num = i; - m_peers[i].SessionEventBus::Handler::BusConnect(m_peers[i].m_gridMate); - } - ////////////////////////////////////////////////////////////////////////// - - for (int i = 0; i < k_numMachines; ++i) - { - // start the multiplayer service (session mgr, extra allocator, etc.) - StartGridMateService(m_peers[i].m_gridMate, SessionServiceDesc()); - AZ_TEST_ASSERT(LANSessionServiceBus::FindFirstHandler(m_peers[i].m_gridMate) != nullptr); - } - } - virtual ~LargeWorldTest() - { - StopGridMateService(m_peers[0].m_gridMate); - - for (int i = 1; i < k_numMachines; ++i) - { - if (m_peers[i].m_gridMate) - { - m_peers[i].SessionEventBus::Handler::BusDisconnect(); - GridMateDestroy(m_peers[i].m_gridMate); - } - } - - // this will stop the first IGridMate which owns the memory allocators. - m_peers[0].SessionEventBus::Handler::BusDisconnect(); - } - - void run() - { - g_PerfIM.Reset(); - g_PerfUpdatingAttributes.Reset(); - - TestCarrierDesc carrierDesc; - carrierDesc.m_enableDisconnectDetection = false; - carrierDesc.m_threadUpdateTimeMS = 10; - carrierDesc.m_familyType = Driver::BSD_AF_INET; - - LANSessionParams sp; - sp.m_topology = ST_PEER_TO_PEER; - sp.m_numPublicSlots = 64; - sp.m_port = k_hostPort; - EBUS_EVENT_ID_RESULT(m_peers[k_host].m_session, m_peers[k_host].m_gridMate, LANSessionServiceBus, HostSession, sp, carrierDesc); - m_peers[k_host].m_session->GetReplicaMgr()->SetAutoBroadcast(false); - - int listenPort = k_hostPort; - for (int i = 0; i < k_numMachines; ++i) - { - if (i == k_host) - { - continue; - } - - LANSearchParams searchParams; - searchParams.m_serverPort = k_hostPort; - searchParams.m_listenPort = listenPort == k_hostPort ? 0 : ++listenPort; // first client will use ephemeral port, the rest specify return ports - searchParams.m_familyType = Driver::BSD_AF_INET; - EBUS_EVENT_ID_RESULT(m_peers[i].m_lanSearch, m_peers[i].m_gridMate, LANSessionServiceBus, StartGridSearch, searchParams); - } - - - static const int maxNumUpdates = 300; - int numUpdates = 0; - TimeStamp time = AZStd::chrono::system_clock::now(); - - while (numUpdates <= maxNumUpdates) - { - g_PerfUpdatingAttributes.PreUpdate(); - for (LargeWorldTestChunk::Ptr replica : m_peers[0].m_replicas) - { - m_peers[0].UpdateAttribute(replica); - } - g_PerfUpdatingAttributes.PostUpdate(); - - for (auto peer : m_peers) - { - peer.UpdateRule(); - } - - //if (numUpdates == 100) - //{ - // // check how many replicas each client got - // for (AZ::u32 i = 1; i < k_numMachines; ++i) - // { - // AZ::u32 count = 0; - // for (auto& replica : m_peers[0].m_replicas) - // { - // ReplicaId repId = replica->GetReplicaId(); - // if (auto rep = m_peers[i].m_session->GetReplicaMgr()->FindReplica(repId)) - // { - // count++; - // } - // } - - // const AZ::Aabb& bounds = m_peers[i].m_rule->Get(); - - // AZ_Printf("GridMate", "Session %s Members: %d Bounds: %f.%f.%f-%f.%f.%f Replicas: %d\n", m_peers[i].m_session->GetId().c_str(), m_peers[i].m_session->GetNumberOfMembers(), - // static_cast(bounds.GetMin().GetX()), - // static_cast(bounds.GetMin().GetY()), - // static_cast(bounds.GetMin().GetZ()), - // static_cast(bounds.GetMax().GetX()), - // static_cast(bounds.GetMax().GetY()), - // static_cast(bounds.GetMax().GetZ()), count); - - // AZ_Assert(count == 1, "Should have at least some replicas to start with"); - // } - //} - - if (numUpdates == 200) - { - // Deleting all attributes - for (auto& replica : m_peers[0].m_replicas) - { - replica->m_attribute = nullptr; - } - } - - if (numUpdates == 250) - { - // Checking everybody lost all replicas (except primary) - for (int i = 0; i < k_numMachines; ++i) - { - /*for (int j = 0; j < k_numMachines; ++j) - { - if (i == j) - { - continue; - } - - ReplicaId repId = m_peers[j].m_replica->GetReplicaId(); - auto rep = m_peers[i].m_session->GetReplicaMgr()->FindReplica(repId); - AZ_TEST_ASSERT(rep == nullptr); - }*/ - - // deleting all rules - m_peers[i].DeleteRule(); - } - } - - ////////////////////////////////////////////////////////////////////////// - for (int i = 0; i < k_numMachines; ++i) - { - if (m_peers[i].m_gridMate) - { - m_peers[i].m_gridMate->Update(); - if (m_peers[i].m_session) - { - UpdateReplicas(m_peers[i].m_session->GetReplicaMgr(), m_peers[i].m_im); - } - } - } - Update(); - ////////////////////////////////////////////////////////////////////////// - - for (int i = 0; i < k_numMachines; ++i) - { - if (m_peers[i].m_lanSearch && m_peers[i].m_lanSearch->IsDone()) - { - AZ_TEST_ASSERT(m_peers[i].m_lanSearch->GetNumResults() == 1); - JoinParams jp; - EBUS_EVENT_ID_RESULT(m_peers[i].m_session, m_peers[i].m_gridMate, LANSessionServiceBus, JoinSessionBySearchInfo, static_cast(*m_peers[i].m_lanSearch->GetResult(0)), jp, carrierDesc); - m_peers[i].m_session->GetReplicaMgr()->SetAutoBroadcast(false); - - m_peers[i].m_lanSearch->Release(); - m_peers[i].m_lanSearch = nullptr; - } - } - - ////////////////////////////////////////////////////////////////////////// - // Debug Info - TimeStamp now = AZStd::chrono::system_clock::now(); - if (AZStd::chrono::milliseconds(now - time).count() > 1000) - { - time = now; - for (int i = 0; i < k_numMachines; ++i) - { - if (m_peers[i].m_session == nullptr) - { - continue; - } - - if (m_peers[i].m_session->IsHost()) - { - AZ_Printf("GridMate", "------ Host %d ------\n", i); - } - else - { - AZ_Printf("GridMate", "------ Client %d ------\n", i); - } - - AZ_Printf("GridMate", "Session %s Members: %d Host: %s Clock: %d\n", m_peers[i].m_session->GetId().c_str(), m_peers[i].m_session->GetNumberOfMembers(), m_peers[i].m_session->IsHost() ? "yes" : "no", m_peers[i].m_session->GetTime()); - for (unsigned int iMember = 0; iMember < m_peers[i].m_session->GetNumberOfMembers(); ++iMember) - { - GridMember* member = m_peers[i].m_session->GetMemberByIndex(iMember); - AZ_Printf("GridMate", " Member: %s(%s) Host: %s Local: %s\n", member->GetName().c_str(), member->GetId().ToString().c_str(), member->IsHost() ? "yes" : "no", member->IsLocal() ? "yes" : "no"); - } - AZ_Printf("GridMate", "\n"); - } - } - ////////////////////////////////////////////////////////////////////////// - - //AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds(30)); - numUpdates++; - } - - auto averageFrame = g_PerfIM.GetAverageFrame(); - auto bestFrame = g_PerfIM.GetBestFrame(); - auto worstFrame = g_PerfIM.GetWorstFrame(); - auto frames = g_PerfIM.GetTotalFrames(); - AZ_Printf("GridMate", "Interest manager performance: average_frame = %f sec, frames = %d, best= %f sec, worst= %f sec\n", - averageFrame, frames, bestFrame, worstFrame); - - AZ_Printf("GridMate", "Updating attributes: average_frame = %f sec, frames = %d, best= %f sec, worst= %f sec\n", - g_PerfUpdatingAttributes.GetAverageFrame(), - g_PerfUpdatingAttributes.GetTotalFrames(), - g_PerfUpdatingAttributes.GetBestFrame(), - g_PerfUpdatingAttributes.GetWorstFrame()); - } - - static const int k_numMachines = 3; - static const int k_host = 0; - static const int k_hostPort = 5450; - - LargeWorldTestPeerInfo m_peers[k_numMachines]; -}; - -void PerfForInterestManager::Reset() -{ - m_frameCount = 0; - m_totalUpdateTime = 0; - m_slowestFrame = 0; - m_fastestFrame = 100.f; -} - -void PerfForInterestManager::PreUpdate() -{ - m_timer.Stamp(); -} - -void PerfForInterestManager::PostUpdate() -{ - auto frameTime = m_timer.StampAndGetDeltaTimeInSeconds(); - m_totalUpdateTime += frameTime; - m_frameCount++; - - m_slowestFrame = AZStd::max(m_slowestFrame, frameTime); - m_fastestFrame = AZStd::min(m_fastestFrame, frameTime); -} - -AZ::u32 PerfForInterestManager::GetTotalFrames() const -{ - return m_frameCount; -} - -float PerfForInterestManager::GetAverageFrame() const -{ - if (m_frameCount > 0) - { - return m_totalUpdateTime / m_frameCount; - } - - return 0; -} - -float PerfForInterestManager::GetWorstFrame() const -{ - return m_slowestFrame; -} - -float PerfForInterestManager::GetBestFrame() const -{ - return m_fastestFrame; -} - -class ProximityHandlerTests - : public GridMateMPTestFixture -{ -public: - struct xyz - { - float x, y, z; - }; - - static AZ::Aabb CreateBox(xyz min, float size) - { - return AZ::Aabb::CreateFromMinMax( - AZ::Vector3::CreateFromFloat3(&min.x), - AZ::Vector3::CreateFromFloat3(&min.x) + AZ::Vector3::CreateOne() * size); - } - - static void run() - { - SimpleFirstUpdate(); - SecondUpdateAfterNoChanges(); - SimpleOutsideOfRule(); - AttributeMovingOutsideOfRule(); - RuleMovingAndAttributeIsOut(); - RuleDestroyed(); - AttributeDestroyed(); - } - - static void RuleMovingAndAttributeIsOut() - { - AZStd::unique_ptr handler(aznew ProximityInterestHandler()); - - auto attribute1 = handler->CreateAttribute(1); - attribute1->Set(CreateBox({ 0, 0, 0 }, 10)); - - auto rule1 = handler->CreateRule(100); - rule1->Set(CreateBox({ 0, 0, 0 }, 100)); - - handler->Update(); - InterestMatchResult results = handler->GetLastResult(); - //ProximityInterestHandler::DebugPrint(results, "1st"); - - AZ_TEST_ASSERT(results[1].size() == 1); - AZ_TEST_ASSERT(results[1].find(100) != results[1].end()); - - // now move the attribute outside of the rule - rule1->Set(CreateBox({ 1000, 0, 0 }, 100)); - - handler->Update(); - results = handler->GetLastResult(); - //ProximityInterestHandler::DebugPrint(results, "2nd"); - - AZ_TEST_ASSERT(results[1].size() == 0); - } - - static void AttributeMovingOutsideOfRule() - { - AZStd::unique_ptr handler(aznew ProximityInterestHandler()); - - auto attribute1 = handler->CreateAttribute(1); - attribute1->Set(CreateBox({ 0, 0, 0 }, 10)); - - auto rule1 = handler->CreateRule(100); - rule1->Set(CreateBox({ 0, 0, 0 }, 100)); - - handler->Update(); - InterestMatchResult results = handler->GetLastResult(); - //ProximityInterestHandler::DebugPrint(results, "1st"); - - AZ_TEST_ASSERT(results[1].size() == 1); - AZ_TEST_ASSERT(results[1].find(100) != results[1].end()); - - // now move the attribute outside of the rule - attribute1->Set(CreateBox({ -1000, 0, 0 }, 10)); - - handler->Update(); - results = handler->GetLastResult(); - //ProximityInterestHandler::DebugPrint(results, "2nd"); - - AZ_TEST_ASSERT(results[1].size() == 0); - } - - static void SimpleFirstUpdate() - { - AZStd::unique_ptr handler(aznew ProximityInterestHandler()); - - auto attribute1 = handler->CreateAttribute(1); - attribute1->Set(CreateBox({ 0, 0, 0 }, 10)); - - auto rule1 = handler->CreateRule(100); - rule1->Set(CreateBox({ 0, 0, 0 }, 100)); - - handler->Update(); - - InterestMatchResult results = handler->GetLastResult(); - - //ProximityInterestHandler::PrintMatchResult(results, "test"); - - AZ_TEST_ASSERT(results[1].size() == 1); - AZ_TEST_ASSERT(results[1].find(100) != results[1].end()); - } - - static void SecondUpdateAfterNoChanges() - { - AZStd::unique_ptr handler(aznew ProximityInterestHandler()); - - auto attribute1 = handler->CreateAttribute(1); - attribute1->Set(CreateBox({ 0, 0, 0 }, 10)); - - auto rule1 = handler->CreateRule(100); - rule1->Set(CreateBox({ 0, 0, 0 }, 100)); - - handler->Update(); - handler->Update(); - - InterestMatchResult results = handler->GetLastResult(); - - //ProximityInterestHandler::PrintMatchResult(results, "test"); - - AZ_TEST_ASSERT(results.size() == 0); - } - - static void SimpleOutsideOfRule() - { - AZStd::unique_ptr handler(aznew ProximityInterestHandler()); - - auto attribute1 = handler->CreateAttribute(1); - attribute1->Set(CreateBox({ -1000, 0, 0 }, 10)); - - auto rule1 = handler->CreateRule(100); - rule1->Set(CreateBox({ 0, 0, 0 }, 100)); - - handler->Update(); - - InterestMatchResult results = handler->GetLastResult(); - - //ProximityInterestHandler::PrintMatchResult(results, "test"); - - AZ_TEST_ASSERT(results.size() == 1); - AZ_TEST_ASSERT(results[1].size() == 0); - } - - static void RuleDestroyed() - { - AZStd::unique_ptr handler(aznew ProximityInterestHandler()); - - auto attribute1 = handler->CreateAttribute(1); - attribute1->Set(CreateBox({ 0, 0, 0 }, 10)); - - { - auto rule1 = handler->CreateRule(100); - rule1->Set(CreateBox({ 0, 0, 0 }, 100)); - - handler->Update(); - - InterestMatchResult results = handler->GetLastResult(); - AZ_TEST_ASSERT(results.size() == 1); - AZ_TEST_ASSERT(results[1].size() == 1); - } - - // rule1 should have been destroyed by now - - handler->Update(); - InterestMatchResult results = handler->GetLastResult(); - //ProximityInterestHandler::PrintMatchResult(results, "last"); - - AZ_TEST_ASSERT(results.size() == 1); - AZ_TEST_ASSERT(results[1].size() == 0); - } - - static void AttributeDestroyed() - { - AZStd::unique_ptr handler(aznew ProximityInterestHandler()); - - auto rule1 = handler->CreateRule(100); - rule1->Set(CreateBox({ 0, 0, 0 }, 100)); - - { - auto attribute1 = handler->CreateAttribute(1); - attribute1->Set(CreateBox({ 0, 0, 0 }, 10)); - - handler->Update(); - - InterestMatchResult results = handler->GetLastResult(); - AZ_TEST_ASSERT(results.size() == 1); - AZ_TEST_ASSERT(results[1].size() == 1); - } - - // attribute1 should have been destroyed by now, but it will show up once to remove it from affected peers - handler->Update(); - InterestMatchResult results = handler->GetLastResult(); - results.PrintMatchResult("last"); - - AZ_TEST_ASSERT(results.size() == 1); - AZ_TEST_ASSERT(results[1].size() == 0); - - // and now attribute1 should not show up in the changes - handler->Update(); - results = handler->GetLastResult(); - results.PrintMatchResult("last"); - - AZ_TEST_ASSERT(results.size() == 0); - } -}; - -}; // namespace UnitTest - -GM_TEST_SUITE(InterestSuite) - GM_TEST(Integ_InterestTest); -#if AZ_TRAIT_GRIDMATE_TEST_EXCLUDE_LARGEWORLDTEST != 0 - GM_TEST(LargeWorldTest); -#endif - GM_TEST(ProximityHandlerTests); -GM_TEST_SUITE_END() diff --git a/Code/Framework/GridMate/Tests/gridmate_test_files.cmake b/Code/Framework/GridMate/Tests/gridmate_test_files.cmake index a8b1dbd120..90ccbbf9a9 100644 --- a/Code/Framework/GridMate/Tests/gridmate_test_files.cmake +++ b/Code/Framework/GridMate/Tests/gridmate_test_files.cmake @@ -24,5 +24,4 @@ set(FILES StreamSocketDriverTests.cpp CarrierStreamSocketDriverTests.cpp Carrier.cpp - Interest.cpp ) From fffff75479b2777f50a7aceeaab3049842875804 Mon Sep 17 00:00:00 2001 From: jromnoa Date: Tue, 15 Jun 2021 13:55:10 -0700 Subject: [PATCH 109/116] add file check for _build_file_paths() function --- scripts/build/tools/upload_to_s3.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/build/tools/upload_to_s3.py b/scripts/build/tools/upload_to_s3.py index 3694014056..80ffcdb8e1 100755 --- a/scripts/build/tools/upload_to_s3.py +++ b/scripts/build/tools/upload_to_s3.py @@ -121,7 +121,8 @@ def _build_file_paths(path_to_files, files_in_path): for file_in_path in files_in_path: complete_file_path = os.path.join(path_to_files, file_in_path) - parsed_file_paths.append(complete_file_path) + if os.path.isfile(complete_file_path): + parsed_file_paths.append(complete_file_path) return parsed_file_paths From 2eca923694423a6714baf0464d1b527866cbe716 Mon Sep 17 00:00:00 2001 From: puvvadar Date: Tue, 15 Jun 2021 14:34:24 -0700 Subject: [PATCH 110/116] Rework session validation to work through Connect packet --- .../AutoGen/Multiplayer.AutoPackets.xml | 5 +- .../Source/MultiplayerSystemComponent.cpp | 81 ++++++++----------- .../Code/Source/MultiplayerSystemComponent.h | 3 +- 3 files changed, 36 insertions(+), 53 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/AutoGen/Multiplayer.AutoPackets.xml b/Gems/Multiplayer/Code/Source/AutoGen/Multiplayer.AutoPackets.xml index 3abd2a86d9..ce8931107f 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/Multiplayer.AutoPackets.xml +++ b/Gems/Multiplayer/Code/Source/AutoGen/Multiplayer.AutoPackets.xml @@ -9,16 +9,13 @@ + - - - - diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp index aa5e0d7467..5f44a2cccb 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp @@ -199,21 +199,10 @@ namespace Multiplayer { AZ::Interface::Get()->InitializeMultiplayer(MultiplayerAgentType::Client); + m_pendingConnectionTickets.push(config.m_playerSessionId); AZStd::string hostname = config.m_dnsName.empty() ? config.m_ipAddress : config.m_dnsName; const IpAddress ipAddress(hostname.c_str(), config.m_port, m_networkInterface->GetType()); - ConnectionId connectionId = m_networkInterface->Connect(ipAddress); - - AzNetworking::IConnection* connection = m_networkInterface->GetConnectionSet().GetConnection(connectionId); - if (connection->GetUserData() == nullptr) // Only add user data if the connect event handler has not already done so - { - connection->SetUserData(new ClientToServerConnectionData(connection, *this, config.m_playerSessionId)); - } - else - { - reinterpret_cast(connection->GetUserData())->SetProviderTicket(config.m_playerSessionId); - } - - connection->SendReliablePacket(MultiplayerPackets::ValidateSession(config.m_playerSessionId.c_str())); + m_networkInterface->Connect(ipAddress); return true; } @@ -416,6 +405,22 @@ namespace Multiplayer [[maybe_unused]] MultiplayerPackets::Connect& packet ) { + // Validate our session with the provider if any + if (AZ::Interface::Get() != nullptr) + { + AzFramework::PlayerConnectionConfig config; + config.m_playerConnectionId = aznumeric_cast(connection->GetConnectionId()); + config.m_playerSessionId = packet.GetTicket(); + if(!AZ::Interface::Get()->ValidatePlayerJoinSession(config)) + { + auto visitor = [](IConnection& connection) { connection.Disconnect(DisconnectReason::TerminatedByUser, TerminationEndpoint::Local); }; + m_networkInterface->GetConnectionSet().VisitConnections(visitor); + return true; + } + + reinterpret_cast(connection->GetUserData())->SetProviderTicket(packet.GetTicket().c_str()); + } + if (connection->SendReliablePacket(MultiplayerPackets::Accept(InvalidHostId, sv_map))) { // Sync our console @@ -441,31 +446,6 @@ namespace Multiplayer return true; } - bool MultiplayerSystemComponent::HandleRequest - ( - [[maybe_unused]] AzNetworking::IConnection* connection, - [[maybe_unused]] const IPacketHeader& packetHeader, - [[maybe_unused]] MultiplayerPackets::ValidateSession& packet - ) - { - // Validate our session with the provider if any - if (AZ::Interface::Get() != nullptr) - { - AzFramework::PlayerConnectionConfig config; - config.m_playerConnectionId = aznumeric_cast(connection->GetConnectionId()); - config.m_playerSessionId = packet.GetTicket(); - if(!AZ::Interface::Get()->ValidatePlayerJoinSession(config)) - { - connection->Disconnect(DisconnectReason::TerminatedByServer, TerminationEndpoint::Local); - return false; - } - - reinterpret_cast(connection->GetUserData())->SetProviderTicket(packet.GetTicket().c_str()); - } - - return true; - } - bool MultiplayerSystemComponent::HandleRequest ( AzNetworking::IConnection* connection, @@ -595,10 +575,16 @@ namespace Multiplayer datum.m_isInvited = false; datum.m_agentType = MultiplayerAgentType::Client; + AZStd::string providerTicket; if (connection->GetConnectionRole() == ConnectionRole::Connector) { AZLOG_INFO("New outgoing connection to remote address: %s", connection->GetRemoteAddress().GetString().c_str()); - connection->SendReliablePacket(MultiplayerPackets::Connect(0)); + if (!m_pendingConnectionTickets.empty()) + { + providerTicket = m_pendingConnectionTickets.front(); + m_pendingConnectionTickets.pop(); + } + connection->SendReliablePacket(MultiplayerPackets::Connect(0, providerTicket.c_str())); } else { @@ -628,7 +614,11 @@ namespace Multiplayer { if (connection->GetUserData() == nullptr) // Only add user data if the connect event handler has not already done so { - connection->SetUserData(new ClientToServerConnectionData(connection, *this)); + connection->SetUserData(new ClientToServerConnectionData(connection, *this, providerTicket)); + } + else + { + reinterpret_cast(connection->GetUserData())->SetProviderTicket(providerTicket); } AZStd::unique_ptr window = AZStd::make_unique(); @@ -652,12 +642,7 @@ namespace Multiplayer AZStd::string reasonString = ToString(reason); AZLOG_INFO("%s due to %s from remote address: %s", endpointString, reasonString.c_str(), connection->GetRemoteAddress().GetString().c_str()); - if (connection->GetConnectionRole() == ConnectionRole::Acceptor) - { - // The authority is shutting down its connection - m_shutdownEvent.Signal(m_networkInterface); - } - else if (GetAgentType() == MultiplayerAgentType::Client && connection->GetConnectionRole() == ConnectionRole::Connector) + if (GetAgentType() == MultiplayerAgentType::Client && connection->GetConnectionRole() == ConnectionRole::Connector) { // The client is disconnecting m_clientDisconnectedEvent.Signal(); @@ -675,7 +660,7 @@ namespace Multiplayer if (m_agentType == MultiplayerAgentType::DedicatedServer || m_agentType == MultiplayerAgentType::ClientServer) { if (AZ::Interface::Get() != nullptr && - connection->GetConnectionRole() == ConnectionRole::Connector) + connection->GetConnectionRole() == ConnectionRole::Acceptor) { AzFramework::PlayerConnectionConfig config; config.m_playerConnectionId = aznumeric_cast(connection->GetConnectionId()); @@ -686,7 +671,7 @@ namespace Multiplayer // Signal to session management when there are no remaining players in a dedicated server for potential cleanup // We avoid this for client server as the host itself is a user - if (m_agentType == MultiplayerAgentType::DedicatedServer && connection->GetConnectionRole() == ConnectionRole::Connector) + if (m_agentType == MultiplayerAgentType::DedicatedServer && connection->GetConnectionRole() == ConnectionRole::Acceptor) { if (AZ::Interface::Get() != nullptr && m_networkInterface->GetConnectionSet().GetConnectionCount() == 0) diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h index 2a3fe73ff4..00313c6b65 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h @@ -82,7 +82,6 @@ namespace Multiplayer bool HandleRequest(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, MultiplayerPackets::Connect& packet); bool HandleRequest(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, MultiplayerPackets::Accept& packet); - bool HandleRequest(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, MultiplayerPackets::ValidateSession& packet); bool HandleRequest(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, MultiplayerPackets::ReadyForEntityUpdates& packet); bool HandleRequest(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, MultiplayerPackets::SyncConsole& packet); bool HandleRequest(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, MultiplayerPackets::ConsoleCommand& packet); @@ -147,6 +146,8 @@ namespace Multiplayer ConnectionAcquiredEvent m_connAcquiredEvent; ClientDisconnectedEvent m_clientDisconnectedEvent; + AZStd::queue m_pendingConnectionTickets; + AZ::TimeMs m_lastReplicatedHostTimeMs = AZ::TimeMs{ 0 }; HostFrameId m_lastReplicatedHostFrameId = InvalidHostFrameId; From cd69b7c9d6c1214d8e4fa4b23dba77971b422eba Mon Sep 17 00:00:00 2001 From: jromnoa Date: Tue, 15 Jun 2021 14:34:44 -0700 Subject: [PATCH 111/116] do 1 print() call for a failed s3_upload_file() call and add a short 100 millisecond sleep between file upload retries --- scripts/build/tools/upload_to_s3.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/scripts/build/tools/upload_to_s3.py b/scripts/build/tools/upload_to_s3.py index 80ffcdb8e1..5666e6ec6b 100755 --- a/scripts/build/tools/upload_to_s3.py +++ b/scripts/build/tools/upload_to_s3.py @@ -26,6 +26,7 @@ python upload_to_s3.py --base_dir %WORKSPACE%/path/to/files --file_regex "(.*png import os import re import json +import time import boto3 from optparse import OptionParser @@ -100,13 +101,18 @@ def get_files_to_upload(base_dir, regex, search_subdirectories): def s3_upload_file(client, file, bucket, key_prefix=None, extra_args=None, max_retry=1): - key = file if key_prefix is None else '{}/{}'.format(key_prefix, file) + key = file if key_prefix is None else f'{key_prefix}/{file}' + error_message = None + for x in range(max_retry): try: client.upload_file(file, bucket, key, ExtraArgs=extra_args) return True except Exception as err: - print(('Upload failed: Exception while uploading: {}'.format(err))) + time.sleep(0.1) # Sleep for 100 milliseconds between retries. + error_message = err + + print(f'Upload failed - Exception while uploading: {error_message}') return False From cf5641a211ba15264d68604b420a223586fc00f2 Mon Sep 17 00:00:00 2001 From: puvvadar Date: Tue, 15 Jun 2021 14:53:23 -0700 Subject: [PATCH 112/116] Cleanup shutdown, activate and deactivate for MPSystemComponent --- .../Code/Source/MultiplayerSystemComponent.cpp | 16 ++++++++++++---- .../Code/Tests/MultiplayerSystemTests.cpp | 5 ++++- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp index 5f44a2cccb..3564c1e91e 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp @@ -179,7 +179,10 @@ namespace Multiplayer AZ::TickBus::Handler::BusConnect(); AzFramework::SessionNotificationBus::Handler::BusConnect(); m_networkInterface = AZ::Interface::Get()->CreateNetworkInterface(AZ::Name(MPNetworkInterfaceName), sv_protocol, TrustZone::ExternalClientToServer, *this); - m_consoleCommandHandler.Connect(AZ::Interface::Get()->GetConsoleCommandInvokedEvent()); + if (AZ::Interface::Get()) + { + m_consoleCommandHandler.Connect(AZ::Interface::Get()->GetConsoleCommandInvokedEvent()); + } AZ::Interface::Register(this); AZ::Interface::Register(this); @@ -191,6 +194,8 @@ namespace Multiplayer { AZ::Interface::Unregister(this); AZ::Interface::Unregister(this); + m_consoleCommandHandler.Disconnect(); + AZ::Interface::Get()->DestroyNetworkInterface(AZ::Name(MPNetworkInterfaceName)); AzFramework::SessionNotificationBus::Handler::BusDisconnect(); AZ::TickBus::Handler::BusDisconnect(); } @@ -673,10 +678,13 @@ namespace Multiplayer // We avoid this for client server as the host itself is a user if (m_agentType == MultiplayerAgentType::DedicatedServer && connection->GetConnectionRole() == ConnectionRole::Acceptor) { - if (AZ::Interface::Get() != nullptr - && m_networkInterface->GetConnectionSet().GetConnectionCount() == 0) + if (m_networkInterface->GetConnectionSet().GetConnectionCount() == 0) { - AZ::Interface::Get()->HandleDestroySession(); + m_shutdownEvent.Signal(m_networkInterface); + if (AZ::Interface::Get() != nullptr) + { + AZ::Interface::Get()->HandleDestroySession(); + } } } } diff --git a/Gems/Multiplayer/Code/Tests/MultiplayerSystemTests.cpp b/Gems/Multiplayer/Code/Tests/MultiplayerSystemTests.cpp index 7b09b65de4..9579c84fc1 100644 --- a/Gems/Multiplayer/Code/Tests/MultiplayerSystemTests.cpp +++ b/Gems/Multiplayer/Code/Tests/MultiplayerSystemTests.cpp @@ -35,14 +35,16 @@ namespace UnitTest m_initHandler = Multiplayer::SessionInitEvent::Handler([this](AzNetworking::INetworkInterface* value) { TestInitEvent(value); }); m_mpComponent->AddSessionInitHandler(m_initHandler); - m_shutdownHandler = Multiplayer::SessionInitEvent::Handler([this](AzNetworking::INetworkInterface* value) { TestShutdownEvent(value); }); + m_shutdownHandler = Multiplayer::SessionShutdownEvent::Handler([this](AzNetworking::INetworkInterface* value) { TestShutdownEvent(value); }); m_mpComponent->AddSessionShutdownHandler(m_shutdownHandler); m_connAcquiredHandler = Multiplayer::ConnectionAcquiredEvent::Handler([this](Multiplayer::MultiplayerAgentDatum value) { TestConnectionAcquiredEvent(value); }); m_mpComponent->AddConnectionAcquiredHandler(m_connAcquiredHandler); + m_mpComponent->Activate(); } void TearDown() override { + m_mpComponent->Deactivate(); delete m_mpComponent; delete m_netComponent; AZ::NameDictionary::Destroy(); @@ -86,6 +88,7 @@ namespace UnitTest TEST_F(MultiplayerSystemTests, TestShutdownEvent) { + m_mpComponent->InitializeMultiplayer(Multiplayer::MultiplayerAgentType::DedicatedServer); IMultiplayerConnectionMock connMock1 = IMultiplayerConnectionMock(AzNetworking::ConnectionId(), AzNetworking::IpAddress(), AzNetworking::ConnectionRole::Acceptor); IMultiplayerConnectionMock connMock2 = IMultiplayerConnectionMock(AzNetworking::ConnectionId(), AzNetworking::IpAddress(), AzNetworking::ConnectionRole::Connector); m_mpComponent->OnDisconnect(&connMock1, AzNetworking::DisconnectReason::None, AzNetworking::TerminationEndpoint::Local); From 7d1a12a14f667cd619dd0bc5f1df285b6aef9ce3 Mon Sep 17 00:00:00 2001 From: Yuriy Toporovskyy Date: Tue, 15 Jun 2021 18:33:44 -0400 Subject: [PATCH 113/116] Bug fix: crash after full screen preview due to dangling pointer --- Code/Sandbox/Editor/EditorViewportWidget.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Code/Sandbox/Editor/EditorViewportWidget.cpp b/Code/Sandbox/Editor/EditorViewportWidget.cpp index b02aafbe32..9ff38a34c1 100644 --- a/Code/Sandbox/Editor/EditorViewportWidget.cpp +++ b/Code/Sandbox/Editor/EditorViewportWidget.cpp @@ -1381,6 +1381,10 @@ void EditorViewportWidget::SetViewportId(int id) { CViewport::SetViewportId(id); + // Clear the cached debugdisplay pointer. we're about to delete that render viewport, and deleting the render + // viewport invalidates the debugdisplay. + m_debugDisplay = nullptr; + // First delete any existing layout // This also deletes any existing render viewport widget (since it will be added to the layout) // Below is the typical method of clearing a QLayout, see e.g. https://doc.qt.io/qt-5/qlayout.html#takeAt From 2a6009c94b9796abbe0222abc67c36e5886e2745 Mon Sep 17 00:00:00 2001 From: puvvadar Date: Tue, 15 Jun 2021 17:46:51 -0700 Subject: [PATCH 114/116] Cleanup OnDisconnect client case slightly --- Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp index 3564c1e91e..c43d136cd8 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp @@ -647,9 +647,10 @@ namespace Multiplayer AZStd::string reasonString = ToString(reason); AZLOG_INFO("%s due to %s from remote address: %s", endpointString, reasonString.c_str(), connection->GetRemoteAddress().GetString().c_str()); - if (GetAgentType() == MultiplayerAgentType::Client && connection->GetConnectionRole() == ConnectionRole::Connector) + // The client is disconnecting + if (GetAgentType() == MultiplayerAgentType::Client) { - // The client is disconnecting + AZ_Assert(connection->GetConnectionRole() == ConnectionRole::Connector, "Client connection role should only ever be Connector"); m_clientDisconnectedEvent.Signal(); } From d9b1ccd3235f5c59233e35d5c16363763a9019b2 Mon Sep 17 00:00:00 2001 From: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> Date: Wed, 16 Jun 2021 12:58:01 +0100 Subject: [PATCH 115/116] Add align grid button to Viewport UI (#1311) * first pass of adding grid snapping button * update to request current grid size * show/hide snapping option based on selection * small tidy-up changes * small updates following review feedback * added some unit tests for snapping functionality and some small tidy-up/refactoring * small refactor to ensure snap to grid ui only appears with snapping enabled * add missing include to resolve build error * fixes for build * add & to make compiler happy --- Code/Framework/AzCore/AzCore/std/math.h | 1 + .../AzManipulatorTestFrameworkTestHelpers.h | 1 + .../Manipulators/ManipulatorSnapping.cpp | 25 +- .../Manipulators/ManipulatorSnapping.h | 17 +- .../EditorTransformComponentSelection.cpp | 118 +++-- .../EditorTransformComponentSelection.h | 36 +- ...torTransformComponentSelectionRequestBus.h | 3 + .../ViewportUi/ViewportUiDisplay.cpp | 2 +- ...EditorTransformComponentSelectionTests.cpp | 417 +++++++++--------- 9 files changed, 364 insertions(+), 256 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/std/math.h b/Code/Framework/AzCore/AzCore/std/math.h index f5e2ac7ea7..fe2469eb41 100644 --- a/Code/Framework/AzCore/AzCore/std/math.h +++ b/Code/Framework/AzCore/AzCore/std/math.h @@ -26,6 +26,7 @@ namespace AZStd using std::exp2; using std::floor; using std::fmod; + using std::pow; using std::round; using std::sin; using std::sqrt; diff --git a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/AzManipulatorTestFrameworkTestHelpers.h b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/AzManipulatorTestFrameworkTestHelpers.h index b61956bdf9..d0107bb317 100644 --- a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/AzManipulatorTestFrameworkTestHelpers.h +++ b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/AzManipulatorTestFrameworkTestHelpers.h @@ -13,6 +13,7 @@ #pragma once #include +#include #include #include #include diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/ManipulatorSnapping.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/ManipulatorSnapping.cpp index 427bb9e9d1..27d8f7e5a3 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/ManipulatorSnapping.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/ManipulatorSnapping.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -95,16 +96,34 @@ namespace AzToolsFramework return axis * snapAdjustment.m_nextSnapDistance; } + AZ::Vector3 CalculateSnappedOffset( + const AZ::Vector3& unsnappedPosition, const AZ::Vector3* snapAxes, const size_t snapAxesCount, const float size) + { + return AZStd::accumulate( + snapAxes, snapAxes + snapAxesCount, AZ::Vector3::CreateZero(), + [&unsnappedPosition, size](AZ::Vector3 acc, const AZ::Vector3& snapAxis) + { + acc += CalculateSnappedOffset(unsnappedPosition, snapAxis, size); + return acc; + }); + } + + AZ::Vector3 CalculateSnappedPosition( + const AZ::Vector3& unsnappedPosition, const AZ::Vector3* snapAxes, const size_t snapAxesCount, const float size) + { + return unsnappedPosition + CalculateSnappedOffset(unsnappedPosition, snapAxes, snapAxesCount, size); + } + AZ::Vector3 CalculateSnappedTerrainPosition( - const AZ::Vector3& worldSurfacePosition, const AZ::Transform& worldFromLocal, const int viewportId, const float gridSize) + const AZ::Vector3& worldSurfacePosition, const AZ::Transform& worldFromLocal, const int viewportId, const float size) { const AZ::Transform localFromWorld = worldFromLocal.GetInverse(); const AZ::Vector3 localSurfacePosition = localFromWorld.TransformPoint(worldSurfacePosition); // snap in xy plane AZ::Vector3 localSnappedSurfacePosition = localSurfacePosition + - CalculateSnappedOffset(localSurfacePosition, AZ::Vector3::CreateAxisX(), gridSize) + - CalculateSnappedOffset(localSurfacePosition, AZ::Vector3::CreateAxisY(), gridSize); + CalculateSnappedOffset(localSurfacePosition, AZ::Vector3::CreateAxisX(), size) + + CalculateSnappedOffset(localSurfacePosition, AZ::Vector3::CreateAxisY(), size); // find terrain height at xy snapped location float terrainHeight = 0.0f; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/ManipulatorSnapping.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/ManipulatorSnapping.h index f2fa104d4c..9024625fae 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/ManipulatorSnapping.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/ManipulatorSnapping.h @@ -12,6 +12,7 @@ #pragma once +#include #include #include @@ -58,10 +59,18 @@ namespace AzToolsFramework //! @note A movement of more than half size (in either direction) will cause a snap by size. AZ::Vector3 CalculateSnappedAmount(const AZ::Vector3& unsnappedPosition, const AZ::Vector3& axis, float size); + //! Overload of CalculateSnappedOffset taking multiple axes. + AZ::Vector3 CalculateSnappedOffset( + const AZ::Vector3& unsnappedPosition, const AZ::Vector3* snapAxes, size_t snapAxesCount, float size); + + //! Return the final snapped position according to size (unsnappedPosition + CalculateSnappedOffset). + AZ::Vector3 CalculateSnappedPosition( + const AZ::Vector3& unsnappedPosition, const AZ::Vector3* snapAxes, size_t snapAxesCount, float size); + //! For a given point on the terrain, calculate the closest xy position snapped to the grid //! (z position is aligned to terrain height, not snapped to z grid) AZ::Vector3 CalculateSnappedTerrainPosition( - const AZ::Vector3& worldSurfacePosition, const AZ::Transform& worldFromLocal, int viewportId, float gridSize); + const AZ::Vector3& worldSurfacePosition, const AZ::Transform& worldFromLocal, int viewportId, float size); //! Wrapper for grid snapping and grid size bus calls. GridSnapParameters GridSnapSettings(int viewportId); @@ -84,8 +93,8 @@ namespace AzToolsFramework //! @param exponent Precision to use when rounding. inline float Round(const float value, const float exponent) { - const float precision = std::pow(10.0f, exponent); - return roundf(value * precision) / precision; + const float precision = AZStd::pow(10.0f, exponent); + return AZStd::round(value * precision) / precision; } //! Round to 3 significant digits (3 digits common usage). @@ -116,7 +125,7 @@ namespace AzToolsFramework //! when dealing with values far from the origin. inline AZ::Vector3 NonUniformScaleReciprocal(const AZ::Vector3& nonUniformScale) { - AZ::Vector3 scaleReciprocal = nonUniformScale.GetReciprocal(); + const AZ::Vector3 scaleReciprocal = nonUniformScale.GetReciprocal(); return AZ::Vector3(Round3(scaleReciprocal.GetX()), Round3(scaleReciprocal.GetY()), Round3(scaleReciprocal.GetZ())); } } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp index eb16bf158e..c4f1ae33da 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp @@ -127,6 +127,7 @@ namespace AzToolsFramework static const char* const s_dittoTranslationIndividualUndoRedoDesc = "Ditto translation individual"; static const char* const s_dittoScaleIndividualWorldUndoRedoDesc = "Ditto scale individual world"; static const char* const s_dittoScaleIndividualLocalUndoRedoDesc = "Ditto scale individual local"; + static const char* const s_snapToWorldGridUndoRedoDesc = "Snap to world grid"; static const char* const s_showAllEntitiesUndoRedoDesc = s_showAllTitle; static const char* const s_lockSelectionUndoRedoDesc = s_lockSelectionTitle; static const char* const s_hideSelectionUndoRedoDesc = s_hideSelectionTitle; @@ -142,6 +143,7 @@ namespace AzToolsFramework static const char* const SpaceClusterWorldTooltip = "Toggle world space lock"; static const char* const SpaceClusterParentTooltip = "Toggle parent space lock"; static const char* const SpaceClusterLocalTooltip = "Toggle local space lock"; + static const char* const SnappingClusterSnapToWorldTooltip = "Snap selected entities to the world space grid"; static const AZ::Color s_fadedXAxisColor = AZ::Color(AZ::u8(200), AZ::u8(127), AZ::u8(127), AZ::u8(255)); static const AZ::Color s_fadedYAxisColor = AZ::Color(AZ::u8(127), AZ::u8(190), AZ::u8(127), AZ::u8(255)); @@ -150,8 +152,6 @@ namespace AzToolsFramework static const AZ::Color s_pickedOrientationColor = AZ::Color(0.0f, 1.0f, 0.0f, 1.0f); static const AZ::Color s_selectedEntityAabbColor = AZ::Color(0.6f, 0.6f, 0.6f, 0.4f); - static const int s_defaultViewportId = 0; - static const float s_pivotSize = 0.075f; // the size of the pivot (box) to render when selected // data passed to manipulators when processing mouse interactions @@ -503,7 +503,8 @@ namespace AzToolsFramework void EditorTransformComponentSelection::SetAllViewportUiVisible(const bool visible) { SetViewportUiClusterVisible(m_transformModeClusterId, visible); - SetViewportUiClusterVisible(m_spaceCluster.m_spaceClusterId, visible); + SetViewportUiClusterVisible(m_spaceCluster.m_clusterId, visible); + SetViewportUiClusterVisible(m_snappingCluster.m_clusterId, visible); m_viewportUiVisible = visible; } @@ -524,8 +525,8 @@ namespace AzToolsFramework }; ViewportUi::ViewportUiRequestBus::Event( - ViewportUi::DefaultViewportId, &ViewportUi::ViewportUiRequestBus::Events::SetClusterActiveButton, - m_spaceCluster.m_spaceClusterId, buttonIdFromFrameFn(referenceFrame)); + ViewportUi::DefaultViewportId, &ViewportUi::ViewportUiRequestBus::Events::SetClusterActiveButton, m_spaceCluster.m_clusterId, + buttonIdFromFrameFn(referenceFrame)); } namespace ETCS @@ -1037,6 +1038,8 @@ namespace AzToolsFramework CreateTransformModeSelectionCluster(); CreateSpaceSelectionCluster(); + CreateSnappingCluster(); + RegisterActions(); SetupBoxSelect(); RefreshSelectedEntityIdsAndRegenerateManipulators(); @@ -1048,7 +1051,8 @@ namespace AzToolsFramework DestroyManipulators(m_entityIdManipulators); DestroyCluster(m_transformModeClusterId); - DestroyCluster(m_spaceCluster.m_spaceClusterId); + DestroyCluster(m_spaceCluster.m_clusterId); + DestroyCluster(m_snappingCluster.m_clusterId); UnregisterActions(); @@ -2513,28 +2517,64 @@ namespace AzToolsFramework m_transformModeSelectionHandler); } - void EditorTransformComponentSelection::CreateSpaceSelectionCluster() + void EditorTransformComponentSelection::CreateSnappingCluster() { // create the cluster for switching spaces/reference frames ViewportUi::ViewportUiRequestBus::EventResult( - m_spaceCluster.m_spaceClusterId, ViewportUi::DefaultViewportId, &ViewportUi::ViewportUiRequestBus::Events::CreateCluster, + m_snappingCluster.m_clusterId, ViewportUi::DefaultViewportId, &ViewportUi::ViewportUiRequestBus::Events::CreateCluster, ViewportUi::Alignment::TopRight); - // create and register the buttons (strings correspond to icons even if the values appear different) - m_spaceCluster.m_worldButtonId = RegisterClusterButton(m_spaceCluster.m_spaceClusterId, "World"); - m_spaceCluster.m_parentButtonId = RegisterClusterButton(m_spaceCluster.m_spaceClusterId, "Parent"); - m_spaceCluster.m_localButtonId = RegisterClusterButton(m_spaceCluster.m_spaceClusterId, "Local"); + m_snappingCluster.m_snapToWorldButtonId = RegisterClusterButton(m_snappingCluster.m_clusterId, "Grid"); // set button tooltips ViewportUi::ViewportUiRequestBus::Event( ViewportUi::DefaultViewportId, &ViewportUi::ViewportUiRequestBus::Events::SetClusterButtonTooltip, - m_spaceCluster.m_spaceClusterId, m_spaceCluster.m_worldButtonId, SpaceClusterWorldTooltip); + m_snappingCluster.m_clusterId, m_snappingCluster.m_snapToWorldButtonId, SnappingClusterSnapToWorldTooltip); + + const auto onButtonClicked = [this](const ViewportUi::ButtonId buttonId) + { + if (buttonId == m_snappingCluster.m_snapToWorldButtonId) + { + float gridSize = 1.0f; + ViewportInteraction::ViewportInteractionRequestBus::EventResult( + gridSize, ViewportUi::DefaultViewportId, &ViewportInteraction::ViewportInteractionRequestBus::Events::GridSize); + + SnapSelectedEntitiesToWorldGrid(gridSize); + } + }; + + m_snappingCluster.m_snappingHandler = AZ::Event::Handler(onButtonClicked); + ViewportUi::ViewportUiRequestBus::Event( - ViewportUi::DefaultViewportId, &ViewportUi::ViewportUiRequestBus::Events::SetClusterButtonTooltip, - m_spaceCluster.m_spaceClusterId, m_spaceCluster.m_parentButtonId, SpaceClusterParentTooltip); + ViewportUi::DefaultViewportId, &ViewportUi::ViewportUiRequestBus::Events::RegisterClusterEventHandler, + m_snappingCluster.m_clusterId, m_snappingCluster.m_snappingHandler); + + // hide initially + SetViewportUiClusterVisible(m_snappingCluster.m_clusterId, false); + } + + void EditorTransformComponentSelection::CreateSpaceSelectionCluster() + { + // create the cluster for switching spaces/reference frames + ViewportUi::ViewportUiRequestBus::EventResult( + m_spaceCluster.m_clusterId, ViewportUi::DefaultViewportId, &ViewportUi::ViewportUiRequestBus::Events::CreateCluster, + ViewportUi::Alignment::TopRight); + + // create and register the buttons (strings correspond to icons even if the values appear different) + m_spaceCluster.m_worldButtonId = RegisterClusterButton(m_spaceCluster.m_clusterId, "World"); + m_spaceCluster.m_parentButtonId = RegisterClusterButton(m_spaceCluster.m_clusterId, "Parent"); + m_spaceCluster.m_localButtonId = RegisterClusterButton(m_spaceCluster.m_clusterId, "Local"); + + // set button tooltips ViewportUi::ViewportUiRequestBus::Event( - ViewportUi::DefaultViewportId, &ViewportUi::ViewportUiRequestBus::Events::SetClusterButtonTooltip, - m_spaceCluster.m_spaceClusterId, m_spaceCluster.m_localButtonId, SpaceClusterLocalTooltip); + ViewportUi::DefaultViewportId, &ViewportUi::ViewportUiRequestBus::Events::SetClusterButtonTooltip, m_spaceCluster.m_clusterId, + m_spaceCluster.m_worldButtonId, SpaceClusterWorldTooltip); + ViewportUi::ViewportUiRequestBus::Event( + ViewportUi::DefaultViewportId, &ViewportUi::ViewportUiRequestBus::Events::SetClusterButtonTooltip, m_spaceCluster.m_clusterId, + m_spaceCluster.m_parentButtonId, SpaceClusterParentTooltip); + ViewportUi::ViewportUiRequestBus::Event( + ViewportUi::DefaultViewportId, &ViewportUi::ViewportUiRequestBus::Events::SetClusterButtonTooltip, m_spaceCluster.m_clusterId, + m_spaceCluster.m_localButtonId, SpaceClusterLocalTooltip); auto onButtonClicked = [this](ViewportUi::ButtonId buttonId) { @@ -2576,14 +2616,31 @@ namespace AzToolsFramework } ViewportUi::ViewportUiRequestBus::Event( ViewportUi::DefaultViewportId, &ViewportUi::ViewportUiRequestBus::Events::SetClusterButtonLocked, - m_spaceCluster.m_spaceClusterId, buttonId, m_spaceCluster.m_spaceLock.has_value()); + m_spaceCluster.m_clusterId, buttonId, m_spaceCluster.m_spaceLock.has_value()); }; - m_spaceCluster.m_spaceSelectionHandler = AZ::Event::Handler(onButtonClicked); + m_spaceCluster.m_spaceHandler = AZ::Event::Handler(onButtonClicked); ViewportUi::ViewportUiRequestBus::Event( ViewportUi::DefaultViewportId, &ViewportUi::ViewportUiRequestBus::Events::RegisterClusterEventHandler, - m_spaceCluster.m_spaceClusterId, m_spaceCluster.m_spaceSelectionHandler); + m_spaceCluster.m_clusterId, m_spaceCluster.m_spaceHandler); + } + + void EditorTransformComponentSelection::SnapSelectedEntitiesToWorldGrid(const float gridSize) + { + AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework); + + const AZStd::array snapAxes = { AZ::Vector3::CreateAxisX(), AZ::Vector3::CreateAxisY(), AZ::Vector3::CreateAxisZ() }; + + ScopedUndoBatch undoBatch(s_snapToWorldGridUndoRedoDesc); + for (const AZ::EntityId& entityId : m_selectedEntityIds) + { + ScopedUndoBatch::MarkEntityDirty(entityId); + SetEntityWorldTranslation( + entityId, CalculateSnappedPosition(GetWorldTranslation(entityId), snapAxes.data(), snapAxes.size(), gridSize)); + } + + RefreshManipulators(RefreshType::Translation); } EditorTransformComponentSelectionRequests::Mode EditorTransformComponentSelection::GetTransformMode() @@ -3145,15 +3202,16 @@ namespace AzToolsFramework return "Transform Component"; } - void EditorTransformComponentSelection::PopulateEditorGlobalContextMenu(QMenu* menu, [[maybe_unused]] const AZ::Vector2& point, [[maybe_unused]] int flags) + void EditorTransformComponentSelection::PopulateEditorGlobalContextMenu( + QMenu* menu, [[maybe_unused]] const AZ::Vector2& point, [[maybe_unused]] int flags) { - QAction* action = menu->addAction(QObject::tr(s_togglePivotTitleRightClick)); - QObject::connect( - action, &QAction::triggered, action, - [this]() - { - ToggleCenterPivotSelection(); - }); + QAction* action = menu->addAction(QObject::tr(s_togglePivotTitleRightClick)); + QObject::connect( + action, &QAction::triggered, action, + [this]() + { + ToggleCenterPivotSelection(); + }); } void EditorTransformComponentSelection::BeforeEntitySelectionChanged() @@ -3175,7 +3233,7 @@ namespace AzToolsFramework } void EditorTransformComponentSelection::AfterEntitySelectionChanged( - const EntityIdList& /*newlySelectedEntities*/, const EntityIdList& /*newlyDeselectedEntities*/) + [[maybe_unused]] const EntityIdList& newlySelectedEntities, [[maybe_unused]] const EntityIdList& newlyDeselectedEntities) { AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework); @@ -3195,6 +3253,8 @@ namespace AzToolsFramework m_didSetSelectedEntities = false; } + SetViewportUiClusterVisible(m_snappingCluster.m_clusterId, m_viewportUiVisible && !m_selectedEntityIds.empty()); + RegenerateManipulators(); } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h index 773921ebea..db96d91911 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h @@ -115,12 +115,25 @@ namespace AzToolsFramework SpaceCluster(const SpaceCluster&) = delete; SpaceCluster& operator=(const SpaceCluster&) = delete; - ViewportUi::ClusterId m_spaceClusterId; //!< The id identifying the reference space cluster. + ViewportUi::ClusterId m_clusterId; //!< The id identifying the reference space cluster. ViewportUi::ButtonId m_localButtonId; //!< Local reference space button id. ViewportUi::ButtonId m_parentButtonId; //!< Parent reference space button id. ViewportUi::ButtonId m_worldButtonId; //!< World reference space button id. - AZ::Event::Handler m_spaceSelectionHandler; //!< Callback for when a space cluster button is pressed. AZStd::optional m_spaceLock; //!< Locked reference frame to use if set. + AZ::Event::Handler m_spaceHandler; //!< Callback for when a space cluster button is pressed. + }; + + //! Grouping of viewport ui related state for aligning transforms to a grid. + struct SnappingCluster + { + SnappingCluster() = default; + // disable copying and moving (implicit) + SnappingCluster(const SnappingCluster&) = delete; + SnappingCluster& operator=(const SnappingCluster&) = delete; + + ViewportUi::ClusterId m_clusterId; //!< The cluster id for all snapping buttons. + ViewportUi::ButtonId m_snapToWorldButtonId; //!< The button id for snapping all axes to the world. + AZ::Event::Handler m_snappingHandler; //!< Callback for when a snapping cluster button is pressed. }; //! Entity selection/interaction handling. @@ -180,6 +193,7 @@ namespace AzToolsFramework void CreateTransformModeSelectionCluster(); void CreateSpaceSelectionCluster(); + void CreateSnappingCluster(); void ClearManipulatorTranslationOverride(); void ClearManipulatorOrientationOverride(); @@ -228,14 +242,15 @@ namespace AzToolsFramework AZStd::optional GetManipulatorTransform() override; void OverrideManipulatorOrientation(const AZ::Quaternion& orientation) override; void OverrideManipulatorTranslation(const AZ::Vector3& translation) override; - void CopyTranslationToSelectedEntitiesIndividual(const AZ::Vector3& translation); - void CopyTranslationToSelectedEntitiesGroup(const AZ::Vector3& translation); - void ResetTranslationForSelectedEntitiesLocal(); - void CopyOrientationToSelectedEntitiesIndividual(const AZ::Quaternion& orientation); - void CopyOrientationToSelectedEntitiesGroup(const AZ::Quaternion& orientation); - void ResetOrientationForSelectedEntitiesLocal(); - void CopyScaleToSelectedEntitiesIndividualLocal(float scale); - void CopyScaleToSelectedEntitiesIndividualWorld(float scale); + void CopyTranslationToSelectedEntitiesIndividual(const AZ::Vector3& translation) override; + void CopyTranslationToSelectedEntitiesGroup(const AZ::Vector3& translation) override; + void ResetTranslationForSelectedEntitiesLocal() override; + void CopyOrientationToSelectedEntitiesIndividual(const AZ::Quaternion& orientation) override; + void CopyOrientationToSelectedEntitiesGroup(const AZ::Quaternion& orientation) override; + void ResetOrientationForSelectedEntitiesLocal() override; + void CopyScaleToSelectedEntitiesIndividualLocal(float scale) override; + void CopyScaleToSelectedEntitiesIndividualWorld(float scale) override; + void SnapSelectedEntitiesToWorldGrid(float gridSize) override; // EditorManipulatorCommandUndoRedoRequestBus ... void UndoRedoEntityManipulatorCommand( @@ -320,6 +335,7 @@ namespace AzToolsFramework AzFramework::ClickDetector m_clickDetector; //!< Detect different types of mouse click. AzFramework::CursorState m_cursorState; //!< Track the mouse position and delta movement each frame. SpaceCluster m_spaceCluster; //!< Related viewport ui state for controlling the current reference space. + SnappingCluster m_snappingCluster; //!< Related viewport ui state for aligning positions to a grid or reference frame. bool m_viewportUiVisible = true; //!< Used to hide/show the viewport ui elements. }; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelectionRequestBus.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelectionRequestBus.h index 966f9333fc..c7b75da206 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelectionRequestBus.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelectionRequestBus.h @@ -104,6 +104,9 @@ namespace AzToolsFramework //! Copy scale to to each individual entity in world (absolute) space. virtual void CopyScaleToSelectedEntitiesIndividualWorld(float scale) = 0; + //! Snap selected entities to be aligned with the world space grid. + virtual void SnapSelectedEntitiesToWorldGrid(float gridSize) = 0; + protected: ~EditorTransformComponentSelectionRequests() = default; }; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiDisplay.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiDisplay.cpp index 7b2d45e652..bb2aeed4d6 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiDisplay.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiDisplay.cpp @@ -281,7 +281,7 @@ namespace AzToolsFramework::ViewportUi::Internal void ViewportUiDisplay::HideViewportUiElement(ViewportUiElementId elementId) { if (ViewportUiElementInfo element = GetViewportUiElementInfo(elementId); - element.m_widget && UiDisplayEnabled()) + element.m_widget) { element.m_widget->setVisible(false); } diff --git a/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp b/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp index cbc81ba9b8..9a34efa6f5 100644 --- a/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp @@ -1,42 +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. -* -*/ + * 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 #include #include -#include #include +#include #include +#include +#include +#include +#include +#include +#include +#include #include #include #include #include #include -#include #include #include +#include #include #include #include #include #include #include -#include -#include -#include -#include -#include -#include -#include using namespace AzToolsFramework; @@ -46,12 +46,11 @@ namespace AZ { return os << entityId.ToString().c_str(); } -} +} // namespace AZ namespace UnitTest { - class EditorEntityVisibilityCacheFixture - : public ToolsApplicationFixture + class EditorEntityVisibilityCacheFixture : public ToolsApplicationFixture { public: void CreateLayerAndEntityHierarchy() @@ -116,8 +115,7 @@ namespace UnitTest } // Fixture to support testing EditorTransformComponentSelection functionality on an Entity selection. - class EditorTransformComponentSelectionFixture - : public ToolsApplicationFixture + class EditorTransformComponentSelectionFixture : public ToolsApplicationFixture { public: void SetUpEditorFixtureImpl() override @@ -138,13 +136,11 @@ namespace UnitTest EntityIdList m_entityIds; }; - void EditorTransformComponentSelectionFixture::ArrangeIndividualRotatedEntitySelection( - const AZ::Quaternion& orientation) + void EditorTransformComponentSelectionFixture::ArrangeIndividualRotatedEntitySelection(const AZ::Quaternion& orientation) { for (auto entityId : m_entityIds) { - AZ::TransformBus::Event( - entityId, &AZ::TransformBus::Events::SetLocalRotationQuaternion, orientation); + AZ::TransformBus::Event(entityId, &AZ::TransformBus::Events::SetLocalRotationQuaternion, orientation); } } @@ -152,40 +148,32 @@ namespace UnitTest { AZStd::optional manipulatorTransform; EditorTransformComponentSelectionRequestBus::EventResult( - manipulatorTransform, GetEntityContextId(), - &EditorTransformComponentSelectionRequests::GetManipulatorTransform); + manipulatorTransform, GetEntityContextId(), &EditorTransformComponentSelectionRequests::GetManipulatorTransform); return manipulatorTransform; } - void EditorTransformComponentSelectionFixture::RefreshManipulators( - EditorTransformComponentSelectionRequests::RefreshType refreshType) + void EditorTransformComponentSelectionFixture::RefreshManipulators(EditorTransformComponentSelectionRequests::RefreshType refreshType) { EditorTransformComponentSelectionRequestBus::Event( GetEntityContextId(), &EditorTransformComponentSelectionRequests::RefreshManipulators, refreshType); } - void EditorTransformComponentSelectionFixture::SetTransformMode( - EditorTransformComponentSelectionRequests::Mode transformMode) + void EditorTransformComponentSelectionFixture::SetTransformMode(EditorTransformComponentSelectionRequests::Mode transformMode) { EditorTransformComponentSelectionRequestBus::Event( - GetEntityContextId(), &EditorTransformComponentSelectionRequests::SetTransformMode, - transformMode); + GetEntityContextId(), &EditorTransformComponentSelectionRequests::SetTransformMode, transformMode); } - void EditorTransformComponentSelectionFixture::OverrideManipulatorOrientation( - const AZ::Quaternion& orientation) + void EditorTransformComponentSelectionFixture::OverrideManipulatorOrientation(const AZ::Quaternion& orientation) { EditorTransformComponentSelectionRequestBus::Event( - GetEntityContextId(), &EditorTransformComponentSelectionRequests::OverrideManipulatorOrientation, - orientation); + GetEntityContextId(), &EditorTransformComponentSelectionRequests::OverrideManipulatorOrientation, orientation); } - void EditorTransformComponentSelectionFixture::OverrideManipulatorTranslation( - const AZ::Vector3& translation) + void EditorTransformComponentSelectionFixture::OverrideManipulatorTranslation(const AZ::Vector3& translation) { EditorTransformComponentSelectionRequestBus::Event( - GetEntityContextId(), &EditorTransformComponentSelectionRequests::OverrideManipulatorTranslation, - translation); + GetEntityContextId(), &EditorTransformComponentSelectionRequests::OverrideManipulatorTranslation, translation); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -202,8 +190,7 @@ namespace UnitTest SetTransformMode(EditorTransformComponentSelectionRequests::Mode::Rotation); - const AZ::Transform manipulatorTransformBefore = - GetManipulatorTransform().value_or(AZ::Transform::CreateIdentity()); + const AZ::Transform manipulatorTransformBefore = GetManipulatorTransform().value_or(AZ::Transform::CreateIdentity()); // check preconditions - manipulator transform matches parent/world transform (identity) EXPECT_THAT(manipulatorTransformBefore.GetBasisY(), IsClose(AZ::Vector3::CreateAxisY())); @@ -218,8 +205,7 @@ namespace UnitTest /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Then - const AZ::Transform manipulatorTransformAfter = - GetManipulatorTransform().value_or(AZ::Transform::CreateIdentity()); + const AZ::Transform manipulatorTransformAfter = GetManipulatorTransform().value_or(AZ::Transform::CreateIdentity()); // check postconditions - manipulator transform matches parent/world transform (identity) EXPECT_THAT(manipulatorTransformAfter.GetBasisY(), IsClose(AZ::Vector3::CreateAxisY())); @@ -229,8 +215,7 @@ namespace UnitTest { // create invalid starting orientation to guarantee correct data is coming from GetLocalRotationQuaternion AZ::Quaternion entityOrientation = AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisX(), 90.0f); - AZ::TransformBus::EventResult( - entityOrientation, entityId, &AZ::TransformBus::Events::GetLocalRotationQuaternion); + AZ::TransformBus::EventResult(entityOrientation, entityId, &AZ::TransformBus::Events::GetLocalRotationQuaternion); // manipulator orientation matches entity orientation EXPECT_THAT(entityOrientation, IsClose(manipulatorTransformAfter.GetRotation())); @@ -252,8 +237,7 @@ namespace UnitTest SetTransformMode(EditorTransformComponentSelectionRequests::Mode::Rotation); - const AZ::Transform manipulatorTransformBefore = - GetManipulatorTransform().value_or(AZ::Transform::CreateIdentity()); + const AZ::Transform manipulatorTransformBefore = GetManipulatorTransform().value_or(AZ::Transform::CreateIdentity()); // check preconditions - manipulator transform matches manipulator orientation override (not entity transform) EXPECT_THAT(manipulatorTransformBefore.GetBasisX(), IsClose(AZ::Vector3::CreateAxisY())); @@ -268,8 +252,7 @@ namespace UnitTest /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Then - const AZ::Transform manipulatorTransformAfter = - GetManipulatorTransform().value_or(AZ::Transform::CreateIdentity()); + const AZ::Transform manipulatorTransformAfter = GetManipulatorTransform().value_or(AZ::Transform::CreateIdentity()); // check postconditions - manipulator transform matches parent/world space (manipulator override was cleared) EXPECT_THAT(manipulatorTransformAfter.GetBasisY(), IsClose(AZ::Vector3::CreateAxisY())); @@ -278,8 +261,7 @@ namespace UnitTest for (auto entityId : m_entityIds) { AZ::Quaternion entityOrientation; - AZ::TransformBus::EventResult( - entityOrientation, entityId, &AZ::TransformBus::Events::GetLocalRotationQuaternion); + AZ::TransformBus::EventResult(entityOrientation, entityId, &AZ::TransformBus::Events::GetLocalRotationQuaternion); // entity transform matches initial (entity transform was not reset, only manipulator was) EXPECT_THAT(entityOrientation, IsClose(initialEntityOrientation)); @@ -301,16 +283,13 @@ namespace UnitTest AZ::EntityId parentId = CreateDefaultEditorEntity("Parent", &parent); AZ::EntityId childId = CreateDefaultEditorEntity("Child", &child); - AZ::TransformBus::Event( - childId, &AZ::TransformInterface::SetParent, parentId); - AZ::TransformBus::Event( - parentId, &AZ::TransformInterface::SetParent, grandParentId); + AZ::TransformBus::Event(childId, &AZ::TransformInterface::SetParent, parentId); + AZ::TransformBus::Event(parentId, &AZ::TransformInterface::SetParent, grandParentId); UnitTest::SliceAssets sliceAssets; const auto sliceAssetId = UnitTest::SaveAsSlice({ grandParent }, GetApplication(), sliceAssets); - EntityList instantiatedEntities = - UnitTest::InstantiateSlice(sliceAssetId, sliceAssets); + EntityList instantiatedEntities = UnitTest::InstantiateSlice(sliceAssetId, sliceAssets); const AZ::EntityId entityIdToMove = instantiatedEntities.back()->GetId(); EditorEntityComponentChangeDetector editorEntityChangeDetector(entityIdToMove); @@ -321,8 +300,7 @@ namespace UnitTest /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // When EditorTransformComponentSelectionRequestBus::Event( - GetEntityContextId(), - &EditorTransformComponentSelectionRequests::CopyOrientationToSelectedEntitiesIndividual, + GetEntityContextId(), &EditorTransformComponentSelectionRequests::CopyOrientationToSelectedEntitiesIndividual, AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisX(), AZ::DegToRad(90.0f))); /////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -362,10 +340,9 @@ namespace UnitTest /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Then AzToolsFramework::EntityIdList selectedEntities; - ToolsApplicationRequestBus::BroadcastResult( - selectedEntities, &ToolsApplicationRequestBus::Events::GetSelectedEntities); + ToolsApplicationRequestBus::BroadcastResult(selectedEntities, &ToolsApplicationRequestBus::Events::GetSelectedEntities); - AzToolsFramework::EntityIdList expectedSelectedEntities = {entity4, entity5, entity6}; + AzToolsFramework::EntityIdList expectedSelectedEntities = { entity4, entity5, entity6 }; EXPECT_THAT(selectedEntities, UnorderedElementsAreArray(expectedSelectedEntities)); /////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -396,10 +373,9 @@ namespace UnitTest /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Then AzToolsFramework::EntityIdList selectedEntities; - ToolsApplicationRequestBus::BroadcastResult( - selectedEntities, &ToolsApplicationRequestBus::Events::GetSelectedEntities); + ToolsApplicationRequestBus::BroadcastResult(selectedEntities, &ToolsApplicationRequestBus::Events::GetSelectedEntities); - AzToolsFramework::EntityIdList expectedSelectedEntities = {m_entity1, entity2, entity3, entity4}; + AzToolsFramework::EntityIdList expectedSelectedEntities = { m_entity1, entity2, entity3, entity4 }; EXPECT_THAT(selectedEntities, UnorderedElementsAreArray(expectedSelectedEntities)); /////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -416,11 +392,9 @@ namespace UnitTest const auto finalTransformWorld = AZ::Transform::CreateTranslation(AZ::Vector3(10.0f, 10.0f, 0.0f)); // calculate the position in screen space of the initial position of the entity - const auto initialPositionScreen = - AzFramework::WorldToScreen(initialTransformWorld.GetTranslation(), m_cameraState); + const auto initialPositionScreen = AzFramework::WorldToScreen(initialTransformWorld.GetTranslation(), m_cameraState); // calculate the position in screen space of the final position of the entity - const auto finalPositionScreen = - AzFramework::WorldToScreen(finalTransformWorld.GetTranslation(), m_cameraState); + const auto finalPositionScreen = AzFramework::WorldToScreen(finalTransformWorld.GetTranslation(), m_cameraState); // select the entity (this will cause the manipulators to appear in EditorTransformComponentSelection) AzToolsFramework::SelectEntity(m_entity1); @@ -452,10 +426,10 @@ namespace UnitTest } // simple widget to listen for a mouse wheel event and then forward it on to the ViewportSelectionRequestBus - class WheelEventWidget - : public QWidget + class WheelEventWidget : public QWidget { using MouseInteractionResult = AzToolsFramework::ViewportInteraction::MouseInteractionResult; + public: WheelEventWidget(QWidget* parent = nullptr) : QWidget(parent) @@ -490,8 +464,7 @@ namespace UnitTest { EditorTransformComponentSelectionRequests::Mode transformMode; EditorTransformComponentSelectionRequestBus::EventResult( - transformMode, GetEntityContextId(), - &EditorTransformComponentSelectionRequestBus::Events::GetTransformMode); + transformMode, GetEntityContextId(), &EditorTransformComponentSelectionRequestBus::Events::GetTransformMode); return transformMode; }; @@ -519,6 +492,56 @@ namespace UnitTest EXPECT_THAT(wheelEventWidget.m_mouseInteractionResult, Eq(vi::MouseInteractionResult::Viewport)); } + TEST_F(EditorTransformComponentSelectionFixture, EntityPositionsCanBeSnappedToGrid) + { + using ::testing::Pointwise; + + m_entityIds.push_back(CreateDefaultEditorEntity("Entity2")); + m_entityIds.push_back(CreateDefaultEditorEntity("Entity3")); + + const AZStd::vector initialUnsnappedPositions = { AZ::Vector3(1.2f, 3.5f, 6.7f), AZ::Vector3(13.2f, 15.6f, 11.4f), + AZ::Vector3(4.2f, 103.2f, 16.6f) }; + AZ::TransformBus::Event(m_entityIds[0], &AZ::TransformBus::Events::SetWorldTranslation, initialUnsnappedPositions[0]); + AZ::TransformBus::Event(m_entityIds[1], &AZ::TransformBus::Events::SetWorldTranslation, initialUnsnappedPositions[1]); + AZ::TransformBus::Event(m_entityIds[2], &AZ::TransformBus::Events::SetWorldTranslation, initialUnsnappedPositions[2]); + + AzToolsFramework::SelectEntities(m_entityIds); + + EditorTransformComponentSelectionRequestBus::Event( + GetEntityContextId(), &EditorTransformComponentSelectionRequestBus::Events::SnapSelectedEntitiesToWorldGrid, 2.0f); + + AZStd::vector entityPositionsAfterSnap; + AZStd::transform( + m_entityIds.cbegin(), m_entityIds.cend(), AZStd::back_inserter(entityPositionsAfterSnap), + [](const AZ::EntityId& entityId) + { + return GetWorldTranslation(entityId); + }); + + const AZStd::vector expectedSnappedPositions = { AZ::Vector3(2.0f, 4.0f, 6.0f), AZ::Vector3(14.0f, 16.0f, 12.0f), + AZ::Vector3(4.0f, 104.0f, 16.0f) }; + EXPECT_THAT(entityPositionsAfterSnap, Pointwise(ContainerIsClose(), expectedSnappedPositions)); + } + + TEST_F(EditorTransformComponentSelectionFixture, ManipulatorStaysAlignedToEntityTranslationAfterSnap) + { + const auto initialUnsnappedPosition = AZ::Vector3(1.2f, 3.5f, 6.7f); + AZ::TransformBus::Event(m_entityIds[0], &AZ::TransformBus::Events::SetWorldTranslation, initialUnsnappedPosition); + + AzToolsFramework::SelectEntities(m_entityIds); + + EditorTransformComponentSelectionRequestBus::Event( + GetEntityContextId(), &EditorTransformComponentSelectionRequestBus::Events::SnapSelectedEntitiesToWorldGrid, 1.0f); + + const auto entityPositionAfterSnap = GetWorldTranslation(m_entity1); + const AZ::Vector3 manipulatorPositionAfterSnap = + GetManipulatorTransform().value_or(AZ::Transform::CreateIdentity()).GetTranslation(); + + const auto expectedSnappedPosition = AZ::Vector3(1.0f, 4.0f, 7.0f); + EXPECT_THAT(entityPositionAfterSnap, IsClose(expectedSnappedPosition)); + EXPECT_THAT(expectedSnappedPosition, IsClose(manipulatorPositionAfterSnap)); + } + // struct to contain input reference frame and expected orientation outcome based on // the reference frame, selection and entity hierarchy struct ReferenceFrameWithOrientation @@ -541,19 +564,20 @@ namespace UnitTest class EditorTransformComponentSelectionSingleEntityPivotFixture : public EditorTransformComponentSelectionFixture - , public ::testing::WithParamInterface {}; + , public ::testing::WithParamInterface + { + }; TEST_P(EditorTransformComponentSelectionSingleEntityPivotFixture, PivotOrientationMatchesReferenceFrameSingleEntity) { - using ETCS::PivotOrientationResult; using ETCS::CalculatePivotOrientation; + using ETCS::PivotOrientationResult; /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Given AZ::TransformBus::Event( m_entityIds[0], &AZ::TransformBus::Events::SetWorldTM, - AZ::Transform::CreateFromQuaternionAndTranslation( - ChildExpectedPivotLocalOrientationInWorldSpace, AZ::Vector3::CreateZero())); + AZ::Transform::CreateFromQuaternionAndTranslation(ChildExpectedPivotLocalOrientationInWorldSpace, AZ::Vector3::CreateZero())); /////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -574,20 +598,20 @@ namespace UnitTest All, EditorTransformComponentSelectionSingleEntityPivotFixture, testing::Values( - ReferenceFrameWithOrientation{ReferenceFrame::Local, ChildExpectedPivotLocalOrientationInWorldSpace}, - ReferenceFrameWithOrientation{ReferenceFrame::Parent, AZ::Quaternion::CreateIdentity()}, - ReferenceFrameWithOrientation{ReferenceFrame::World, AZ::Quaternion::CreateIdentity()})); + ReferenceFrameWithOrientation{ ReferenceFrame::Local, ChildExpectedPivotLocalOrientationInWorldSpace }, + ReferenceFrameWithOrientation{ ReferenceFrame::Parent, AZ::Quaternion::CreateIdentity() }, + ReferenceFrameWithOrientation{ ReferenceFrame::World, AZ::Quaternion::CreateIdentity() })); class EditorTransformComponentSelectionSingleEntityWithParentPivotFixture : public EditorTransformComponentSelectionFixture - , public ::testing::WithParamInterface {}; - - TEST_P( - EditorTransformComponentSelectionSingleEntityWithParentPivotFixture, - PivotOrientationMatchesReferenceFrameEntityWithParent) + , public ::testing::WithParamInterface + { + }; + + TEST_P(EditorTransformComponentSelectionSingleEntityWithParentPivotFixture, PivotOrientationMatchesReferenceFrameEntityWithParent) { - using ETCS::PivotOrientationResult; using ETCS::CalculatePivotOrientation; + using ETCS::PivotOrientationResult; /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Given @@ -596,8 +620,7 @@ namespace UnitTest AZ::TransformBus::Event( parentEntityId, &AZ::TransformBus::Events::SetWorldTM, - AZ::Transform::CreateFromQuaternionAndTranslation( - ParentExpectedPivotLocalOrientationInWorldSpace, AZ::Vector3::CreateZero())); + AZ::Transform::CreateFromQuaternionAndTranslation(ParentExpectedPivotLocalOrientationInWorldSpace, AZ::Vector3::CreateZero())); AZ::TransformBus::Event( m_entityIds[0], &AZ::TransformBus::Events::SetWorldTM, @@ -624,20 +647,20 @@ namespace UnitTest All, EditorTransformComponentSelectionSingleEntityWithParentPivotFixture, testing::Values( - ReferenceFrameWithOrientation{ReferenceFrame::Local, ChildExpectedPivotLocalOrientationInWorldSpace}, - ReferenceFrameWithOrientation{ReferenceFrame::Parent, ParentExpectedPivotLocalOrientationInWorldSpace}, - ReferenceFrameWithOrientation{ReferenceFrame::World, AZ::Quaternion::CreateIdentity()})); + ReferenceFrameWithOrientation{ ReferenceFrame::Local, ChildExpectedPivotLocalOrientationInWorldSpace }, + ReferenceFrameWithOrientation{ ReferenceFrame::Parent, ParentExpectedPivotLocalOrientationInWorldSpace }, + ReferenceFrameWithOrientation{ ReferenceFrame::World, AZ::Quaternion::CreateIdentity() })); class EditorTransformComponentSelectionMultipleEntitiesPivotFixture : public EditorTransformComponentSelectionFixture - , public ::testing::WithParamInterface {}; - - TEST_P( - EditorTransformComponentSelectionMultipleEntitiesPivotFixture, - PivotOrientationMatchesReferenceFrameMultipleEntities) + , public ::testing::WithParamInterface + { + }; + + TEST_P(EditorTransformComponentSelectionMultipleEntitiesPivotFixture, PivotOrientationMatchesReferenceFrameMultipleEntities) { - using ETCS::PivotOrientationResult; using ETCS::CalculatePivotOrientationForEntityIds; + using ETCS::PivotOrientationResult; /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Given @@ -646,23 +669,18 @@ namespace UnitTest // setup entities in arbitrary triangle arrangement AZ::TransformBus::Event( - m_entityIds[0], &AZ::TransformBus::Events::SetWorldTM, - AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisX(-10.0f))); + m_entityIds[0], &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisX(-10.0f))); AZ::TransformBus::Event( - m_entityIds[1], &AZ::TransformBus::Events::SetWorldTM, - AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisX(10.0f))); + m_entityIds[1], &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisX(10.0f))); AZ::TransformBus::Event( - m_entityIds[2], &AZ::TransformBus::Events::SetWorldTM, - AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisY(10.0f))); + m_entityIds[2], &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisY(10.0f))); // note: EntityIdManipulatorLookup{} is unused during this test - EntityIdManipulatorLookups lookups { - {m_entityIds[0], EntityIdManipulatorLookup{}}, - {m_entityIds[1], EntityIdManipulatorLookup{}}, - {m_entityIds[2], EntityIdManipulatorLookup{}} - }; + EntityIdManipulatorLookups lookups{ { m_entityIds[0], EntityIdManipulatorLookup{} }, + { m_entityIds[1], EntityIdManipulatorLookup{} }, + { m_entityIds[2], EntityIdManipulatorLookup{} } }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -691,14 +709,16 @@ namespace UnitTest class EditorTransformComponentSelectionMultipleEntitiesWithSameParentPivotFixture : public EditorTransformComponentSelectionFixture - , public ::testing::WithParamInterface {}; + , public ::testing::WithParamInterface + { + }; TEST_P( EditorTransformComponentSelectionMultipleEntitiesWithSameParentPivotFixture, PivotOrientationMatchesReferenceFrameMultipleEntitiesSameParent) { - using ETCS::PivotOrientationResult; using ETCS::CalculatePivotOrientationForEntityIds; + using ETCS::PivotOrientationResult; /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Given @@ -711,22 +731,18 @@ namespace UnitTest ParentExpectedPivotLocalOrientationInWorldSpace, AZ::Vector3::CreateAxisZ(-5.0f))); AZ::TransformBus::Event( - m_entityIds[1], &AZ::TransformBus::Events::SetWorldTM, - AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisX(10.0f))); + m_entityIds[1], &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisX(10.0f))); AZ::TransformBus::Event( - m_entityIds[2], &AZ::TransformBus::Events::SetWorldTM, - AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisY(10.0f))); + m_entityIds[2], &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisY(10.0f))); AZ::TransformBus::Event(m_entityIds[1], &AZ::TransformBus::Events::SetParent, m_entityIds[0]); AZ::TransformBus::Event(m_entityIds[2], &AZ::TransformBus::Events::SetParent, m_entityIds[0]); // note: EntityIdManipulatorLookup{} is unused during this test // only select second two entities that are children of m_entityIds[0] - EntityIdManipulatorLookups lookups{ - {m_entityIds[1], EntityIdManipulatorLookup{}}, - {m_entityIds[2], EntityIdManipulatorLookup{}} - }; + EntityIdManipulatorLookups lookups{ { m_entityIds[1], EntityIdManipulatorLookup{} }, + { m_entityIds[2], EntityIdManipulatorLookup{} } }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -755,14 +771,16 @@ namespace UnitTest class EditorTransformComponentSelectionMultipleEntitiesWithDifferentParentPivotFixture : public EditorTransformComponentSelectionFixture - , public ::testing::WithParamInterface {}; + , public ::testing::WithParamInterface + { + }; TEST_P( EditorTransformComponentSelectionMultipleEntitiesWithDifferentParentPivotFixture, PivotOrientationMatchesReferenceFrameMultipleEntitiesDifferentParent) { - using ETCS::PivotOrientationResult; using ETCS::CalculatePivotOrientationForEntityIds; + using ETCS::PivotOrientationResult; /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Given @@ -776,22 +794,18 @@ namespace UnitTest ParentExpectedPivotLocalOrientationInWorldSpace, AZ::Vector3::CreateAxisZ(-5.0f))); AZ::TransformBus::Event( - m_entityIds[1], &AZ::TransformBus::Events::SetWorldTM, - AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisX(10.0f))); + m_entityIds[1], &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisX(10.0f))); AZ::TransformBus::Event( - m_entityIds[2], &AZ::TransformBus::Events::SetWorldTM, - AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisY(10.0f))); + m_entityIds[2], &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisY(10.0f))); AZ::TransformBus::Event(m_entityIds[1], &AZ::TransformBus::Events::SetParent, m_entityIds[0]); AZ::TransformBus::Event(m_entityIds[2], &AZ::TransformBus::Events::SetParent, m_entityIds[3]); // note: EntityIdManipulatorLookup{} is unused during this test // only select second two entities that are children of different m_entities - EntityIdManipulatorLookups lookups{ - {m_entityIds[1], EntityIdManipulatorLookup{}}, - {m_entityIds[2], EntityIdManipulatorLookup{}} - }; + EntityIdManipulatorLookups lookups{ { m_entityIds[1], EntityIdManipulatorLookup{} }, + { m_entityIds[2], EntityIdManipulatorLookup{} } }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -819,30 +833,29 @@ namespace UnitTest class EditorTransformComponentSelectionSingleEntityPivotAndOverrideFixture : public EditorTransformComponentSelectionFixture - , public ::testing::WithParamInterface {}; + , public ::testing::WithParamInterface + { + }; TEST_P( EditorTransformComponentSelectionSingleEntityPivotAndOverrideFixture, PivotOrientationMatchesReferenceFrameSingleEntityOptionalOverride) { - using ETCS::PivotOrientationResult; using ETCS::CalculateSelectionPivotOrientation; + using ETCS::PivotOrientationResult; /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Given AZ::TransformBus::Event( m_entityIds[0], &AZ::TransformBus::Events::SetWorldTM, - AZ::Transform::CreateFromQuaternionAndTranslation( - ChildExpectedPivotLocalOrientationInWorldSpace, AZ::Vector3::CreateZero())); + AZ::Transform::CreateFromQuaternionAndTranslation(ChildExpectedPivotLocalOrientationInWorldSpace, AZ::Vector3::CreateZero())); /////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // When const ReferenceFrameWithOrientation referenceFrameWithOrientation = GetParam(); - EntityIdManipulatorLookups lookups{ - {m_entityIds[0], EntityIdManipulatorLookup{}} - }; + EntityIdManipulatorLookups lookups{ { m_entityIds[0], EntityIdManipulatorLookup{} } }; // set override frame (orientation only) OptionalFrame optionalFrame; @@ -870,14 +883,16 @@ namespace UnitTest class EditorTransformComponentSelectionMultipleEntitiesPivotAndOverrideFixture : public EditorTransformComponentSelectionFixture - , public ::testing::WithParamInterface {}; + , public ::testing::WithParamInterface + { + }; TEST_P( EditorTransformComponentSelectionMultipleEntitiesPivotAndOverrideFixture, PivotOrientationMatchesReferenceFrameMultipleEntitiesOptionalOverride) { - using ETCS::PivotOrientationResult; using ETCS::CalculateSelectionPivotOrientation; + using ETCS::PivotOrientationResult; /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Given @@ -885,23 +900,18 @@ namespace UnitTest m_entityIds.push_back(CreateDefaultEditorEntity("Entity3")); AZ::TransformBus::Event( - m_entityIds[0], &AZ::TransformBus::Events::SetWorldTM, - AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisX(-10.0f))); + m_entityIds[0], &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisX(-10.0f))); AZ::TransformBus::Event( - m_entityIds[1], &AZ::TransformBus::Events::SetWorldTM, - AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisX(10.0f))); + m_entityIds[1], &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisX(10.0f))); AZ::TransformBus::Event( - m_entityIds[2], &AZ::TransformBus::Events::SetWorldTM, - AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisY(10.0f))); + m_entityIds[2], &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisY(10.0f))); // note: EntityIdManipulatorLookup{} is unused during this test - EntityIdManipulatorLookups lookups{ - {m_entityIds[0], EntityIdManipulatorLookup{}}, - {m_entityIds[1], EntityIdManipulatorLookup{}}, - {m_entityIds[2], EntityIdManipulatorLookup{}} - }; + EntityIdManipulatorLookups lookups{ { m_entityIds[0], EntityIdManipulatorLookup{} }, + { m_entityIds[1], EntityIdManipulatorLookup{} }, + { m_entityIds[2], EntityIdManipulatorLookup{} } }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -932,14 +942,16 @@ namespace UnitTest class EditorTransformComponentSelectionMultipleEntitiesPivotAndNoOverrideFixture : public EditorTransformComponentSelectionFixture - , public ::testing::WithParamInterface {}; + , public ::testing::WithParamInterface + { + }; TEST_P( EditorTransformComponentSelectionMultipleEntitiesPivotAndNoOverrideFixture, PivotOrientationMatchesReferenceFrameMultipleEntitiesNoOptionalOverride) { - using ETCS::PivotOrientationResult; using ETCS::CalculateSelectionPivotOrientation; + using ETCS::PivotOrientationResult; /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Given @@ -947,23 +959,18 @@ namespace UnitTest m_entityIds.push_back(CreateDefaultEditorEntity("Entity3")); AZ::TransformBus::Event( - m_entityIds[0], &AZ::TransformBus::Events::SetWorldTM, - AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisX(-10.0f))); + m_entityIds[0], &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisX(-10.0f))); AZ::TransformBus::Event( - m_entityIds[1], &AZ::TransformBus::Events::SetWorldTM, - AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisX(10.0f))); + m_entityIds[1], &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisX(10.0f))); AZ::TransformBus::Event( - m_entityIds[2], &AZ::TransformBus::Events::SetWorldTM, - AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisY(10.0f))); + m_entityIds[2], &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisY(10.0f))); // note: EntityIdManipulatorLookup{} is unused during this test - EntityIdManipulatorLookups lookups{ - {m_entityIds[0], EntityIdManipulatorLookup{}}, - {m_entityIds[1], EntityIdManipulatorLookup{}}, - {m_entityIds[2], EntityIdManipulatorLookup{}} - }; + EntityIdManipulatorLookups lookups{ { m_entityIds[0], EntityIdManipulatorLookup{} }, + { m_entityIds[1], EntityIdManipulatorLookup{} }, + { m_entityIds[2], EntityIdManipulatorLookup{} } }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -992,14 +999,16 @@ namespace UnitTest class EditorTransformComponentSelectionMultipleEntitiesSameParentPivotAndNoOverrideFixture : public EditorTransformComponentSelectionFixture - , public ::testing::WithParamInterface {}; + , public ::testing::WithParamInterface + { + }; TEST_P( EditorTransformComponentSelectionMultipleEntitiesSameParentPivotAndNoOverrideFixture, PivotOrientationMatchesReferenceFrameMultipleEntitiesSameParentNoOptionalOverride) { - using ETCS::PivotOrientationResult; using ETCS::CalculateSelectionPivotOrientation; + using ETCS::PivotOrientationResult; /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Given @@ -1012,21 +1021,17 @@ namespace UnitTest ParentExpectedPivotLocalOrientationInWorldSpace, AZ::Vector3::CreateAxisZ(-5.0f))); AZ::TransformBus::Event( - m_entityIds[1], &AZ::TransformBus::Events::SetWorldTM, - AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisX(10.0f))); + m_entityIds[1], &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisX(10.0f))); AZ::TransformBus::Event( - m_entityIds[2], &AZ::TransformBus::Events::SetWorldTM, - AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisY(10.0f))); + m_entityIds[2], &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisY(10.0f))); AZ::TransformBus::Event(m_entityIds[1], &AZ::TransformBus::Events::SetParent, m_entityIds[0]); AZ::TransformBus::Event(m_entityIds[2], &AZ::TransformBus::Events::SetParent, m_entityIds[0]); // note: EntityIdManipulatorLookup{} is unused during this test - EntityIdManipulatorLookups lookups{ - {m_entityIds[1], EntityIdManipulatorLookup{}}, - {m_entityIds[2], EntityIdManipulatorLookup{}} - }; + EntityIdManipulatorLookups lookups{ { m_entityIds[1], EntityIdManipulatorLookup{} }, + { m_entityIds[2], EntityIdManipulatorLookup{} } }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1174,13 +1179,13 @@ namespace UnitTest AZ::TransformBus::Event(f, &AZ::TransformBus::Events::SetParent, secondLayerId); // Layer1 - // A - // B - // C - // Layer2 - // D - // E - // F + // A + // B + // C + // Layer2 + // D + // E + // F /////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1270,13 +1275,13 @@ namespace UnitTest AZ::TransformBus::Event(f, &AZ::TransformBus::Events::SetParent, secondLayerId); // Layer1 - // A - // B - // C - // Layer2 - // D - // E - // F + // A + // B + // C + // Layer2 + // D + // E + // F /////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1368,8 +1373,7 @@ namespace UnitTest EXPECT_TRUE(!IsEntityVisible(m_layerId)); bool flagSetVisible = false; - EditorVisibilityRequestBus::EventResult( - flagSetVisible, m_layerId, &EditorVisibilityRequestBus::Events::GetVisibilityFlag); + EditorVisibilityRequestBus::EventResult(flagSetVisible, m_layerId, &EditorVisibilityRequestBus::Events::GetVisibilityFlag); // even though a layer is set to not be visible, this is recorded by SetLayerChildrenVisibility // and AreLayerChildrenVisible - the visibility flag will not be modified and remains true @@ -1377,12 +1381,12 @@ namespace UnitTest /////////////////////////////////////////////////////////////////////////////////////////////////////////////// } - class EditorEntityInfoRequestActivateTestComponent - : public AzToolsFramework::Components::EditorComponentBase + class EditorEntityInfoRequestActivateTestComponent : public AzToolsFramework::Components::EditorComponentBase { public: AZ_EDITOR_COMPONENT( - EditorEntityInfoRequestActivateTestComponent, "{849DA1FC-6A0C-4CB8-A0BB-D90DEE7FF7F7}", + EditorEntityInfoRequestActivateTestComponent, + "{849DA1FC-6A0C-4CB8-A0BB-D90DEE7FF7F7}", AzToolsFramework::Components::EditorComponentBase); static void Reflect(AZ::ReflectContext* context); @@ -1391,13 +1395,13 @@ namespace UnitTest void Activate() override { // ensure we can successfully read IsVisible and IsLocked (bus will be connected to in entity Init) - EditorEntityInfoRequestBus::EventResult( - m_visible, GetEntityId(), &EditorEntityInfoRequestBus::Events::IsVisible); - EditorEntityInfoRequestBus::EventResult( - m_locked, GetEntityId(), &EditorEntityInfoRequestBus::Events::IsLocked); + EditorEntityInfoRequestBus::EventResult(m_visible, GetEntityId(), &EditorEntityInfoRequestBus::Events::IsVisible); + EditorEntityInfoRequestBus::EventResult(m_locked, GetEntityId(), &EditorEntityInfoRequestBus::Events::IsLocked); } - void Deactivate() override {} + void Deactivate() override + { + } bool m_visible = false; bool m_locked = true; @@ -1407,14 +1411,11 @@ namespace UnitTest { if (auto serializeContext = azrtti_cast(context)) { - serializeContext->Class() - ->Version(0) - ; + serializeContext->Class()->Version(0); } } - class EditorEntityModelEntityInfoRequestFixture - : public ToolsApplicationFixture + class EditorEntityModelEntityInfoRequestFixture : public ToolsApplicationFixture { public: void SetUpEditorFixtureImpl() override @@ -1435,8 +1436,7 @@ namespace UnitTest // This is necessary to prevent a warning in the undo system. AzToolsFramework::ToolsApplicationRequests::Bus::Broadcast( - &AzToolsFramework::ToolsApplicationRequests::Bus::Events::AddDirtyEntity, - entity->GetId()); + &AzToolsFramework::ToolsApplicationRequests::Bus::Events::AddDirtyEntity, entity->GetId()); /////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1469,8 +1469,7 @@ namespace UnitTest // This is necessary to prevent a warning in the undo system. AzToolsFramework::ToolsApplicationRequests::Bus::Broadcast( - &AzToolsFramework::ToolsApplicationRequests::Bus::Events::AddDirtyEntity, - entity->GetId()); + &AzToolsFramework::ToolsApplicationRequests::Bus::Events::AddDirtyEntity, entity->GetId()); /////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////// From 2f9a055a8fec46991f334526f9cb7140d5fe4ecc Mon Sep 17 00:00:00 2001 From: mnaumov Date: Wed, 16 Jun 2021 11:42:18 -0700 Subject: [PATCH 116/116] Fixing "type not registered with BehaviorContext" when running ASV --- .../DisplayMapperConfigurationDescriptor.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Gems/Atom/Feature/Common/Code/Source/DisplayMapper/DisplayMapperConfigurationDescriptor.cpp b/Gems/Atom/Feature/Common/Code/Source/DisplayMapper/DisplayMapperConfigurationDescriptor.cpp index a064b61a1a..ae48c7defb 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DisplayMapper/DisplayMapperConfigurationDescriptor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DisplayMapper/DisplayMapperConfigurationDescriptor.cpp @@ -50,6 +50,8 @@ namespace AZ if (auto behaviorContext = azrtti_cast(context)) { + behaviorContext->Class("OutputDeviceTransformType"); + behaviorContext->Class("AcesParameterOverrides") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Category, "render") @@ -58,6 +60,16 @@ namespace AZ ->Method("LoadPreset", &AcesParameterOverrides::LoadPreset) ->Property("overrideDefaults", BehaviorValueProperty(&AcesParameterOverrides::m_overrideDefaults)) ->Property("preset", BehaviorValueProperty(&AcesParameterOverrides::m_preset)) + ->Enum(OutputDeviceTransformType::NumOutputDeviceTransformTypes)>( + "OutputDeviceTransformType_NumOutputDeviceTransformTypes") + ->Enum(OutputDeviceTransformType::OutputDeviceTransformType_48Nits)>( + "OutputDeviceTransformType_48Nits") + ->Enum(OutputDeviceTransformType::OutputDeviceTransformType_1000Nits)>( + "OutputDeviceTransformType_1000Nits") + ->Enum(OutputDeviceTransformType::OutputDeviceTransformType_2000Nits)>( + "OutputDeviceTransformType_2000Nits") + ->Enum(OutputDeviceTransformType::OutputDeviceTransformType_4000Nits)>( + "OutputDeviceTransformType_4000Nits") ->Property("alterSurround", BehaviorValueProperty(&AcesParameterOverrides::m_alterSurround)) ->Property("applyDesaturation", BehaviorValueProperty(&AcesParameterOverrides::m_applyDesaturation)) ->Property("applyCATD60toD65", BehaviorValueProperty(&AcesParameterOverrides::m_applyCATD60toD65))