/* * 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. * */ // Original file Copyright Crytek GMBH or its affiliates, used under license. #include #include #include #include #include #include #include #include #include #include #include #include namespace AudioControls { //-------------------------------------------------------------------------------------------// ATLControlsDialog::ATLControlsDialog(QWidget* pParent, EACEControlType eType) : QDialog(pParent) , m_eType(eType) { setWindowTitle(GetWindowTitle(m_eType)); setWindowModality(Qt::ApplicationModal); QBoxLayout* pLayout = new QBoxLayout(QBoxLayout::TopToBottom); setLayout(pLayout); m_TextFilterLineEdit = new QLineEdit(this); m_TextFilterLineEdit->setAlignment(Qt::AlignLeading | Qt::AlignLeft | Qt::AlignVCenter); m_TextFilterLineEdit->setPlaceholderText(QApplication::translate("ATLControlsPanel", "Search", 0)); connect(m_TextFilterLineEdit, &QLineEdit::textChanged, this, &ATLControlsDialog::SetTextFilter); connect(m_TextFilterLineEdit, &QLineEdit::returnPressed, this, &ATLControlsDialog::EnterPressed); pLayout->addWidget(m_TextFilterLineEdit, 0); m_pControlTree = new QAudioControlsTreeView(this); m_pControlTree->header()->setVisible(false); m_pControlTree->setEnabled(true); m_pControlTree->setAutoScroll(true); m_pControlTree->setDragEnabled(false); m_pControlTree->setDragDropMode(QAbstractItemView::NoDragDrop); m_pControlTree->setDefaultDropAction(Qt::IgnoreAction); m_pControlTree->setAlternatingRowColors(false); m_pControlTree->setSelectionMode(QAbstractItemView::SingleSelection); m_pControlTree->setRootIsDecorated(true); m_pControlTree->setSortingEnabled(true); m_pControlTree->setAnimated(false); m_pControlTree->setEditTriggers(QAbstractItemView::NoEditTriggers); pLayout->addWidget(m_pControlTree, 0); m_pATLModel = CAudioControlsEditorPlugin::GetATLModel(); m_pTreeModel = CAudioControlsEditorPlugin::GetControlsTree(); m_pProxyModel = new QAudioControlSortProxy(this); m_pProxyModel->setSourceModel(m_pTreeModel); m_pControlTree->setModel(m_pProxyModel); pDialogButtons = new QDialogButtonBox(this); pDialogButtons->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); connect(pDialogButtons, SIGNAL(accepted()), this, SLOT(accept())); connect(pDialogButtons, SIGNAL(rejected()), this, SLOT(reject())); pLayout->addWidget(pDialogButtons, 0); connect(m_pControlTree->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), this, SLOT(UpdateSelectedControl())); ApplyFilter(); UpdateSelectedControl(); m_pControlTree->setFocus(); m_pControlTree->installEventFilter(this); m_pControlTree->viewport()->installEventFilter(this); m_TextFilterLineEdit->installEventFilter(this); connect(m_pControlTree->selectionModel(), SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), this, SLOT(StopTrigger())); } //-------------------------------------------------------------------------------------------// ATLControlsDialog::~ATLControlsDialog() { StopTrigger(); } //-------------------------------------------------------------------------------------------// const char* ATLControlsDialog::ChooseItem(const char* currentValue) { m_sControlName = currentValue; if (m_pTreeModel && m_pProxyModel && !m_sControlName.empty()) { QModelIndex index = FindItem(m_sControlName); if (index.isValid()) { m_pControlTree->setCurrentIndex(index); } } if (exec() == QDialog::Accepted) { return m_sControlName.c_str(); } return currentValue; } //-------------------------------------------------------------------------------------------// void ATLControlsDialog::UpdateSelectedControl() { m_sControlName.clear(); if (m_pATLModel) { QModelIndexList indexes = m_pControlTree->selectionModel()->selectedIndexes(); if (!indexes.empty()) { const CATLControl* control = GetControlFromModelIndex(indexes[0]); if (control && IsCriteriaMatch(control)) { m_sControlName = control->GetName(); } } } if (QPushButton* pButton = pDialogButtons->button(QDialogButtonBox::Ok)) { pButton->setEnabled(!m_sControlName.empty()); } } //-------------------------------------------------------------------------------------------// void ATLControlsDialog::SetTextFilter(QString filter) { m_sFilter = filter; ApplyFilter(); } //-------------------------------------------------------------------------------------------// void ATLControlsDialog::EnterPressed() { m_sFilter = m_TextFilterLineEdit->text(); ApplyFilter(); m_pControlTree->setFocus(); } //-------------------------------------------------------------------------------------------// void ATLControlsDialog::ApplyFilter() { QModelIndex index = m_pProxyModel->index(0, 0); for (int i = 0; index.isValid(); ++i) { ApplyFilter(index); index = index.sibling(i, 0); } if (!m_sFilter.isEmpty()) { m_pControlTree->expandAll(); } } //-------------------------------------------------------------------------------------------// bool ATLControlsDialog::ApplyFilter(const QModelIndex parent) { if (parent.isValid()) { bool bChildValid = false; bool bHasChildren = false; QModelIndex child = parent.model()->index(0, 0, parent); for (int i = 1; child.isValid(); ++i) { bHasChildren = true; if (ApplyFilter(child)) { bChildValid = true; } child = parent.model()->index(i, 0, parent); } if (bChildValid || IsValid(parent)) { m_pControlTree->setRowHidden(parent.row(), parent.parent(), false); return true; } else { m_pControlTree->setRowHidden(parent.row(), parent.parent(), true); } } return false; } //-------------------------------------------------------------------------------------------// bool ATLControlsDialog::IsValid(const QModelIndex index) { const QString sName = index.data(Qt::DisplayRole).toString(); if (m_sFilter.isEmpty() || sName.contains(m_sFilter, Qt::CaseInsensitive)) { if (index.data(eDR_TYPE) == eIT_AUDIO_CONTROL) { return IsCriteriaMatch(GetControlFromModelIndex(index)); } } return false; } //-------------------------------------------------------------------------------------------// bool ATLControlsDialog::IsCriteriaMatch(const CATLControl* control) const { if (control) { AZStd::string sControlScope = control->GetScope(); if (control->GetType() == m_eType && (sControlScope.empty() || AZ::StringFunc::Equal(sControlScope.c_str(), m_sScope.c_str()))) { // LY-22029 - Only allow selecting Preload controls that are non-AutoLoad. // This change applies everywhere, to all Preload selectors, so if there's ever a need to select preloads // that are AutoLoad, then that option would need to be introduced to the resource selectors. // Note, there are no validation mechanisms in place if a user selects a preload, then later switches // it to be AutoLoad in the ACEditor. Any property containing that preload wouldn't know about it. // Fortunately, attempting to load one that's already been loaded won't double-dip. if (m_eType == eACET_PRELOAD && control->IsAutoLoad()) { return false; } return true; } } return false; } //-------------------------------------------------------------------------------------------// const CATLControl* ATLControlsDialog::GetControlFromModelIndex(const QModelIndex index) const { CID controlId = index.isValid() ? index.data(eDR_ID).toUInt() : ACE_INVALID_CID; if (controlId != ACE_INVALID_CID) { return m_pATLModel->GetControlByID(controlId); } return nullptr; } //-------------------------------------------------------------------------------------------// QString ATLControlsDialog::GetWindowTitle(EACEControlType type) const { switch (type) { case eACET_TRIGGER: return QString(tr("Choose Trigger...")); case eACET_RTPC: return QString(tr("Choose Rtpc...")); case eACET_SWITCH: return QString(tr("Choose Switch...")); case eACET_SWITCH_STATE: return QString(tr("Choose Switch State...")); case eACET_ENVIRONMENT: return QString(tr("Choose Environment...")); case eACET_PRELOAD: return QString(tr("Choose Preload...")); default: return QString(tr("Choose...")); } } //-------------------------------------------------------------------------------------------// QSize ATLControlsDialog::sizeHint() const { return QSize(400, 900); } //-------------------------------------------------------------------------------------------// void ATLControlsDialog::SetScope(const AZStd::string& sScope) { m_sScope = sScope; ApplyFilter(); } //-------------------------------------------------------------------------------------------// QModelIndex ATLControlsDialog::FindItem(const AZStd::string_view sControlName) { if (m_pTreeModel && m_pATLModel) { QModelIndexList indexes = m_pTreeModel->match(m_pTreeModel->index(0, 0, QModelIndex()), Qt::DisplayRole, QString(sControlName.data()), -1, Qt::MatchRecursive); if (!indexes.empty()) { const int size = indexes.size(); for (int i = 0; i < size; ++i) { QModelIndex index = indexes[i]; if (index.isValid() && (index.data(eDR_TYPE) == eIT_AUDIO_CONTROL)) { if (IsCriteriaMatch(GetControlFromModelIndex(index))) { return m_pProxyModel->mapFromSource(index); } } } } } return QModelIndex(); } //-------------------------------------------------------------------------------------------// bool ATLControlsDialog::eventFilter(QObject* pObject, QEvent* pEvent) { if (pEvent->type() == QEvent::FocusIn && pObject == m_TextFilterLineEdit) { // Clear the selection when moving to the line edit, so that the enter key does not select the item. m_pControlTree->clearSelection(); UpdateSelectedControl(); } if (pEvent->type() == QEvent::KeyRelease) { QKeyEvent* pKeyEvent = static_cast(pEvent); if (pKeyEvent && pKeyEvent->key() == Qt::Key_Space) { QModelIndex index = m_pControlTree->currentIndex(); if (index.isValid() && index.data(eDR_TYPE) == eIT_AUDIO_CONTROL) { CAudioControlsEditorPlugin::ExecuteTrigger(index.data(Qt::DisplayRole).toString().toUtf8().data()); } } } // double-clicking an item will accept it when valid (not a folder, wrong type)... if (pEvent->type() == QEvent::MouseButtonDblClick) { QMouseEvent* pMouseEvent = static_cast(pEvent); if (pMouseEvent && pMouseEvent->button() == Qt::LeftButton) { QModelIndex index = m_pControlTree->currentIndex(); if (index.isValid() && IsValid(index) && index.data(eDR_TYPE) != eIT_FOLDER) { accept(); } } } return QWidget::eventFilter(pObject, pEvent); } //-------------------------------------------------------------------------------------------// void ATLControlsDialog::showEvent(QShowEvent* e) { QDialog::showEvent(e); // When EditorProxyStyle inserted a WindowDecorationWrapper parent, it resized the dialog very small for some reason, so we resize it back here. window()->resize(sizeHint()); } //-------------------------------------------------------------------------------------------// void ATLControlsDialog::StopTrigger() { CAudioControlsEditorPlugin::StopTriggerExecution(); } } // namespace AudioControls #include