/* * 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 "stdafx.h" #include "FindEntityWidget.h" #include "FindEntityItemModel.h" #include "FindEntitySortFilterProxyModel.h" #include #include #include #include #include #include #include #include #include Q_DECLARE_METATYPE(AZ::Uuid); namespace { bool AppearsInUiComponentMenu(const AZ::SerializeContext::ClassData& classData) { return AzToolsFramework::AppearsInAddComponentMenu(classData, AZ_CRC("UI", 0x27ff46b0)); } } FindEntityWidget::FindEntityWidget(AZ::EntityId canvasEntityId, QWidget* pParent, Qt::WindowFlags flags) : QWidget(pParent, flags) { SetupUI(); m_objectTree->setSelectionMode(QAbstractItemView::ExtendedSelection); m_objectTree->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_objectTree->setAutoScrollMargin(20); m_objectTree->setUniformRowHeights(true); m_objectTree->setHeaderHidden(true); m_listModel = aznew FindEntityItemModel(this); m_proxyModel = aznew FindEntitySortFilterProxyModel(this); m_proxyModel->setSourceModel(m_listModel); m_objectTree->setModel(m_proxyModel); AZ::SerializeContext* serializeContext = nullptr; EBUS_EVENT_RESULT(serializeContext, AZ::ComponentApplicationBus, GetSerializeContext); if (serializeContext) { // Make a list of all components that are currently used in the canvas AZStd::unordered_set usedComponents; GetUsedComponents(canvasEntityId, usedComponents); AzToolsFramework::ComponentPaletteUtil::ComponentDataTable componentDataTable; AzToolsFramework::ComponentPaletteUtil::ComponentIconTable componentIconTable; AZStd::vector serviceFilter; AzToolsFramework::ComponentPaletteUtil::BuildComponentTables(serializeContext, AppearsInUiComponentMenu, serviceFilter, componentDataTable, componentIconTable); for (const auto& categoryPair : componentDataTable) { const auto& componentMap = categoryPair.second; for (const auto& componentPair : componentMap) { auto iter = usedComponents.find(componentPair.second->m_typeId); if (iter != usedComponents.end()) { usedComponents.erase(iter); m_searchWidget->AddTypeFilter(categoryPair.first, componentPair.first, QVariant::fromValue(componentPair.second->m_typeId)); } } } } connect(m_objectTree->selectionModel(), &QItemSelectionModel::selectionChanged, this, &FindEntityWidget::OnSelectionChanged); connect(m_objectTree, &QTreeView::doubleClicked, this, &FindEntityWidget::OnItemDblClick); connect(m_searchWidget, &AzQtComponents::FilteredSearchWidget::TextFilterChanged, this, &FindEntityWidget::OnSearchTextChanged); connect(m_searchWidget, &AzQtComponents::FilteredSearchWidget::TypeFilterChanged, this, &FindEntityWidget::OnFilterChanged); connect(m_selectButton, &QPushButton::clicked, this, &FindEntityWidget::OnSelectClicked); connect(m_cancelButton, &QPushButton::clicked, this, &FindEntityWidget::OnCancelClicked); m_listModel->Initialize(canvasEntityId); m_objectTree->expandAll(); // Select button starts off disabled and becomes enabled when there is a selection m_selectButton->setEnabled(false); } FindEntityWidget::~FindEntityWidget() { delete m_listModel; delete m_proxyModel; } AZ::EntityId FindEntityWidget::GetEntityIdFromIndex(const QModelIndex& index) const { if (index.isValid()) { const QModelIndex modelIndex = m_proxyModel->mapToSource(index); if (modelIndex.isValid()) { return m_listModel->GetEntityFromIndex(modelIndex); } } return AZ::EntityId(); } QModelIndex FindEntityWidget::GetIndexFromEntityId(const AZ::EntityId& entityId) const { if (entityId.IsValid()) { QModelIndex modelIndex = m_listModel->GetIndexFromEntity(entityId); if (modelIndex.isValid()) { return m_proxyModel->mapFromSource(modelIndex); } } return QModelIndex(); } void FindEntityWidget::SetupUI() { QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); sizePolicy.setHorizontalStretch(0); sizePolicy.setVerticalStretch(0); setSizePolicy(sizePolicy); QVBoxLayout* verticalLayout = new QVBoxLayout(this); verticalLayout->setSizeConstraint(QLayout::SetMinimumSize); QHBoxLayout* horizontalLayoutSearch = new QHBoxLayout(); horizontalLayoutSearch->setSpacing(0); m_searchWidget = new AzQtComponents::FilteredSearchWidget(this); horizontalLayoutSearch->addWidget(m_searchWidget); verticalLayout->addLayout(horizontalLayoutSearch); QScrollArea* objectList = new QScrollArea(this); objectList->setFocusPolicy(Qt::ClickFocus); objectList->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents); objectList->setWidgetResizable(true); QWidget* objectListContents = new QWidget(); QVBoxLayout* verticalLayoutObjectListContents = new QVBoxLayout(objectListContents); verticalLayoutObjectListContents->setSpacing(0); verticalLayoutObjectListContents->setContentsMargins(0, 0, 0, 0); m_objectTree = new QTreeView(objectListContents); verticalLayoutObjectListContents->addWidget(m_objectTree); objectList->setWidget(objectListContents); verticalLayout->addWidget(objectList); QDialogButtonBox* buttonBox = new QDialogButtonBox(this); m_selectButton = new QPushButton(tr("Select in Hierarchy")); m_selectButton->setToolTip(tr("Select the selected elements in the Hierarchy.")); m_selectButton->setDefault(true); m_selectButton->setAutoDefault(true); m_selectButton->setProperty("class", "Primary"); m_cancelButton = new QPushButton(tr("Cancel")); m_cancelButton->setDefault(false); m_cancelButton->setAutoDefault(false); buttonBox->addButton(m_selectButton, QDialogButtonBox::ApplyRole); buttonBox->addButton(m_cancelButton, QDialogButtonBox::RejectRole); verticalLayout->addWidget(buttonBox, 1); } void FindEntityWidget::GetUsedComponents(AZ::EntityId canvasEntityId, AZStd::unordered_set& usedComponents) { LyShine::EntityArray entities; EBUS_EVENT_ID(canvasEntityId, UiCanvasBus, FindElements, [](const AZ::Entity* entity) { return true; }, entities); for (AZ::Entity* entity : entities) { for (AZ::Component* component : entity->GetComponents()) { const AZ::Uuid& componentType = azrtti_typeid(component); usedComponents.insert(componentType); } } } void FindEntityWidget::OnSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected) { // Update select button state m_selectButton->setEnabled(!selected.isEmpty()); } void FindEntityWidget::OnItemDblClick(const QModelIndex& index) { OnSelectClicked(); } void FindEntityWidget::OnSearchTextChanged(const QString& activeTextFilter) { AZStd::string filterString = activeTextFilter.toUtf8().data(); m_listModel->SearchStringChanged(filterString); m_proxyModel->UpdateFilter(); m_objectTree->expandAll(); } void FindEntityWidget::OnFilterChanged(const AzQtComponents::SearchTypeFilterList& activeTypeFilters) { AZStd::vector componentFilters; componentFilters.reserve(activeTypeFilters.count()); for (auto filter : activeTypeFilters) { AZ::Uuid typeId = qvariant_cast(filter.metadata); componentFilters.push_back(typeId); } m_listModel->SearchFilterChanged(componentFilters); m_proxyModel->UpdateFilter(); m_objectTree->expandAll(); } void FindEntityWidget::OnSelectClicked() { AZStd::vector selectedEntities; QModelIndexList selectedIndexes = m_objectTree->selectionModel()->selectedIndexes(); for (const QModelIndex& index : selectedIndexes) { const AZ::EntityId entityId = GetEntityIdFromIndex(index); if (entityId.IsValid()) { selectedEntities.push_back(entityId); } } emit OnFinished(selectedEntities); } void FindEntityWidget::OnCancelClicked() { emit OnCanceled(); } #include