Merge pull request #3381 from aws-lumberyard-dev/Atom/guthadam/atomtools_document_main_window_base_class
AtomTools: moved remaining document and window common code from ME and SMC to base class
This commit is contained in:
+90
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h>
|
||||
#include <AtomToolsFramework/Window/AtomToolsMainWindow.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzQtComponents/Components/Widgets/TabWidget.h>
|
||||
#endif
|
||||
|
||||
namespace AtomToolsFramework
|
||||
{
|
||||
//! AtomToolsDocumentMainWindow
|
||||
class AtomToolsDocumentMainWindow
|
||||
: public AtomToolsMainWindow
|
||||
, private AtomToolsDocumentNotificationBus::Handler
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(AtomToolsDocumentMainWindow, AZ::SystemAllocator, 0);
|
||||
|
||||
using Base = AtomToolsMainWindow;
|
||||
|
||||
AtomToolsDocumentMainWindow(QWidget* parent = 0);
|
||||
~AtomToolsDocumentMainWindow();
|
||||
|
||||
protected:
|
||||
void AddDocumentMenus();
|
||||
void AddDocumentTabBar();
|
||||
|
||||
QString GetDocumentPath(const AZ::Uuid& documentId) const;
|
||||
|
||||
AZ::Uuid GetDocumentTabId(const int tabIndex) const;
|
||||
|
||||
void AddDocumentTab(
|
||||
const AZ::Uuid& documentId,
|
||||
const AZStd::string& label,
|
||||
const AZStd::string& toolTip);
|
||||
|
||||
void RemoveDocumentTab(const AZ::Uuid& documentId);
|
||||
|
||||
void UpdateDocumentTab(
|
||||
const AZ::Uuid& documentId, const AZStd::string& label, const AZStd::string& toolTip, bool isModified);
|
||||
|
||||
void SelectPrevDocumentTab();
|
||||
void SelectNextDocumentTab();
|
||||
|
||||
virtual QWidget* CreateDocumentTabView(const AZ::Uuid& documentId);
|
||||
virtual void OpenDocumentTabContextMenu();
|
||||
virtual bool GetCreateDocumentParams(AZStd::string& openPath, AZStd::string& savePath);
|
||||
virtual bool GetOpenDocumentParams(AZStd::string& openPath);
|
||||
|
||||
// AtomToolsDocumentNotificationBus::Handler overrides...
|
||||
void OnDocumentOpened(const AZ::Uuid& documentId) override;
|
||||
void OnDocumentClosed(const AZ::Uuid& documentId) override;
|
||||
void OnDocumentModified(const AZ::Uuid& documentId) override;
|
||||
void OnDocumentUndoStateChanged(const AZ::Uuid& documentId) override;
|
||||
void OnDocumentSaved(const AZ::Uuid& documentId) override;
|
||||
|
||||
void closeEvent(QCloseEvent* closeEvent) override;
|
||||
|
||||
template<typename Functor>
|
||||
QAction* CreateAction(const QString& text, Functor functor, const QKeySequence& shortcut = 0);
|
||||
|
||||
QAction* m_actionNew = {};
|
||||
QAction* m_actionOpen = {};
|
||||
QAction* m_actionClose = {};
|
||||
QAction* m_actionCloseAll = {};
|
||||
QAction* m_actionCloseOthers = {};
|
||||
QAction* m_actionSave = {};
|
||||
QAction* m_actionSaveAsCopy = {};
|
||||
QAction* m_actionSaveAsChild = {};
|
||||
QAction* m_actionSaveAll = {};
|
||||
|
||||
QAction* m_actionUndo = {};
|
||||
QAction* m_actionRedo = {};
|
||||
|
||||
QAction* m_actionNextTab = {};
|
||||
QAction* m_actionPreviousTab = {};
|
||||
|
||||
AzQtComponents::TabWidget* m_tabWidget = {};
|
||||
};
|
||||
} // namespace AtomToolsFramework
|
||||
+16
-22
@@ -7,18 +7,14 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h>
|
||||
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
|
||||
#include <AzQtComponents/Components/DockMainWindow.h>
|
||||
#include <AzQtComponents/Components/FancyDocking.h>
|
||||
#include <AzQtComponents/Components/StyledDockWidget.h>
|
||||
#include <AzQtComponents/Components/Widgets/TabWidget.h>
|
||||
|
||||
#include <QLabel>
|
||||
#include <QMenuBar>
|
||||
#include <QToolBar>
|
||||
|
||||
namespace AtomToolsFramework
|
||||
{
|
||||
@@ -38,28 +34,26 @@ namespace AtomToolsFramework
|
||||
bool IsDockWidgetVisible(const AZStd::string& name) const override;
|
||||
AZStd::vector<AZStd::string> GetDockWidgetNames() const override;
|
||||
|
||||
virtual void CreateMenu();
|
||||
virtual void CreateTabBar();
|
||||
|
||||
virtual void AddTabForDocumentId(
|
||||
const AZ::Uuid& documentId, const AZStd::string& label, const AZStd::string& toolTip, AZStd::function<QWidget*()> widgetCreator);
|
||||
virtual void RemoveTabForDocumentId(const AZ::Uuid& documentId);
|
||||
virtual void UpdateTabForDocumentId(
|
||||
const AZ::Uuid& documentId, const AZStd::string& label, const AZStd::string& toolTip, bool isModified);
|
||||
virtual AZ::Uuid GetDocumentIdFromTab(const int tabIndex) const;
|
||||
|
||||
virtual void OpenTabContextMenu();
|
||||
virtual void SelectPreviousTab();
|
||||
virtual void SelectNextTab();
|
||||
|
||||
void SetStatusMessage(const QString& message);
|
||||
void SetStatusWarning(const QString& message);
|
||||
void SetStatusError(const QString& message);
|
||||
|
||||
AzQtComponents::FancyDocking* m_advancedDockManager = nullptr;
|
||||
AzQtComponents::TabWidget* m_tabWidget = nullptr;
|
||||
QLabel* m_statusMessage = nullptr;
|
||||
void AddCommonMenus();
|
||||
|
||||
virtual void OpenSettings();
|
||||
virtual void OpenHelp();
|
||||
virtual void OpenAbout();
|
||||
|
||||
AzQtComponents::FancyDocking* m_advancedDockManager = {};
|
||||
|
||||
QLabel* m_statusMessage = {};
|
||||
|
||||
QMenu* m_menuFile = {};
|
||||
QMenu* m_menuEdit = {};
|
||||
QMenu* m_menuView = {};
|
||||
QMenu* m_menuHelp = {};
|
||||
|
||||
AZStd::unordered_map<AZStd::string, AzQtComponents::StyledDockWidget*> m_dockWidgets;
|
||||
AZStd::unordered_map<AZStd::string, QAction*> m_dockActions;
|
||||
};
|
||||
} // namespace AtomToolsFramework
|
||||
|
||||
+493
@@ -0,0 +1,493 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AtomToolsFramework/Document/AtomToolsDocumentMainWindow.h>
|
||||
#include <AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h>
|
||||
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
|
||||
#include <AtomToolsFramework/Util/Util.h>
|
||||
#include <AtomToolsFramework/Window/AtomToolsMainWindowNotificationBus.h>
|
||||
#include <AzFramework/StringFunc/StringFunc.h>
|
||||
|
||||
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
|
||||
#include <QApplication>
|
||||
#include <QByteArray>
|
||||
#include <QCloseEvent>
|
||||
#include <QLayout>
|
||||
#include <QMenu>
|
||||
#include <QMenuBar>
|
||||
#include <QWindow>
|
||||
AZ_POP_DISABLE_WARNING
|
||||
|
||||
namespace AtomToolsFramework
|
||||
{
|
||||
AtomToolsDocumentMainWindow::AtomToolsDocumentMainWindow(QWidget* parent /* = 0 */)
|
||||
: AtomToolsMainWindow(parent)
|
||||
{
|
||||
setObjectName("AtomToolsDocumentMainWindow");
|
||||
AddDocumentMenus();
|
||||
AddDocumentTabBar();
|
||||
AtomToolsDocumentNotificationBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
AtomToolsDocumentMainWindow::~AtomToolsDocumentMainWindow()
|
||||
{
|
||||
AtomToolsDocumentNotificationBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void AtomToolsDocumentMainWindow::AddDocumentMenus()
|
||||
{
|
||||
QAction* insertPostion = !m_menuFile->actions().empty() ? m_menuFile->actions().front() : nullptr;
|
||||
|
||||
// Generating the main menu manually because it's easier and we will have some dynamic or data driven entries
|
||||
m_actionNew = CreateAction("&New...", [this]() {
|
||||
AZStd::string openPath;
|
||||
AZStd::string savePath;
|
||||
if (GetCreateDocumentParams(openPath, savePath))
|
||||
{
|
||||
AtomToolsDocumentSystemRequestBus::Broadcast(
|
||||
&AtomToolsDocumentSystemRequestBus::Events::CreateDocumentFromFile, openPath, savePath);
|
||||
}
|
||||
}, QKeySequence::New);
|
||||
m_menuFile->insertAction(insertPostion, m_actionNew);
|
||||
|
||||
m_actionOpen = CreateAction("&Open...", [this]() {
|
||||
AZStd::string openPath;
|
||||
if (GetOpenDocumentParams(openPath))
|
||||
{
|
||||
AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::OpenDocument, openPath);
|
||||
}
|
||||
}, QKeySequence::Open);
|
||||
m_menuFile->insertAction(insertPostion, m_actionOpen);
|
||||
m_menuFile->insertSeparator(insertPostion);
|
||||
|
||||
m_actionSave = CreateAction("&Save", [this]() {
|
||||
const AZ::Uuid documentId = GetDocumentTabId(m_tabWidget->currentIndex());
|
||||
bool result = false;
|
||||
AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsDocumentSystemRequestBus::Events::SaveDocument, documentId);
|
||||
if (!result)
|
||||
{
|
||||
SetStatusError(tr("Document save failed: %1").arg(GetDocumentPath(documentId)));
|
||||
}
|
||||
}, QKeySequence::Save);
|
||||
m_menuFile->insertAction(insertPostion, m_actionSave);
|
||||
|
||||
m_actionSaveAsCopy = CreateAction("Save &As...", [this]() {
|
||||
const AZ::Uuid documentId = GetDocumentTabId(m_tabWidget->currentIndex());
|
||||
const QString documentPath = GetDocumentPath(documentId);
|
||||
|
||||
bool result = false;
|
||||
AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsDocumentSystemRequestBus::Events::SaveDocumentAsCopy,
|
||||
documentId, GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData());
|
||||
if (!result)
|
||||
{
|
||||
SetStatusError(tr("Document save failed: %1").arg(GetDocumentPath(documentId)));
|
||||
}
|
||||
}, QKeySequence::SaveAs);
|
||||
m_menuFile->insertAction(insertPostion, m_actionSaveAsCopy);
|
||||
|
||||
m_actionSaveAsChild = CreateAction("Save As &Child...", [this]() {
|
||||
const AZ::Uuid documentId = GetDocumentTabId(m_tabWidget->currentIndex());
|
||||
const QString documentPath = GetDocumentPath(documentId);
|
||||
|
||||
bool result = false;
|
||||
AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsDocumentSystemRequestBus::Events::SaveDocumentAsChild,
|
||||
documentId, GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData());
|
||||
if (!result)
|
||||
{
|
||||
SetStatusError(tr("Document save failed: %1").arg(GetDocumentPath(documentId)));
|
||||
}
|
||||
});
|
||||
m_menuFile->insertAction(insertPostion, m_actionSaveAsChild);
|
||||
|
||||
m_actionSaveAll = CreateAction("Save A&ll", [this]() {
|
||||
bool result = false;
|
||||
AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsDocumentSystemRequestBus::Events::SaveAllDocuments);
|
||||
if (!result)
|
||||
{
|
||||
SetStatusError(tr("Document save all failed"));
|
||||
}
|
||||
});
|
||||
m_menuFile->insertAction(insertPostion, m_actionSaveAll);
|
||||
m_menuFile->insertSeparator(insertPostion);
|
||||
|
||||
m_actionClose = CreateAction("&Close", [this]() {
|
||||
const AZ::Uuid documentId = GetDocumentTabId(m_tabWidget->currentIndex());
|
||||
AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId);
|
||||
}, QKeySequence::Close);
|
||||
m_menuFile->insertAction(insertPostion, m_actionClose);
|
||||
|
||||
m_actionCloseAll = CreateAction("Close All", [this]() {
|
||||
AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::CloseAllDocuments);
|
||||
});
|
||||
m_menuFile->insertAction(insertPostion, m_actionCloseAll);
|
||||
|
||||
m_actionCloseOthers = CreateAction("Close Others", [this]() {
|
||||
const AZ::Uuid documentId = GetDocumentTabId(m_tabWidget->currentIndex());
|
||||
AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId);
|
||||
});
|
||||
m_menuFile->insertAction(insertPostion, m_actionCloseOthers);
|
||||
m_menuFile->insertSeparator(insertPostion);
|
||||
|
||||
insertPostion = !m_menuEdit->actions().empty() ? m_menuEdit->actions().front() : nullptr;
|
||||
|
||||
m_actionUndo = CreateAction("&Undo", [this]() {
|
||||
const AZ::Uuid documentId = GetDocumentTabId(m_tabWidget->currentIndex());
|
||||
bool result = false;
|
||||
AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsDocumentRequestBus::Events::Undo);
|
||||
if (!result)
|
||||
{
|
||||
SetStatusError(tr("Document undo failed: %1").arg(GetDocumentPath(documentId)));
|
||||
}
|
||||
}, QKeySequence::Undo);
|
||||
m_menuEdit->insertAction(insertPostion, m_actionUndo);
|
||||
|
||||
m_actionRedo = CreateAction("&Redo", [this]() {
|
||||
const AZ::Uuid documentId = GetDocumentTabId(m_tabWidget->currentIndex());
|
||||
bool result = false;
|
||||
AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsDocumentRequestBus::Events::Redo);
|
||||
if (!result)
|
||||
{
|
||||
SetStatusError(tr("Document redo failed: %1").arg(GetDocumentPath(documentId)));
|
||||
}
|
||||
}, QKeySequence::Redo);
|
||||
m_menuEdit->insertAction(insertPostion, m_actionRedo);
|
||||
m_menuEdit->insertSeparator(insertPostion);
|
||||
|
||||
insertPostion = !m_menuView->actions().empty() ? m_menuView->actions().front() : nullptr;
|
||||
|
||||
m_actionPreviousTab = CreateAction(
|
||||
"&Previous Tab",
|
||||
[this]()
|
||||
{
|
||||
SelectPrevDocumentTab();
|
||||
}, Qt::CTRL | Qt::SHIFT | Qt::Key_Tab); //QKeySequence::PreviousChild is mapped incorrectly in Qt
|
||||
m_menuView->insertAction(insertPostion, m_actionPreviousTab);
|
||||
|
||||
m_actionNextTab = CreateAction("&Next Tab", [this]() {
|
||||
SelectNextDocumentTab();
|
||||
}, Qt::CTRL | Qt::Key_Tab); //QKeySequence::NextChild works as expected but mirroring Previous
|
||||
m_menuView->insertAction(insertPostion, m_actionNextTab);
|
||||
m_menuView->insertSeparator(insertPostion);
|
||||
}
|
||||
|
||||
void AtomToolsDocumentMainWindow::AddDocumentTabBar()
|
||||
{
|
||||
m_tabWidget = new AzQtComponents::TabWidget(centralWidget());
|
||||
m_tabWidget->setObjectName("TabWidget");
|
||||
m_tabWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred);
|
||||
m_tabWidget->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
// The tab bar should only be visible if it has active documents
|
||||
m_tabWidget->setVisible(false);
|
||||
m_tabWidget->setTabBarAutoHide(false);
|
||||
m_tabWidget->setMovable(true);
|
||||
m_tabWidget->setTabsClosable(true);
|
||||
m_tabWidget->setUsesScrollButtons(true);
|
||||
|
||||
// This signal will be triggered whenever a tab is added, removed, selected, clicked, dragged
|
||||
// When the last tab is removed tabIndex will be -1 and the document ID will be null
|
||||
// This should automatically clear the active document
|
||||
connect(m_tabWidget, &QTabWidget::currentChanged, this, [this](int tabIndex) {
|
||||
const AZ::Uuid documentId = GetDocumentTabId(tabIndex);
|
||||
AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, documentId);
|
||||
});
|
||||
|
||||
connect(m_tabWidget, &QTabWidget::tabCloseRequested, this, [this](int tabIndex) {
|
||||
const AZ::Uuid documentId = GetDocumentTabId(tabIndex);
|
||||
AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId);
|
||||
});
|
||||
|
||||
// Add context menu for right-clicking on tabs
|
||||
m_tabWidget->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu);
|
||||
connect(m_tabWidget, &QWidget::customContextMenuRequested, this, [this]() {
|
||||
OpenDocumentTabContextMenu();
|
||||
});
|
||||
|
||||
centralWidget()->layout()->addWidget(m_tabWidget);
|
||||
}
|
||||
|
||||
QString AtomToolsDocumentMainWindow::GetDocumentPath(const AZ::Uuid& documentId) const
|
||||
{
|
||||
AZStd::string absolutePath;
|
||||
AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsDocumentRequestBus::Handler::GetAbsolutePath);
|
||||
return absolutePath.c_str();
|
||||
}
|
||||
|
||||
AZ::Uuid AtomToolsDocumentMainWindow::GetDocumentTabId(const int tabIndex) const
|
||||
{
|
||||
const QVariant tabData = m_tabWidget->tabBar()->tabData(tabIndex);
|
||||
if (!tabData.isNull())
|
||||
{
|
||||
// We need to be able to convert between a UUID and a string to store and retrieve a document ID from the tab bar
|
||||
const QString documentIdString = tabData.toString();
|
||||
const QByteArray documentIdBytes = documentIdString.toUtf8();
|
||||
const AZ::Uuid documentId(documentIdBytes.data(), documentIdBytes.size());
|
||||
return documentId;
|
||||
}
|
||||
return AZ::Uuid::CreateNull();
|
||||
}
|
||||
|
||||
void AtomToolsDocumentMainWindow::AddDocumentTab(
|
||||
const AZ::Uuid& documentId, const AZStd::string& label, const AZStd::string& toolTip)
|
||||
{
|
||||
// Blocking signals from the tab bar so the currentChanged signal is not sent while a document is already being opened.
|
||||
// This prevents the OnDocumentOpened notification from being sent recursively.
|
||||
const QSignalBlocker blocker(m_tabWidget);
|
||||
|
||||
// If a tab for this document already exists then select it instead of creating a new one
|
||||
for (int tabIndex = 0; tabIndex < m_tabWidget->count(); ++tabIndex)
|
||||
{
|
||||
if (documentId == GetDocumentTabId(tabIndex))
|
||||
{
|
||||
m_tabWidget->setCurrentIndex(tabIndex);
|
||||
m_tabWidget->repaint();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const int tabIndex = m_tabWidget->addTab(CreateDocumentTabView(documentId), label.c_str());
|
||||
|
||||
// The user can manually reorder tabs which will invalidate any association by index.
|
||||
// We need to store the document ID with the tab using the tab instead of a separate mapping.
|
||||
m_tabWidget->tabBar()->setTabData(tabIndex, QVariant(documentId.ToString<QString>()));
|
||||
m_tabWidget->setTabToolTip(tabIndex, toolTip.c_str());
|
||||
m_tabWidget->setCurrentIndex(tabIndex);
|
||||
m_tabWidget->setVisible(true);
|
||||
m_tabWidget->repaint();
|
||||
}
|
||||
|
||||
void AtomToolsDocumentMainWindow::RemoveDocumentTab(const AZ::Uuid& documentId)
|
||||
{
|
||||
// We are not blocking signals here because we want closing tabs to close the associated document
|
||||
// and automatically select the next document.
|
||||
for (int tabIndex = 0; tabIndex < m_tabWidget->count(); ++tabIndex)
|
||||
{
|
||||
if (documentId == GetDocumentTabId(tabIndex))
|
||||
{
|
||||
m_tabWidget->removeTab(tabIndex);
|
||||
m_tabWidget->setVisible(m_tabWidget->count() > 0);
|
||||
m_tabWidget->repaint();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AtomToolsDocumentMainWindow::UpdateDocumentTab(
|
||||
const AZ::Uuid& documentId, const AZStd::string& label, const AZStd::string& toolTip, bool isModified)
|
||||
{
|
||||
// Whenever a document is opened, saved, or modified we need to update the tab label
|
||||
if (!documentId.IsNull())
|
||||
{
|
||||
// Because tab order and indexes can change from user interactions, we cannot store a map
|
||||
// between a tab index and document ID.
|
||||
// We must iterate over all of the tabs to find the one associated with this document.
|
||||
for (int tabIndex = 0; tabIndex < m_tabWidget->count(); ++tabIndex)
|
||||
{
|
||||
if (documentId == GetDocumentTabId(tabIndex))
|
||||
{
|
||||
// We use an asterisk prepended to the file name to denote modified document
|
||||
// Appending is standard and preferred but the tabs elide from the
|
||||
// end (instead of middle) and cut it off
|
||||
const AZStd::string modifiedLabel = isModified ? "* " + label : label;
|
||||
m_tabWidget->setTabText(tabIndex, modifiedLabel.c_str());
|
||||
m_tabWidget->setTabToolTip(tabIndex, toolTip.c_str());
|
||||
m_tabWidget->repaint();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AtomToolsDocumentMainWindow::SelectPrevDocumentTab()
|
||||
{
|
||||
if (m_tabWidget->count() > 1)
|
||||
{
|
||||
// Adding count to wrap around when index <= 0
|
||||
m_tabWidget->setCurrentIndex((m_tabWidget->currentIndex() + m_tabWidget->count() - 1) % m_tabWidget->count());
|
||||
}
|
||||
}
|
||||
|
||||
void AtomToolsDocumentMainWindow::SelectNextDocumentTab()
|
||||
{
|
||||
if (m_tabWidget->count() > 1)
|
||||
{
|
||||
m_tabWidget->setCurrentIndex((m_tabWidget->currentIndex() + 1) % m_tabWidget->count());
|
||||
}
|
||||
}
|
||||
|
||||
QWidget* AtomToolsDocumentMainWindow::CreateDocumentTabView(const AZ::Uuid& documentId)
|
||||
{
|
||||
AZ_UNUSED(documentId);
|
||||
auto contentWidget = new QWidget(centralWidget());
|
||||
contentWidget->setContentsMargins(0, 0, 0, 0);
|
||||
contentWidget->setFixedSize(0, 0);
|
||||
return contentWidget;
|
||||
}
|
||||
|
||||
void AtomToolsDocumentMainWindow::OpenDocumentTabContextMenu()
|
||||
{
|
||||
const QTabBar* tabBar = m_tabWidget->tabBar();
|
||||
const QPoint position = tabBar->mapFromGlobal(QCursor::pos());
|
||||
const int clickedTabIndex = tabBar->tabAt(position);
|
||||
const int currentTabIndex = tabBar->currentIndex();
|
||||
if (clickedTabIndex >= 0)
|
||||
{
|
||||
QMenu tabMenu;
|
||||
const QString selectActionName = (currentTabIndex == clickedTabIndex) ? "Select in Browser" : "Select";
|
||||
tabMenu.addAction(selectActionName, [this, clickedTabIndex]() {
|
||||
const AZ::Uuid documentId = GetDocumentTabId(clickedTabIndex);
|
||||
AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, documentId);
|
||||
});
|
||||
tabMenu.addAction("Close", [this, clickedTabIndex]() {
|
||||
const AZ::Uuid documentId = GetDocumentTabId(clickedTabIndex);
|
||||
AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId);
|
||||
});
|
||||
auto closeOthersAction = tabMenu.addAction("Close Others", [this, clickedTabIndex]() {
|
||||
const AZ::Uuid documentId = GetDocumentTabId(clickedTabIndex);
|
||||
AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId);
|
||||
});
|
||||
closeOthersAction->setEnabled(tabBar->count() > 1);
|
||||
tabMenu.exec(QCursor::pos());
|
||||
}
|
||||
}
|
||||
|
||||
bool AtomToolsDocumentMainWindow::GetCreateDocumentParams(AZStd::string& openPath, AZStd::string& savePath)
|
||||
{
|
||||
AZ_UNUSED(openPath);
|
||||
AZ_UNUSED(savePath);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AtomToolsDocumentMainWindow::GetOpenDocumentParams(AZStd::string& openPath)
|
||||
{
|
||||
AZ_UNUSED(openPath);
|
||||
return false;
|
||||
}
|
||||
|
||||
void AtomToolsDocumentMainWindow::OnDocumentOpened(const AZ::Uuid& documentId)
|
||||
{
|
||||
bool isOpen = false;
|
||||
AtomToolsDocumentRequestBus::EventResult(isOpen, documentId, &AtomToolsDocumentRequestBus::Events::IsOpen);
|
||||
bool isSavable = false;
|
||||
AtomToolsDocumentRequestBus::EventResult(isSavable, documentId, &AtomToolsDocumentRequestBus::Events::IsSavable);
|
||||
bool isModified = false;
|
||||
AtomToolsDocumentRequestBus::EventResult(isModified, documentId, &AtomToolsDocumentRequestBus::Events::IsModified);
|
||||
bool canUndo = false;
|
||||
AtomToolsDocumentRequestBus::EventResult(canUndo, documentId, &AtomToolsDocumentRequestBus::Events::CanUndo);
|
||||
bool canRedo = false;
|
||||
AtomToolsDocumentRequestBus::EventResult(canRedo, documentId, &AtomToolsDocumentRequestBus::Events::CanRedo);
|
||||
AZStd::string absolutePath;
|
||||
AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
|
||||
AZStd::string filename;
|
||||
AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename);
|
||||
|
||||
// Update UI to display the new document
|
||||
if (!documentId.IsNull() && isOpen)
|
||||
{
|
||||
// Create a new tab for the document ID and assign it's label to the file name of the document.
|
||||
AddDocumentTab(documentId, filename, absolutePath);
|
||||
UpdateDocumentTab(documentId, filename, absolutePath, isModified);
|
||||
}
|
||||
|
||||
const bool hasTabs = m_tabWidget->count() > 0;
|
||||
|
||||
// Update menu options
|
||||
m_actionNew->setEnabled(true);
|
||||
m_actionOpen->setEnabled(true);
|
||||
m_actionClose->setEnabled(hasTabs);
|
||||
m_actionCloseAll->setEnabled(hasTabs);
|
||||
m_actionCloseOthers->setEnabled(hasTabs);
|
||||
|
||||
m_actionSave->setEnabled(isOpen && isSavable);
|
||||
m_actionSaveAsCopy->setEnabled(isOpen && isSavable);
|
||||
m_actionSaveAsChild->setEnabled(isOpen);
|
||||
m_actionSaveAll->setEnabled(hasTabs);
|
||||
|
||||
m_actionUndo->setEnabled(canUndo);
|
||||
m_actionRedo->setEnabled(canRedo);
|
||||
|
||||
m_actionPreviousTab->setEnabled(m_tabWidget->count() > 1);
|
||||
m_actionNextTab->setEnabled(m_tabWidget->count() > 1);
|
||||
|
||||
activateWindow();
|
||||
raise();
|
||||
|
||||
const QString documentPath = GetDocumentPath(documentId);
|
||||
if (!documentPath.isEmpty())
|
||||
{
|
||||
SetStatusMessage(tr("Document opened: %1").arg(documentPath));
|
||||
}
|
||||
}
|
||||
|
||||
void AtomToolsDocumentMainWindow::OnDocumentClosed(const AZ::Uuid& documentId)
|
||||
{
|
||||
RemoveDocumentTab(documentId);
|
||||
SetStatusMessage(tr("Document closed: %1").arg(GetDocumentPath(documentId)));
|
||||
}
|
||||
|
||||
void AtomToolsDocumentMainWindow::OnDocumentModified(const AZ::Uuid& documentId)
|
||||
{
|
||||
bool isModified = false;
|
||||
AtomToolsDocumentRequestBus::EventResult(isModified, documentId, &AtomToolsDocumentRequestBus::Events::IsModified);
|
||||
AZStd::string absolutePath;
|
||||
AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
|
||||
AZStd::string filename;
|
||||
AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename);
|
||||
UpdateDocumentTab(documentId, filename, absolutePath, isModified);
|
||||
}
|
||||
|
||||
void AtomToolsDocumentMainWindow::OnDocumentUndoStateChanged(const AZ::Uuid& documentId)
|
||||
{
|
||||
if (documentId == GetDocumentTabId(m_tabWidget->currentIndex()))
|
||||
{
|
||||
bool canUndo = false;
|
||||
AtomToolsDocumentRequestBus::EventResult(canUndo, documentId, &AtomToolsDocumentRequestBus::Events::CanUndo);
|
||||
bool canRedo = false;
|
||||
AtomToolsDocumentRequestBus::EventResult(canRedo, documentId, &AtomToolsDocumentRequestBus::Events::CanRedo);
|
||||
m_actionUndo->setEnabled(canUndo);
|
||||
m_actionRedo->setEnabled(canRedo);
|
||||
}
|
||||
}
|
||||
|
||||
void AtomToolsDocumentMainWindow::OnDocumentSaved(const AZ::Uuid& documentId)
|
||||
{
|
||||
bool isModified = false;
|
||||
AtomToolsDocumentRequestBus::EventResult(isModified, documentId, &AtomToolsDocumentRequestBus::Events::IsModified);
|
||||
AZStd::string absolutePath;
|
||||
AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
|
||||
AZStd::string filename;
|
||||
AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename);
|
||||
UpdateDocumentTab(documentId, filename, absolutePath, isModified);
|
||||
SetStatusMessage(tr("Document saved: %1").arg(GetDocumentPath(documentId)));
|
||||
}
|
||||
|
||||
|
||||
void AtomToolsDocumentMainWindow::closeEvent(QCloseEvent* closeEvent)
|
||||
{
|
||||
bool didClose = true;
|
||||
AtomToolsDocumentSystemRequestBus::BroadcastResult(didClose, &AtomToolsDocumentSystemRequestBus::Events::CloseAllDocuments);
|
||||
if (!didClose)
|
||||
{
|
||||
closeEvent->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
AtomToolsMainWindowNotificationBus::Broadcast(&AtomToolsMainWindowNotifications::OnMainWindowClosing);
|
||||
}
|
||||
|
||||
template<typename Functor>
|
||||
QAction* AtomToolsDocumentMainWindow::CreateAction(const QString& text, Functor functor, const QKeySequence& shortcut)
|
||||
{
|
||||
QAction* action = new QAction(text, this);
|
||||
action->setShortcut(shortcut);
|
||||
connect(action, &QAction::triggered, this, functor);
|
||||
return action;
|
||||
}
|
||||
} // namespace AtomToolsFramework
|
||||
|
||||
//#include <Document/moc_AtomToolsDocumentMainWindow.cpp>
|
||||
@@ -7,6 +7,11 @@
|
||||
*/
|
||||
|
||||
#include <AtomToolsFramework/Window/AtomToolsMainWindow.h>
|
||||
#include <AzToolsFramework/API/EditorPythonRunnerRequestsBus.h>
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QMenu>
|
||||
#include <QMenuBar>
|
||||
#include <QStatusBar>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
@@ -23,6 +28,8 @@ namespace AtomToolsFramework
|
||||
setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea);
|
||||
setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
|
||||
|
||||
AddCommonMenus();
|
||||
|
||||
m_statusMessage = new QLabel(statusBar());
|
||||
statusBar()->addPermanentWidget(m_statusMessage, 1);
|
||||
|
||||
@@ -65,6 +72,10 @@ namespace AtomToolsFramework
|
||||
addDockWidget(aznumeric_cast<Qt::DockWidgetArea>(area), dockWidget);
|
||||
resizeDocks({ dockWidget }, { 400 }, aznumeric_cast<Qt::Orientation>(orientation));
|
||||
m_dockWidgets[name] = dockWidget;
|
||||
|
||||
m_dockActions[name] = m_menuView->addAction(name.c_str(), [this, name](){
|
||||
SetDockWidgetVisible(name, !IsDockWidgetVisible(name));
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -76,6 +87,12 @@ namespace AtomToolsFramework
|
||||
delete dockWidgetItr->second;
|
||||
m_dockWidgets.erase(dockWidgetItr);
|
||||
}
|
||||
auto dockActionItr = m_dockActions.find(name);
|
||||
if (dockActionItr != m_dockActions.end())
|
||||
{
|
||||
delete dockActionItr->second;
|
||||
m_dockActions.erase(dockActionItr);
|
||||
}
|
||||
}
|
||||
|
||||
void AtomToolsMainWindow::SetDockWidgetVisible(const AZStd::string& name, bool visible)
|
||||
@@ -108,145 +125,6 @@ namespace AtomToolsFramework
|
||||
return names;
|
||||
}
|
||||
|
||||
void AtomToolsMainWindow::CreateMenu()
|
||||
{
|
||||
auto menuBar = new QMenuBar(this);
|
||||
menuBar->setObjectName("MenuBar");
|
||||
setMenuBar(menuBar);
|
||||
}
|
||||
|
||||
void AtomToolsMainWindow::CreateTabBar()
|
||||
{
|
||||
m_tabWidget = new AzQtComponents::TabWidget(centralWidget());
|
||||
m_tabWidget->setObjectName("TabWidget");
|
||||
m_tabWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred);
|
||||
m_tabWidget->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
// The tab bar should only be visible if it has active documents
|
||||
m_tabWidget->setVisible(false);
|
||||
m_tabWidget->setTabBarAutoHide(false);
|
||||
m_tabWidget->setMovable(true);
|
||||
m_tabWidget->setTabsClosable(true);
|
||||
m_tabWidget->setUsesScrollButtons(true);
|
||||
|
||||
// Add context menu for right-clicking on tabs
|
||||
m_tabWidget->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu);
|
||||
connect(
|
||||
m_tabWidget, &QWidget::customContextMenuRequested, this,
|
||||
[this]()
|
||||
{
|
||||
OpenTabContextMenu();
|
||||
});
|
||||
|
||||
centralWidget()->layout()->addWidget(m_tabWidget);
|
||||
}
|
||||
|
||||
void AtomToolsMainWindow::AddTabForDocumentId(
|
||||
const AZ::Uuid& documentId, const AZStd::string& label, const AZStd::string& toolTip, AZStd::function<QWidget*()> widgetCreator)
|
||||
{
|
||||
// Blocking signals from the tab bar so the currentChanged signal is not sent while a document is already being opened.
|
||||
// This prevents the OnDocumentOpened notification from being sent recursively.
|
||||
const QSignalBlocker blocker(m_tabWidget);
|
||||
|
||||
// If a tab for this document already exists then select it instead of creating a new one
|
||||
for (int tabIndex = 0; tabIndex < m_tabWidget->count(); ++tabIndex)
|
||||
{
|
||||
if (documentId == GetDocumentIdFromTab(tabIndex))
|
||||
{
|
||||
m_tabWidget->setCurrentIndex(tabIndex);
|
||||
m_tabWidget->repaint();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const int tabIndex = m_tabWidget->addTab(widgetCreator(), label.c_str());
|
||||
|
||||
// The user can manually reorder tabs which will invalidate any association by index.
|
||||
// We need to store the document ID with the tab using the tab instead of a separate mapping.
|
||||
m_tabWidget->tabBar()->setTabData(tabIndex, QVariant(documentId.ToString<QString>()));
|
||||
m_tabWidget->setTabToolTip(tabIndex, toolTip.c_str());
|
||||
m_tabWidget->setCurrentIndex(tabIndex);
|
||||
m_tabWidget->setVisible(true);
|
||||
m_tabWidget->repaint();
|
||||
}
|
||||
|
||||
void AtomToolsMainWindow::RemoveTabForDocumentId(const AZ::Uuid& documentId)
|
||||
{
|
||||
// We are not blocking signals here because we want closing tabs to close the associated document
|
||||
// and automatically select the next document.
|
||||
for (int tabIndex = 0; tabIndex < m_tabWidget->count(); ++tabIndex)
|
||||
{
|
||||
if (documentId == GetDocumentIdFromTab(tabIndex))
|
||||
{
|
||||
m_tabWidget->removeTab(tabIndex);
|
||||
m_tabWidget->setVisible(m_tabWidget->count() > 0);
|
||||
m_tabWidget->repaint();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AtomToolsMainWindow::UpdateTabForDocumentId(
|
||||
const AZ::Uuid& documentId, const AZStd::string& label, const AZStd::string& toolTip, bool isModified)
|
||||
{
|
||||
// Whenever a document is opened, saved, or modified we need to update the tab label
|
||||
if (!documentId.IsNull())
|
||||
{
|
||||
// Because tab order and indexes can change from user interactions, we cannot store a map
|
||||
// between a tab index and document ID.
|
||||
// We must iterate over all of the tabs to find the one associated with this document.
|
||||
for (int tabIndex = 0; tabIndex < m_tabWidget->count(); ++tabIndex)
|
||||
{
|
||||
if (documentId == GetDocumentIdFromTab(tabIndex))
|
||||
{
|
||||
// We use an asterisk prepended to the file name to denote modified document
|
||||
// Appending is standard and preferred but the tabs elide from the
|
||||
// end (instead of middle) and cut it off
|
||||
const AZStd::string modifiedLabel = isModified ? "* " + label : label;
|
||||
m_tabWidget->setTabText(tabIndex, modifiedLabel.c_str());
|
||||
m_tabWidget->setTabToolTip(tabIndex, toolTip.c_str());
|
||||
m_tabWidget->repaint();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AZ::Uuid AtomToolsMainWindow::GetDocumentIdFromTab(const int tabIndex) const
|
||||
{
|
||||
const QVariant tabData = m_tabWidget->tabBar()->tabData(tabIndex);
|
||||
if (!tabData.isNull())
|
||||
{
|
||||
// We need to be able to convert between a UUID and a string to store and retrieve a document ID from the tab bar
|
||||
const QString documentIdString = tabData.toString();
|
||||
const QByteArray documentIdBytes = documentIdString.toUtf8();
|
||||
const AZ::Uuid documentId(documentIdBytes.data(), documentIdBytes.size());
|
||||
return documentId;
|
||||
}
|
||||
return AZ::Uuid::CreateNull();
|
||||
}
|
||||
|
||||
void AtomToolsMainWindow::OpenTabContextMenu()
|
||||
{
|
||||
}
|
||||
|
||||
void AtomToolsMainWindow::SelectPreviousTab()
|
||||
{
|
||||
if (m_tabWidget->count() > 1)
|
||||
{
|
||||
// Adding count to wrap around when index <= 0
|
||||
m_tabWidget->setCurrentIndex((m_tabWidget->currentIndex() + m_tabWidget->count() - 1) % m_tabWidget->count());
|
||||
}
|
||||
}
|
||||
|
||||
void AtomToolsMainWindow::SelectNextTab()
|
||||
{
|
||||
if (m_tabWidget->count() > 1)
|
||||
{
|
||||
m_tabWidget->setCurrentIndex((m_tabWidget->currentIndex() + 1) % m_tabWidget->count());
|
||||
}
|
||||
}
|
||||
|
||||
void AtomToolsMainWindow::SetStatusMessage(const QString& message)
|
||||
{
|
||||
m_statusMessage->setText(QString("<font color=\"White\">%1</font>").arg(message));
|
||||
@@ -261,4 +139,50 @@ namespace AtomToolsFramework
|
||||
{
|
||||
m_statusMessage->setText(QString("<font color=\"Red\">%1</font>").arg(message));
|
||||
}
|
||||
|
||||
void AtomToolsMainWindow::AddCommonMenus()
|
||||
{
|
||||
m_menuFile = menuBar()->addMenu("&File");
|
||||
m_menuEdit = menuBar()->addMenu("&Edit");
|
||||
m_menuView = menuBar()->addMenu("&View");
|
||||
m_menuHelp = menuBar()->addMenu("&Help");
|
||||
|
||||
m_menuFile->addAction("Run &Python...", [this]() {
|
||||
const QString script = QFileDialog::getOpenFileName(this, "Run Script", QString(), QString("*.py"));
|
||||
if (!script.isEmpty())
|
||||
{
|
||||
AzToolsFramework::EditorPythonRunnerRequestBus::Broadcast(&AzToolsFramework::EditorPythonRunnerRequestBus::Events::ExecuteByFilename, script.toUtf8().constData());
|
||||
}
|
||||
});
|
||||
|
||||
m_menuFile->addSeparator();
|
||||
|
||||
m_menuFile->addAction("E&xit", [this]() {
|
||||
close();
|
||||
}, QKeySequence::Quit);
|
||||
|
||||
m_menuEdit->addAction("&Settings...", [this]() {
|
||||
OpenSettings();
|
||||
}, QKeySequence::Preferences);
|
||||
|
||||
m_menuHelp->addAction("&Help...", [this]() {
|
||||
OpenHelp();
|
||||
});
|
||||
|
||||
m_menuHelp->addAction("&About...", [this]() {
|
||||
OpenAbout();
|
||||
});
|
||||
}
|
||||
|
||||
void AtomToolsMainWindow::OpenSettings()
|
||||
{
|
||||
}
|
||||
|
||||
void AtomToolsMainWindow::OpenHelp()
|
||||
{
|
||||
}
|
||||
|
||||
void AtomToolsMainWindow::OpenAbout()
|
||||
{
|
||||
}
|
||||
} // namespace AtomToolsFramework
|
||||
|
||||
@@ -12,6 +12,7 @@ set(FILES
|
||||
Include/AtomToolsFramework/Communication/LocalSocket.h
|
||||
Include/AtomToolsFramework/Debug/TraceRecorder.h
|
||||
Include/AtomToolsFramework/Document/AtomToolsDocument.h
|
||||
Include/AtomToolsFramework/Document/AtomToolsDocumentMainWindow.h
|
||||
Include/AtomToolsFramework/Document/AtomToolsDocumentSystemSettings.h
|
||||
Include/AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h
|
||||
Include/AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h
|
||||
@@ -38,6 +39,7 @@ set(FILES
|
||||
Source/Communication/LocalSocket.cpp
|
||||
Source/Debug/TraceRecorder.cpp
|
||||
Source/Document/AtomToolsDocument.cpp
|
||||
Source/Document/AtomToolsDocumentMainWindow.cpp
|
||||
Source/Document/AtomToolsDocumentSystemSettings.cpp
|
||||
Source/Document/AtomToolsDocumentSystemComponent.cpp
|
||||
Source/Document/AtomToolsDocumentSystemComponent.h
|
||||
|
||||
@@ -9,15 +9,9 @@
|
||||
#include <Atom/Document/MaterialDocumentRequestBus.h>
|
||||
#include <Atom/RHI/Factory.h>
|
||||
#include <Atom/Window/MaterialEditorWindowSettings.h>
|
||||
#include <AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h>
|
||||
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
|
||||
#include <AtomToolsFramework/Util/Util.h>
|
||||
#include <AtomToolsFramework/Window/AtomToolsMainWindowNotificationBus.h>
|
||||
#include <AzFramework/StringFunc/StringFunc.h>
|
||||
#include <AzQtComponents/Components/StyleManager.h>
|
||||
#include <AzQtComponents/Components/WindowDecorationWrapper.h>
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
||||
#include <AzToolsFramework/API/EditorPythonRunnerRequestsBus.h>
|
||||
#include <AzToolsFramework/PythonTerminal/ScriptTermDialog.h>
|
||||
#include <Viewport/MaterialViewportWidget.h>
|
||||
#include <Window/CreateMaterialDialog/CreateMaterialDialog.h>
|
||||
@@ -33,7 +27,6 @@ AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnin
|
||||
#include <QApplication>
|
||||
#include <QByteArray>
|
||||
#include <QCloseEvent>
|
||||
#include <QDesktopWidget>
|
||||
#include <QFileDialog>
|
||||
#include <QWindow>
|
||||
AZ_POP_DISABLE_WARNING
|
||||
@@ -41,7 +34,7 @@ AZ_POP_DISABLE_WARNING
|
||||
namespace MaterialEditor
|
||||
{
|
||||
MaterialEditorWindow::MaterialEditorWindow(QWidget* parent /* = 0 */)
|
||||
: AtomToolsFramework::AtomToolsMainWindow(parent)
|
||||
: AtomToolsFramework::AtomToolsDocumentMainWindow(parent)
|
||||
{
|
||||
resize(1280, 1024);
|
||||
|
||||
@@ -74,9 +67,6 @@ namespace MaterialEditor
|
||||
m_toolBar->setObjectName("ToolBar");
|
||||
addToolBar(m_toolBar);
|
||||
|
||||
CreateMenu();
|
||||
CreateTabBar();
|
||||
|
||||
m_materialViewport = new MaterialViewportWidget(centralWidget());
|
||||
m_materialViewport->setObjectName("Viewport");
|
||||
m_materialViewport->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
|
||||
@@ -105,16 +95,9 @@ namespace MaterialEditor
|
||||
m_advancedDockManager->restoreState(windowState);
|
||||
}
|
||||
|
||||
AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect();
|
||||
OnDocumentOpened(AZ::Uuid::CreateNull());
|
||||
}
|
||||
|
||||
MaterialEditorWindow::~MaterialEditorWindow()
|
||||
{
|
||||
AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
|
||||
void MaterialEditorWindow::ResizeViewportRenderTarget(uint32_t width, uint32_t height)
|
||||
{
|
||||
QSize requestedViewportSize = QSize(width, height) / devicePixelRatioF();
|
||||
@@ -146,16 +129,43 @@ namespace MaterialEditor
|
||||
m_materialViewport->UnlockRenderTargetSize();
|
||||
}
|
||||
|
||||
bool MaterialEditorWindow::GetCreateDocumentParams(AZStd::string& openPath, AZStd::string& savePath)
|
||||
{
|
||||
CreateMaterialDialog createDialog(this);
|
||||
createDialog.adjustSize();
|
||||
|
||||
if (createDialog.exec() == QDialog::Accepted &&
|
||||
!createDialog.m_materialFileInfo.absoluteFilePath().isEmpty() &&
|
||||
!createDialog.m_materialTypeFileInfo.absoluteFilePath().isEmpty())
|
||||
{
|
||||
savePath = createDialog.m_materialFileInfo.absoluteFilePath().toUtf8().constData();
|
||||
openPath = createDialog.m_materialTypeFileInfo.absoluteFilePath().toUtf8().constData();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MaterialEditorWindow::GetOpenDocumentParams(AZStd::string& openPath)
|
||||
{
|
||||
const AZStd::vector<AZ::Data::AssetType> assetTypes = { azrtti_typeid<AZ::RPI::MaterialAsset>() };
|
||||
openPath = AtomToolsFramework::GetOpenFileInfo(assetTypes).absoluteFilePath().toUtf8().constData();
|
||||
return !openPath.empty();
|
||||
}
|
||||
|
||||
void MaterialEditorWindow::OpenSettings()
|
||||
{
|
||||
SettingsDialog dialog(this);
|
||||
dialog.exec();
|
||||
}
|
||||
|
||||
void MaterialEditorWindow::OpenHelp()
|
||||
{
|
||||
HelpDialog dialog(this);
|
||||
dialog.exec();
|
||||
}
|
||||
|
||||
void MaterialEditorWindow::closeEvent(QCloseEvent* closeEvent)
|
||||
{
|
||||
bool didClose = true;
|
||||
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(didClose, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseAllDocuments);
|
||||
if (!didClose)
|
||||
{
|
||||
closeEvent->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
// Capture docking state before shutdown
|
||||
auto windowSettings = AZ::UserSettings::CreateFind<MaterialEditorWindowSettings>(
|
||||
AZ::Crc32("MaterialEditorWindowSettings"), AZ::UserSettings::CT_GLOBAL);
|
||||
@@ -163,368 +173,7 @@ namespace MaterialEditor
|
||||
QByteArray windowState = m_advancedDockManager->saveState();
|
||||
windowSettings->m_mainWindowState.assign(windowState.begin(), windowState.end());
|
||||
|
||||
AtomToolsFramework::AtomToolsMainWindowNotificationBus::Broadcast(
|
||||
&AtomToolsFramework::AtomToolsMainWindowNotifications::OnMainWindowClosing);
|
||||
}
|
||||
|
||||
void MaterialEditorWindow::OnDocumentOpened(const AZ::Uuid& documentId)
|
||||
{
|
||||
bool isOpen = false;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isOpen, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsOpen);
|
||||
bool isSavable = false;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isSavable, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsSavable);
|
||||
bool isModified = false;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isModified, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsModified);
|
||||
bool canUndo = false;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(canUndo, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::CanUndo);
|
||||
bool canRedo = false;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(canRedo, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::CanRedo);
|
||||
AZStd::string absolutePath;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
|
||||
AZStd::string filename;
|
||||
AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename);
|
||||
|
||||
// Update UI to display the new document
|
||||
if (!documentId.IsNull() && isOpen)
|
||||
{
|
||||
// Create a new tab for the document ID and assign it's label to the file name of the document.
|
||||
AddTabForDocumentId(documentId, filename, absolutePath, [this]{
|
||||
// The tab widget requires a dummy page per tab
|
||||
auto contentWidget = new QWidget(centralWidget());
|
||||
contentWidget->setContentsMargins(0, 0, 0, 0);
|
||||
contentWidget->setFixedSize(0, 0);
|
||||
return contentWidget;
|
||||
});
|
||||
}
|
||||
|
||||
UpdateTabForDocumentId(documentId, filename, absolutePath, isModified);
|
||||
|
||||
const bool hasTabs = m_tabWidget->count() > 0;
|
||||
|
||||
// Update menu options
|
||||
m_actionNew->setEnabled(true);
|
||||
m_actionOpen->setEnabled(true);
|
||||
m_actionOpenRecent->setEnabled(false);
|
||||
m_actionClose->setEnabled(hasTabs);
|
||||
m_actionCloseAll->setEnabled(hasTabs);
|
||||
m_actionCloseOthers->setEnabled(hasTabs);
|
||||
|
||||
m_actionSave->setEnabled(isOpen && isSavable);
|
||||
m_actionSaveAsCopy->setEnabled(isOpen && isSavable);
|
||||
m_actionSaveAsChild->setEnabled(isOpen);
|
||||
m_actionSaveAll->setEnabled(hasTabs);
|
||||
|
||||
m_actionExit->setEnabled(true);
|
||||
|
||||
m_actionUndo->setEnabled(canUndo);
|
||||
m_actionRedo->setEnabled(canRedo);
|
||||
m_actionSettings->setEnabled(true);
|
||||
|
||||
m_actionAssetBrowser->setEnabled(true);
|
||||
m_actionInspector->setEnabled(true);
|
||||
m_actionConsole->setEnabled(false);
|
||||
m_actionPythonTerminal->setEnabled(true);
|
||||
m_actionPerfMonitor->setEnabled(true);
|
||||
m_actionViewportSettings->setEnabled(true);
|
||||
m_actionPreviousTab->setEnabled(m_tabWidget->count() > 1);
|
||||
m_actionNextTab->setEnabled(m_tabWidget->count() > 1);
|
||||
|
||||
m_actionAbout->setEnabled(false);
|
||||
|
||||
activateWindow();
|
||||
raise();
|
||||
|
||||
const QString documentPath = GetDocumentPath(documentId);
|
||||
if (!documentPath.isEmpty())
|
||||
{
|
||||
SetStatusMessage(tr("Document opened: %1").arg(documentPath));
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialEditorWindow::OnDocumentClosed(const AZ::Uuid& documentId)
|
||||
{
|
||||
RemoveTabForDocumentId(documentId);
|
||||
SetStatusMessage(tr("Document closed: %1").arg(GetDocumentPath(documentId)));
|
||||
}
|
||||
|
||||
void MaterialEditorWindow::OnDocumentModified(const AZ::Uuid& documentId)
|
||||
{
|
||||
bool isModified = false;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isModified, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsModified);
|
||||
AZStd::string absolutePath;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
|
||||
AZStd::string filename;
|
||||
AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename);
|
||||
UpdateTabForDocumentId(documentId, filename, absolutePath, isModified);
|
||||
}
|
||||
|
||||
void MaterialEditorWindow::OnDocumentUndoStateChanged(const AZ::Uuid& documentId)
|
||||
{
|
||||
if (documentId == GetDocumentIdFromTab(m_tabWidget->currentIndex()))
|
||||
{
|
||||
bool canUndo = false;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(canUndo, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::CanUndo);
|
||||
bool canRedo = false;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(canRedo, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::CanRedo);
|
||||
m_actionUndo->setEnabled(canUndo);
|
||||
m_actionRedo->setEnabled(canRedo);
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialEditorWindow::OnDocumentSaved(const AZ::Uuid& documentId)
|
||||
{
|
||||
bool isModified = false;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isModified, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsModified);
|
||||
AZStd::string absolutePath;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
|
||||
AZStd::string filename;
|
||||
AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename);
|
||||
UpdateTabForDocumentId(documentId, filename, absolutePath, isModified);
|
||||
SetStatusMessage(tr("Document saved: %1").arg(GetDocumentPath(documentId)));
|
||||
}
|
||||
|
||||
void MaterialEditorWindow::CreateMenu()
|
||||
{
|
||||
Base::CreateMenu();
|
||||
|
||||
// Generating the main menu manually because it's easier and we will have some dynamic or data driven entries
|
||||
m_menuFile = menuBar()->addMenu("&File");
|
||||
|
||||
m_actionNew = m_menuFile->addAction("&New...", [this]() {
|
||||
CreateMaterialDialog createDialog(this);
|
||||
createDialog.adjustSize();
|
||||
|
||||
if (createDialog.exec() == QDialog::Accepted &&
|
||||
!createDialog.m_materialFileInfo.absoluteFilePath().isEmpty() &&
|
||||
!createDialog.m_materialTypeFileInfo.absoluteFilePath().isEmpty())
|
||||
{
|
||||
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CreateDocumentFromFile,
|
||||
createDialog.m_materialTypeFileInfo.absoluteFilePath().toUtf8().constData(),
|
||||
createDialog.m_materialFileInfo.absoluteFilePath().toUtf8().constData());
|
||||
}
|
||||
}, QKeySequence::New);
|
||||
|
||||
m_actionOpen = m_menuFile->addAction("&Open...", [this]() {
|
||||
const AZStd::vector<AZ::Data::AssetType> assetTypes = { azrtti_typeid<AZ::RPI::MaterialAsset>() };
|
||||
const AZStd::string filePath = AtomToolsFramework::GetOpenFileInfo(assetTypes).absoluteFilePath().toUtf8().constData();
|
||||
if (!filePath.empty())
|
||||
{
|
||||
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, filePath);
|
||||
}
|
||||
}, QKeySequence::Open);
|
||||
|
||||
m_actionOpenRecent = m_menuFile->addAction("Open &Recent");
|
||||
|
||||
m_menuFile->addSeparator();
|
||||
|
||||
m_actionSave = m_menuFile->addAction("&Save", [this]() {
|
||||
const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex());
|
||||
bool result = false;
|
||||
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::SaveDocument, documentId);
|
||||
if (!result)
|
||||
{
|
||||
SetStatusError(tr("Document save failed: %1").arg(GetDocumentPath(documentId)));
|
||||
}
|
||||
}, QKeySequence::Save);
|
||||
|
||||
m_actionSaveAsCopy = m_menuFile->addAction("Save &As...", [this]() {
|
||||
const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex());
|
||||
const QString documentPath = GetDocumentPath(documentId);
|
||||
|
||||
bool result = false;
|
||||
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::SaveDocumentAsCopy,
|
||||
documentId, AtomToolsFramework::GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData());
|
||||
if (!result)
|
||||
{
|
||||
SetStatusError(tr("Document save failed: %1").arg(GetDocumentPath(documentId)));
|
||||
}
|
||||
}, QKeySequence::SaveAs);
|
||||
|
||||
m_actionSaveAsChild = m_menuFile->addAction("Save As &Child...", [this]() {
|
||||
const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex());
|
||||
const QString documentPath = GetDocumentPath(documentId);
|
||||
|
||||
bool result = false;
|
||||
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::SaveDocumentAsChild,
|
||||
documentId, AtomToolsFramework::GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData());
|
||||
if (!result)
|
||||
{
|
||||
SetStatusError(tr("Document save failed: %1").arg(GetDocumentPath(documentId)));
|
||||
}
|
||||
});
|
||||
|
||||
m_actionSaveAll = m_menuFile->addAction("Save A&ll", [this]() {
|
||||
bool result = false;
|
||||
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::SaveAllDocuments);
|
||||
if (!result)
|
||||
{
|
||||
SetStatusError(tr("Document save all failed"));
|
||||
}
|
||||
});
|
||||
|
||||
m_menuFile->addSeparator();
|
||||
|
||||
m_actionClose = m_menuFile->addAction("&Close", [this]() {
|
||||
const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex());
|
||||
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId);
|
||||
}, QKeySequence::Close);
|
||||
|
||||
m_actionCloseAll = m_menuFile->addAction("Close All", [this]() {
|
||||
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseAllDocuments);
|
||||
});
|
||||
|
||||
m_actionCloseOthers = m_menuFile->addAction("Close Others", [this]() {
|
||||
const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex());
|
||||
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId);
|
||||
});
|
||||
|
||||
m_menuFile->addSeparator();
|
||||
|
||||
m_menuFile->addAction("Run &Python...", [this]() {
|
||||
const QString script = QFileDialog::getOpenFileName(this, "Run Script", QString(), QString("*.py"));
|
||||
if (!script.isEmpty())
|
||||
{
|
||||
AzToolsFramework::EditorPythonRunnerRequestBus::Broadcast(&AzToolsFramework::EditorPythonRunnerRequestBus::Events::ExecuteByFilename, script.toUtf8().constData());
|
||||
}
|
||||
});
|
||||
|
||||
m_menuFile->addSeparator();
|
||||
|
||||
m_actionExit = m_menuFile->addAction("E&xit", [this]() {
|
||||
close();
|
||||
}, QKeySequence::Quit);
|
||||
|
||||
m_menuEdit = menuBar()->addMenu("&Edit");
|
||||
|
||||
m_actionUndo = m_menuEdit->addAction("&Undo", [this]() {
|
||||
const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex());
|
||||
bool result = false;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::Undo);
|
||||
if (!result)
|
||||
{
|
||||
SetStatusError(tr("Document undo failed: %1").arg(GetDocumentPath(documentId)));
|
||||
}
|
||||
}, QKeySequence::Undo);
|
||||
|
||||
m_actionRedo = m_menuEdit->addAction("&Redo", [this]() {
|
||||
const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex());
|
||||
bool result = false;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::Redo);
|
||||
if (!result)
|
||||
{
|
||||
SetStatusError(tr("Document redo failed: %1").arg(GetDocumentPath(documentId)));
|
||||
}
|
||||
}, QKeySequence::Redo);
|
||||
|
||||
m_menuEdit->addSeparator();
|
||||
|
||||
m_actionSettings = m_menuEdit->addAction("&Settings...", [this]() {
|
||||
SettingsDialog dialog(this);
|
||||
dialog.exec();
|
||||
}, QKeySequence::Preferences);
|
||||
m_actionSettings->setEnabled(true);
|
||||
|
||||
m_menuView = menuBar()->addMenu("&View");
|
||||
|
||||
m_actionAssetBrowser = m_menuView->addAction("&Asset Browser", [this]() {
|
||||
const AZStd::string label = "Asset Browser";
|
||||
SetDockWidgetVisible(label, !IsDockWidgetVisible(label));
|
||||
});
|
||||
|
||||
m_actionInspector = m_menuView->addAction("&Inspector", [this]() {
|
||||
const AZStd::string label = "Inspector";
|
||||
SetDockWidgetVisible(label, !IsDockWidgetVisible(label));
|
||||
});
|
||||
|
||||
m_actionConsole = m_menuView->addAction("&Console", [this]() {
|
||||
});
|
||||
|
||||
m_actionPythonTerminal = m_menuView->addAction("Python &Terminal", [this]() {
|
||||
const AZStd::string label = "Python Terminal";
|
||||
SetDockWidgetVisible(label, !IsDockWidgetVisible(label));
|
||||
});
|
||||
|
||||
m_actionPerfMonitor = m_menuView->addAction("Performance &Monitor", [this]() {
|
||||
const AZStd::string label = "Performance Monitor";
|
||||
SetDockWidgetVisible(label, !IsDockWidgetVisible(label));
|
||||
});
|
||||
|
||||
m_actionViewportSettings = m_menuView->addAction("Viewport Settings", [this]() {
|
||||
const AZStd::string label = "Viewport Settings";
|
||||
SetDockWidgetVisible(label, !IsDockWidgetVisible(label));
|
||||
});
|
||||
|
||||
m_menuView->addSeparator();
|
||||
|
||||
m_actionPreviousTab = m_menuView->addAction("&Previous Tab", [this]() {
|
||||
SelectPreviousTab();
|
||||
}, Qt::CTRL | Qt::SHIFT | Qt::Key_Tab); //QKeySequence::PreviousChild is mapped incorrectly in Qt
|
||||
|
||||
m_actionNextTab = m_menuView->addAction("&Next Tab", [this]() {
|
||||
SelectNextTab();
|
||||
}, Qt::CTRL | Qt::Key_Tab); //QKeySequence::NextChild works as expected but mirroring Previous
|
||||
|
||||
m_menuHelp = menuBar()->addMenu("&Help");
|
||||
|
||||
m_actionHelp = m_menuHelp->addAction("&Help...", [this]() {
|
||||
HelpDialog dialog(this);
|
||||
dialog.exec();
|
||||
});
|
||||
|
||||
m_actionAbout = m_menuHelp->addAction("&About...", [this]() {
|
||||
});
|
||||
}
|
||||
|
||||
void MaterialEditorWindow::CreateTabBar()
|
||||
{
|
||||
Base::CreateTabBar();
|
||||
|
||||
// This signal will be triggered whenever a tab is added, removed, selected, clicked, dragged
|
||||
// When the last tab is removed tabIndex will be -1 and the document ID will be null
|
||||
// This should automatically clear the active document
|
||||
connect(m_tabWidget, &QTabWidget::currentChanged, this, [this](int tabIndex) {
|
||||
const AZ::Uuid documentId = GetDocumentIdFromTab(tabIndex);
|
||||
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, documentId);
|
||||
});
|
||||
|
||||
connect(m_tabWidget, &QTabWidget::tabCloseRequested, this, [this](int tabIndex) {
|
||||
const AZ::Uuid documentId = GetDocumentIdFromTab(tabIndex);
|
||||
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId);
|
||||
});
|
||||
}
|
||||
|
||||
QString MaterialEditorWindow::GetDocumentPath(const AZ::Uuid& documentId) const
|
||||
{
|
||||
AZStd::string absolutePath;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Handler::GetAbsolutePath);
|
||||
return absolutePath.c_str();
|
||||
}
|
||||
|
||||
void MaterialEditorWindow::OpenTabContextMenu()
|
||||
{
|
||||
const QTabBar* tabBar = m_tabWidget->tabBar();
|
||||
const QPoint position = tabBar->mapFromGlobal(QCursor::pos());
|
||||
const int clickedTabIndex = tabBar->tabAt(position);
|
||||
const int currentTabIndex = tabBar->currentIndex();
|
||||
if (clickedTabIndex >= 0)
|
||||
{
|
||||
QMenu tabMenu;
|
||||
const QString selectActionName = (currentTabIndex == clickedTabIndex) ? "Select in Browser" : "Select";
|
||||
tabMenu.addAction(selectActionName, [this, clickedTabIndex]() {
|
||||
const AZ::Uuid documentId = GetDocumentIdFromTab(clickedTabIndex);
|
||||
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, documentId);
|
||||
});
|
||||
tabMenu.addAction("Close", [this, clickedTabIndex]() {
|
||||
const AZ::Uuid documentId = GetDocumentIdFromTab(clickedTabIndex);
|
||||
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId);
|
||||
});
|
||||
auto closeOthersAction = tabMenu.addAction("Close Others", [this, clickedTabIndex]() {
|
||||
const AZ::Uuid documentId = GetDocumentIdFromTab(clickedTabIndex);
|
||||
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId);
|
||||
});
|
||||
closeOthersAction->setEnabled(tabBar->count() > 1);
|
||||
tabMenu.exec(QCursor::pos());
|
||||
}
|
||||
Base::closeEvent(closeEvent);
|
||||
}
|
||||
} // namespace MaterialEditor
|
||||
|
||||
|
||||
@@ -9,9 +9,7 @@
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h>
|
||||
#include <AtomToolsFramework/Window/AtomToolsMainWindow.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AtomToolsFramework/Document/AtomToolsDocumentMainWindow.h>
|
||||
|
||||
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
|
||||
#include <Viewport/MaterialViewportWidget.h>
|
||||
@@ -21,80 +19,36 @@ AZ_POP_DISABLE_WARNING
|
||||
|
||||
namespace MaterialEditor
|
||||
{
|
||||
/**
|
||||
* MaterialEditorWindow is the main class. Its responsibility is limited to initializing and connecting
|
||||
* its panels, managing selection of assets, and performing high-level actions like saving. It contains...
|
||||
* 1) MaterialBrowser - The user browses for Material (.material) assets.
|
||||
* 2) MaterialViewport - The user can see the selected Material applied to a model.
|
||||
* 3) MaterialPropertyInspector - The user edits the properties of the selected Material.
|
||||
*/
|
||||
//! MaterialEditorWindow is the main class. Its responsibility is limited to initializing and connecting
|
||||
//! its panels, managing selection of assets, and performing high-level actions like saving. It contains...
|
||||
//! 1) MaterialBrowser - The user browses for Material (.material) assets.
|
||||
//! 2) MaterialViewport - The user can see the selected Material applied to a model.
|
||||
//! 3) MaterialPropertyInspector - The user edits the properties of the selected Material.
|
||||
class MaterialEditorWindow
|
||||
: public AtomToolsFramework::AtomToolsMainWindow
|
||||
, private AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler
|
||||
: public AtomToolsFramework::AtomToolsDocumentMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(MaterialEditorWindow, AZ::SystemAllocator, 0);
|
||||
|
||||
using Base = AtomToolsFramework::AtomToolsMainWindow;
|
||||
using Base = AtomToolsFramework::AtomToolsDocumentMainWindow;
|
||||
|
||||
MaterialEditorWindow(QWidget* parent = 0);
|
||||
~MaterialEditorWindow();
|
||||
~MaterialEditorWindow() = default;
|
||||
|
||||
private:
|
||||
protected:
|
||||
void ResizeViewportRenderTarget(uint32_t width, uint32_t height) override;
|
||||
void LockViewportRenderTargetSize(uint32_t width, uint32_t height) override;
|
||||
void UnlockViewportRenderTargetSize() override;
|
||||
|
||||
// AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler overrides...
|
||||
void OnDocumentOpened(const AZ::Uuid& documentId) override;
|
||||
void OnDocumentClosed(const AZ::Uuid& documentId) override;
|
||||
void OnDocumentModified(const AZ::Uuid& documentId) override;
|
||||
void OnDocumentUndoStateChanged(const AZ::Uuid& documentId) override;
|
||||
void OnDocumentSaved(const AZ::Uuid& documentId) override;
|
||||
|
||||
void CreateMenu() override;
|
||||
void CreateTabBar() override;
|
||||
|
||||
QString GetDocumentPath(const AZ::Uuid& documentId) const;
|
||||
|
||||
void OpenTabContextMenu() override;
|
||||
bool GetCreateDocumentParams(AZStd::string& openPath, AZStd::string& savePath) override;
|
||||
bool GetOpenDocumentParams(AZStd::string& openPath) override;
|
||||
void OpenSettings() override;
|
||||
void OpenHelp() override;
|
||||
|
||||
void closeEvent(QCloseEvent* closeEvent) override;
|
||||
|
||||
MaterialViewportWidget* m_materialViewport = nullptr;
|
||||
MaterialEditorToolBar* m_toolBar = nullptr;
|
||||
|
||||
QMenu* m_menuFile = {};
|
||||
QAction* m_actionNew = {};
|
||||
QAction* m_actionOpen = {};
|
||||
QAction* m_actionOpenRecent = {};
|
||||
QAction* m_actionClose = {};
|
||||
QAction* m_actionCloseAll = {};
|
||||
QAction* m_actionCloseOthers = {};
|
||||
QAction* m_actionSave = {};
|
||||
QAction* m_actionSaveAsCopy = {};
|
||||
QAction* m_actionSaveAsChild = {};
|
||||
QAction* m_actionSaveAll = {};
|
||||
QAction* m_actionExit = {};
|
||||
|
||||
QMenu* m_menuEdit = {};
|
||||
QAction* m_actionUndo = {};
|
||||
QAction* m_actionRedo = {};
|
||||
QAction* m_actionSettings = {};
|
||||
|
||||
QMenu* m_menuView = {};
|
||||
QAction* m_actionAssetBrowser = {};
|
||||
QAction* m_actionInspector = {};
|
||||
QAction* m_actionConsole = {};
|
||||
QAction* m_actionPythonTerminal = {};
|
||||
QAction* m_actionPerfMonitor = {};
|
||||
QAction* m_actionViewportSettings = {};
|
||||
QAction* m_actionNextTab = {};
|
||||
QAction* m_actionPreviousTab = {};
|
||||
|
||||
QMenu* m_menuHelp = {};
|
||||
QAction* m_actionHelp = {};
|
||||
QAction* m_actionAbout = {};
|
||||
};
|
||||
} // namespace MaterialEditor
|
||||
|
||||
+26
-353
@@ -5,24 +5,15 @@
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/Name/Name.h>
|
||||
#include <AzFramework/StringFunc/StringFunc.h>
|
||||
#include <AzQtComponents/Components/StyleManager.h>
|
||||
#include <AzQtComponents/Components/WindowDecorationWrapper.h>
|
||||
#include <AzToolsFramework/API/EditorPythonRunnerRequestsBus.h>
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
||||
#include <AzToolsFramework/PythonTerminal/ScriptTermDialog.h>
|
||||
#include <AtomToolsFramework/Util/Util.h>
|
||||
#include <AtomToolsFramework/Window/AtomToolsMainWindowNotificationBus.h>
|
||||
|
||||
#include <Atom/Document/ShaderManagementConsoleDocumentRequestBus.h>
|
||||
#include <AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h>
|
||||
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
|
||||
#include <AtomToolsFramework/Util/Util.h>
|
||||
#include <AzCore/Name/Name.h>
|
||||
#include <AzQtComponents/Components/WindowDecorationWrapper.h>
|
||||
#include <AzToolsFramework/PythonTerminal/ScriptTermDialog.h>
|
||||
#include <Window/ShaderManagementConsoleWindow.h>
|
||||
|
||||
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
|
||||
#include <QCloseEvent>
|
||||
#include <QFileDialog>
|
||||
#include <QHeaderView>
|
||||
#include <QStandardItemModel>
|
||||
#include <QTableView>
|
||||
@@ -32,7 +23,7 @@ AZ_POP_DISABLE_WARNING
|
||||
namespace ShaderManagementConsole
|
||||
{
|
||||
ShaderManagementConsoleWindow::ShaderManagementConsoleWindow(QWidget* parent /* = 0 */)
|
||||
: AtomToolsFramework::AtomToolsMainWindow(parent)
|
||||
: AtomToolsFramework::AtomToolsDocumentMainWindow(parent)
|
||||
{
|
||||
resize(1280, 1024);
|
||||
|
||||
@@ -50,9 +41,6 @@ namespace ShaderManagementConsole
|
||||
m_toolBar->setObjectName("ToolBar");
|
||||
addToolBar(m_toolBar);
|
||||
|
||||
CreateMenu();
|
||||
CreateTabBar();
|
||||
|
||||
AddDockWidget("Asset Browser", new ShaderManagementConsoleBrowserWidget, Qt::BottomDockWidgetArea, Qt::Vertical);
|
||||
AddDockWidget("Python Terminal", new AzToolsFramework::CScriptTermDialog, Qt::BottomDockWidgetArea, Qt::Horizontal);
|
||||
|
||||
@@ -61,356 +49,36 @@ namespace ShaderManagementConsole
|
||||
// Restore geometry and show the window
|
||||
mainWindowWrapper->showFromSettings();
|
||||
|
||||
AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect();
|
||||
// Disable unused actions
|
||||
m_actionNew->setVisible(false);
|
||||
m_actionNew->setEnabled(false);
|
||||
m_actionSaveAsChild->setVisible(false);
|
||||
m_actionSaveAsChild->setEnabled(false);
|
||||
|
||||
OnDocumentOpened(AZ::Uuid::CreateNull());
|
||||
}
|
||||
|
||||
ShaderManagementConsoleWindow::~ShaderManagementConsoleWindow()
|
||||
{
|
||||
AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void ShaderManagementConsoleWindow::closeEvent(QCloseEvent* closeEvent)
|
||||
{
|
||||
bool didClose = true;
|
||||
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(didClose, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseAllDocuments);
|
||||
if (!didClose)
|
||||
{
|
||||
closeEvent->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
AtomToolsFramework::AtomToolsMainWindowNotificationBus::Broadcast(
|
||||
&AtomToolsFramework::AtomToolsMainWindowNotifications::OnMainWindowClosing);
|
||||
}
|
||||
|
||||
void ShaderManagementConsoleWindow::OnDocumentOpened(const AZ::Uuid& documentId)
|
||||
{
|
||||
bool isOpen = false;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isOpen, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsOpen);
|
||||
bool isSavable = false;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isSavable, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsSavable);
|
||||
bool isModified = false;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isModified, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsModified);
|
||||
bool canUndo = false;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(canUndo, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::CanUndo);
|
||||
bool canRedo = false;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(canRedo, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::CanRedo);
|
||||
AZStd::string absolutePath;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
|
||||
AZStd::string filename;
|
||||
AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename);
|
||||
|
||||
// Update UI to display the new document
|
||||
if (!documentId.IsNull() && isOpen)
|
||||
{
|
||||
// Create a new tab for the document ID and assign it's label to the file name of the document.
|
||||
AddTabForDocumentId(documentId, filename, absolutePath, [this, documentId]{
|
||||
// The document tab contains a table view.
|
||||
auto contentWidget = new QTableView(centralWidget());
|
||||
contentWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
contentWidget->setModel(CreateDocumentContent(documentId));
|
||||
return contentWidget;
|
||||
});
|
||||
}
|
||||
|
||||
UpdateTabForDocumentId(documentId, filename, absolutePath, isModified);
|
||||
|
||||
const bool hasTabs = m_tabWidget->count() > 0;
|
||||
|
||||
// Update menu options
|
||||
m_actionOpen->setEnabled(true);
|
||||
m_actionOpenRecent->setEnabled(false);
|
||||
m_actionClose->setEnabled(hasTabs);
|
||||
m_actionCloseAll->setEnabled(hasTabs);
|
||||
m_actionCloseOthers->setEnabled(hasTabs);
|
||||
|
||||
m_actionSave->setEnabled(isOpen && isSavable);
|
||||
m_actionSaveAsCopy->setEnabled(isOpen && isSavable);
|
||||
m_actionSaveAll->setEnabled(hasTabs);
|
||||
|
||||
m_actionExit->setEnabled(true);
|
||||
|
||||
m_actionUndo->setEnabled(canUndo);
|
||||
m_actionRedo->setEnabled(canRedo);
|
||||
m_actionSettings->setEnabled(false);
|
||||
|
||||
m_actionAssetBrowser->setEnabled(true);
|
||||
m_actionPythonTerminal->setEnabled(true);
|
||||
m_actionPreviousTab->setEnabled(m_tabWidget->count() > 1);
|
||||
m_actionNextTab->setEnabled(m_tabWidget->count() > 1);
|
||||
|
||||
m_actionHelp->setEnabled(false);
|
||||
m_actionAbout->setEnabled(false);
|
||||
|
||||
activateWindow();
|
||||
raise();
|
||||
|
||||
const QString documentPath = GetDocumentPath(documentId);
|
||||
if (!documentPath.isEmpty())
|
||||
{
|
||||
SetStatusMessage(tr("Document opened: %1").arg(documentPath));
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderManagementConsoleWindow::OnDocumentClosed(const AZ::Uuid& documentId)
|
||||
{
|
||||
RemoveTabForDocumentId(documentId);
|
||||
SetStatusMessage(tr("Document closed: %1").arg(GetDocumentPath(documentId)));
|
||||
}
|
||||
|
||||
void ShaderManagementConsoleWindow::OnDocumentModified(const AZ::Uuid& documentId)
|
||||
{
|
||||
bool isModified = false;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isModified, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsModified);
|
||||
AZStd::string absolutePath;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
|
||||
AZStd::string filename;
|
||||
AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename);
|
||||
UpdateTabForDocumentId(documentId, filename, absolutePath, isModified);
|
||||
}
|
||||
|
||||
void ShaderManagementConsoleWindow::OnDocumentUndoStateChanged(const AZ::Uuid& documentId)
|
||||
{
|
||||
if (documentId == GetDocumentIdFromTab(m_tabWidget->currentIndex()))
|
||||
{
|
||||
bool canUndo = false;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(canUndo, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::CanUndo);
|
||||
bool canRedo = false;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(canRedo, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::CanRedo);
|
||||
m_actionUndo->setEnabled(canUndo);
|
||||
m_actionRedo->setEnabled(canRedo);
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderManagementConsoleWindow::OnDocumentSaved(const AZ::Uuid& documentId)
|
||||
{
|
||||
bool isModified = false;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isModified, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsModified);
|
||||
AZStd::string absolutePath;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
|
||||
AZStd::string filename;
|
||||
AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename);
|
||||
UpdateTabForDocumentId(documentId, filename, absolutePath, isModified);
|
||||
SetStatusMessage(tr("Document saved: %1").arg(GetDocumentPath(documentId)));
|
||||
}
|
||||
|
||||
void ShaderManagementConsoleWindow::CreateMenu()
|
||||
{
|
||||
Base::CreateMenu();
|
||||
|
||||
// Generating the main menu manually because it's easier and we will have some dynamic or data driven entries
|
||||
m_menuFile = menuBar()->addMenu("&File");
|
||||
|
||||
m_actionOpen = m_menuFile->addAction("&Open...", [this]() {
|
||||
const AZStd::vector<AZ::Data::AssetType> assetTypes = {
|
||||
};
|
||||
|
||||
const AZStd::string filePath = AtomToolsFramework::GetOpenFileInfo(assetTypes).absoluteFilePath().toUtf8().constData();
|
||||
if (!filePath.empty())
|
||||
{
|
||||
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, filePath);
|
||||
}
|
||||
}, QKeySequence::Open);
|
||||
|
||||
m_actionOpenRecent = m_menuFile->addAction("Open &Recent");
|
||||
|
||||
m_menuFile->addSeparator();
|
||||
|
||||
m_actionSave = m_menuFile->addAction("&Save", [this]() {
|
||||
const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex());
|
||||
bool result = false;
|
||||
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::SaveDocument, documentId);
|
||||
if (!result)
|
||||
{
|
||||
SetStatusError(tr("Document save failed: %1").arg(GetDocumentPath(documentId)));
|
||||
}
|
||||
}, QKeySequence::Save);
|
||||
|
||||
m_actionSaveAsCopy = m_menuFile->addAction("Save &As...", [this]() {
|
||||
const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex());
|
||||
const QString documentPath = GetDocumentPath(documentId);
|
||||
|
||||
bool result = false;
|
||||
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::SaveDocumentAsCopy,
|
||||
documentId, AtomToolsFramework::GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData());
|
||||
if (!result)
|
||||
{
|
||||
SetStatusError(tr("Document save failed: %1").arg(GetDocumentPath(documentId)));
|
||||
}
|
||||
}, QKeySequence::SaveAs);
|
||||
|
||||
m_actionSaveAll = m_menuFile->addAction("Save A&ll", [this]() {
|
||||
bool result = false;
|
||||
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::SaveAllDocuments);
|
||||
if (!result)
|
||||
{
|
||||
SetStatusError(tr("Document save all failed"));
|
||||
}
|
||||
});
|
||||
|
||||
m_menuFile->addSeparator();
|
||||
|
||||
m_actionClose = m_menuFile->addAction("&Close", [this]() {
|
||||
const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex());
|
||||
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId);
|
||||
}, QKeySequence::Close);
|
||||
|
||||
m_actionCloseAll = m_menuFile->addAction("Close All", [this]() {
|
||||
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseAllDocuments);
|
||||
});
|
||||
|
||||
m_actionCloseOthers = m_menuFile->addAction("Close Others", [this]() {
|
||||
const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex());
|
||||
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId);
|
||||
});
|
||||
|
||||
m_menuFile->addSeparator();
|
||||
|
||||
m_menuFile->addAction("Run &Python...", [this]() {
|
||||
const QString script = QFileDialog::getOpenFileName(this, "Run Script", QString(), QString("*.py"));
|
||||
if (!script.isEmpty())
|
||||
{
|
||||
AzToolsFramework::EditorPythonRunnerRequestBus::Broadcast(&AzToolsFramework::EditorPythonRunnerRequestBus::Events::ExecuteByFilename, script.toUtf8().constData());
|
||||
}
|
||||
});
|
||||
|
||||
m_menuFile->addSeparator();
|
||||
|
||||
m_actionExit = m_menuFile->addAction("E&xit", [this]() {
|
||||
close();
|
||||
}, QKeySequence::Quit);
|
||||
|
||||
m_menuEdit = menuBar()->addMenu("&Edit");
|
||||
|
||||
m_actionUndo = m_menuEdit->addAction("&Undo", [this]() {
|
||||
const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex());
|
||||
bool result = false;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::Undo);
|
||||
if (!result)
|
||||
{
|
||||
SetStatusError(tr("Document undo failed: %1").arg(GetDocumentPath(documentId)));
|
||||
}
|
||||
}, QKeySequence::Undo);
|
||||
|
||||
m_actionRedo = m_menuEdit->addAction("&Redo", [this]() {
|
||||
const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex());
|
||||
bool result = false;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::Redo);
|
||||
if (!result)
|
||||
{
|
||||
SetStatusError(tr("Document redo failed: %1").arg(GetDocumentPath(documentId)));
|
||||
}
|
||||
}, QKeySequence::Redo);
|
||||
|
||||
m_menuEdit->addSeparator();
|
||||
|
||||
m_actionSettings = m_menuEdit->addAction("&Settings...", [this]() {
|
||||
}, QKeySequence::Preferences);
|
||||
m_actionSettings->setEnabled(false);
|
||||
|
||||
m_menuView = menuBar()->addMenu("&View");
|
||||
|
||||
m_actionAssetBrowser = m_menuView->addAction("&Asset Browser", [this]() {
|
||||
const AZStd::string label = "Asset Browser";
|
||||
SetDockWidgetVisible(label, !IsDockWidgetVisible(label));
|
||||
});
|
||||
|
||||
m_actionPythonTerminal = m_menuView->addAction("Python &Terminal", [this]() {
|
||||
const AZStd::string label = "Python Terminal";
|
||||
SetDockWidgetVisible(label, !IsDockWidgetVisible(label));
|
||||
});
|
||||
|
||||
|
||||
m_menuView->addSeparator();
|
||||
|
||||
m_actionPreviousTab = m_menuView->addAction("&Previous Tab", [this]() {
|
||||
SelectPreviousTab();
|
||||
}, Qt::CTRL | Qt::SHIFT | Qt::Key_Tab); //QKeySequence::PreviousChild is mapped incorrectly in Qt
|
||||
|
||||
m_actionNextTab = m_menuView->addAction("&Next Tab", [this]() {
|
||||
SelectNextTab();
|
||||
}, Qt::CTRL | Qt::Key_Tab); //QKeySequence::NextChild works as expected but mirroring Previous
|
||||
|
||||
m_menuHelp = menuBar()->addMenu("&Help");
|
||||
|
||||
m_actionHelp = m_menuHelp->addAction("&Help...", [this]() {
|
||||
});
|
||||
|
||||
m_actionAbout = m_menuHelp->addAction("&About...", [this]() {
|
||||
});
|
||||
}
|
||||
|
||||
void ShaderManagementConsoleWindow::CreateTabBar()
|
||||
{
|
||||
Base::CreateTabBar();
|
||||
|
||||
// This signal will be triggered whenever a tab is added, removed, selected, clicked, dragged
|
||||
// When the last tab is removed tabIndex will be -1 and the document ID will be null
|
||||
// This should automatically clear the active document
|
||||
connect(m_tabWidget, &QTabWidget::currentChanged, this, [this](int tabIndex) {
|
||||
const AZ::Uuid documentId = GetDocumentIdFromTab(tabIndex);
|
||||
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, documentId);
|
||||
});
|
||||
|
||||
connect(m_tabWidget, &QTabWidget::tabCloseRequested, this, [this](int tabIndex) {
|
||||
const AZ::Uuid documentId = GetDocumentIdFromTab(tabIndex);
|
||||
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId);
|
||||
});
|
||||
}
|
||||
|
||||
QString ShaderManagementConsoleWindow::GetDocumentPath(const AZ::Uuid& documentId) const
|
||||
{
|
||||
AZStd::string absolutePath;
|
||||
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Handler::GetAbsolutePath);
|
||||
return absolutePath.c_str();
|
||||
}
|
||||
|
||||
void ShaderManagementConsoleWindow::OpenTabContextMenu()
|
||||
{
|
||||
const QTabBar* tabBar = m_tabWidget->tabBar();
|
||||
const QPoint position = tabBar->mapFromGlobal(QCursor::pos());
|
||||
const int clickedTabIndex = tabBar->tabAt(position);
|
||||
const int currentTabIndex = tabBar->currentIndex();
|
||||
if (clickedTabIndex >= 0)
|
||||
{
|
||||
QMenu tabMenu;
|
||||
const QString selectActionName = (currentTabIndex == clickedTabIndex) ? "Select in Browser" : "Select";
|
||||
tabMenu.addAction(selectActionName, [this, clickedTabIndex]() {
|
||||
const AZ::Uuid documentId = GetDocumentIdFromTab(clickedTabIndex);
|
||||
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, documentId);
|
||||
});
|
||||
tabMenu.addAction("Close", [this, clickedTabIndex]() {
|
||||
const AZ::Uuid documentId = GetDocumentIdFromTab(clickedTabIndex);
|
||||
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId);
|
||||
});
|
||||
auto closeOthersAction = tabMenu.addAction("Close Others", [this, clickedTabIndex]() {
|
||||
const AZ::Uuid documentId = GetDocumentIdFromTab(clickedTabIndex);
|
||||
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId);
|
||||
});
|
||||
closeOthersAction->setEnabled(tabBar->count() > 1);
|
||||
tabMenu.exec(QCursor::pos());
|
||||
}
|
||||
}
|
||||
|
||||
QStandardItemModel* ShaderManagementConsoleWindow::CreateDocumentContent(const AZ::Uuid& documentId)
|
||||
QWidget* ShaderManagementConsoleWindow::CreateDocumentTabView(const AZ::Uuid& documentId)
|
||||
{
|
||||
AZStd::unordered_set<AZStd::string> optionNames;
|
||||
|
||||
size_t shaderOptionCount = 0;
|
||||
ShaderManagementConsoleDocumentRequestBus::EventResult(shaderOptionCount, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderOptionCount);
|
||||
ShaderManagementConsoleDocumentRequestBus::EventResult(
|
||||
shaderOptionCount, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderOptionCount);
|
||||
|
||||
for (size_t optionIndex = 0; optionIndex < shaderOptionCount; ++optionIndex)
|
||||
{
|
||||
AZ::RPI::ShaderOptionDescriptor shaderOptionDesc;
|
||||
ShaderManagementConsoleDocumentRequestBus::EventResult(shaderOptionDesc, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderOptionDescriptor, optionIndex);
|
||||
ShaderManagementConsoleDocumentRequestBus::EventResult(
|
||||
shaderOptionDesc, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderOptionDescriptor, optionIndex);
|
||||
|
||||
const char* optionName = shaderOptionDesc.GetName().GetCStr();
|
||||
optionNames.insert(optionName);
|
||||
}
|
||||
|
||||
size_t shaderVariantCount = 0;
|
||||
ShaderManagementConsoleDocumentRequestBus::EventResult(shaderVariantCount, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderVariantCount);
|
||||
ShaderManagementConsoleDocumentRequestBus::EventResult(
|
||||
shaderVariantCount, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderVariantCount);
|
||||
|
||||
auto model = new QStandardItemModel();
|
||||
model->setRowCount(static_cast<int>(shaderVariantCount));
|
||||
@@ -425,7 +93,8 @@ namespace ShaderManagementConsole
|
||||
for (int variantIndex = 0; variantIndex < shaderVariantCount; ++variantIndex)
|
||||
{
|
||||
AZ::RPI::ShaderVariantListSourceData::VariantInfo shaderVariantInfo;
|
||||
ShaderManagementConsoleDocumentRequestBus::EventResult(shaderVariantInfo, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderVariantInfo, variantIndex);
|
||||
ShaderManagementConsoleDocumentRequestBus::EventResult(
|
||||
shaderVariantInfo, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderVariantInfo, variantIndex);
|
||||
|
||||
model->setHeaderData(variantIndex, Qt::Vertical, QString::number(variantIndex));
|
||||
|
||||
@@ -442,7 +111,11 @@ namespace ShaderManagementConsole
|
||||
}
|
||||
}
|
||||
|
||||
return model;
|
||||
// The document tab contains a table view.
|
||||
auto contentWidget = new QTableView(centralWidget());
|
||||
contentWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
contentWidget->setModel(model);
|
||||
return contentWidget;
|
||||
}
|
||||
} // namespace ShaderManagementConsole
|
||||
|
||||
|
||||
+8
-56
@@ -11,9 +11,7 @@
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <Atom/RPI.Edit/Shader/ShaderVariantListSourceData.h>
|
||||
#include <Atom/RPI.Public/Shader/Shader.h>
|
||||
#include <AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h>
|
||||
#include <AtomToolsFramework/Window/AtomToolsMainWindow.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AtomToolsFramework/Document/AtomToolsDocumentMainWindow.h>
|
||||
|
||||
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
|
||||
#include <Window/ShaderManagementConsoleBrowserWidget.h>
|
||||
@@ -25,69 +23,23 @@ AZ_POP_DISABLE_WARNING
|
||||
|
||||
namespace ShaderManagementConsole
|
||||
{
|
||||
/**
|
||||
* ShaderManagementConsoleWindow is the main class. Its responsibility is limited to initializing and connecting
|
||||
* its panels, managing selection of assets, and performing high-level actions like saving. It contains...
|
||||
*/
|
||||
//! ShaderManagementConsoleWindow is the main class. Its responsibility is limited to initializing and connecting
|
||||
//! its panels, managing selection of assets, and performing high-level actions like saving. It contains...
|
||||
class ShaderManagementConsoleWindow
|
||||
: public AtomToolsFramework::AtomToolsMainWindow
|
||||
, private AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler
|
||||
: public AtomToolsFramework::AtomToolsDocumentMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(ShaderManagementConsoleWindow, AZ::SystemAllocator, 0);
|
||||
|
||||
using Base = AtomToolsFramework::AtomToolsMainWindow;
|
||||
using Base = AtomToolsFramework::AtomToolsDocumentMainWindow;
|
||||
|
||||
ShaderManagementConsoleWindow(QWidget* parent = 0);
|
||||
~ShaderManagementConsoleWindow();
|
||||
~ShaderManagementConsoleWindow() = default;
|
||||
|
||||
private:
|
||||
// AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler overrides...
|
||||
void OnDocumentOpened(const AZ::Uuid& documentId) override;
|
||||
void OnDocumentClosed(const AZ::Uuid& documentId) override;
|
||||
void OnDocumentModified(const AZ::Uuid& documentId) override;
|
||||
void OnDocumentUndoStateChanged(const AZ::Uuid& documentId) override;
|
||||
void OnDocumentSaved(const AZ::Uuid& documentId) override;
|
||||
|
||||
void CreateMenu() override;
|
||||
void CreateTabBar() override;
|
||||
|
||||
QString GetDocumentPath(const AZ::Uuid& documentId) const;
|
||||
|
||||
void OpenTabContextMenu() override;
|
||||
|
||||
void closeEvent(QCloseEvent* closeEvent) override;
|
||||
|
||||
QStandardItemModel* CreateDocumentContent(const AZ::Uuid& documentId);
|
||||
protected:
|
||||
QWidget* CreateDocumentTabView(const AZ::Uuid& documentId) override;
|
||||
|
||||
ShaderManagementConsoleToolBar* m_toolBar = nullptr;
|
||||
|
||||
QMenu* m_menuFile = {};
|
||||
QMenu* m_menuNew = {};
|
||||
QAction* m_actionOpen = {};
|
||||
QAction* m_actionOpenRecent = {};
|
||||
QAction* m_actionClose = {};
|
||||
QAction* m_actionCloseAll = {};
|
||||
QAction* m_actionCloseOthers = {};
|
||||
QAction* m_actionSave = {};
|
||||
QAction* m_actionSaveAsCopy = {};
|
||||
QAction* m_actionSaveAll = {};
|
||||
QAction* m_actionExit = {};
|
||||
|
||||
QMenu* m_menuEdit = {};
|
||||
QAction* m_actionUndo = {};
|
||||
QAction* m_actionRedo = {};
|
||||
QAction* m_actionSettings = {};
|
||||
|
||||
QMenu* m_menuView = {};
|
||||
QAction* m_actionAssetBrowser = {};
|
||||
QAction* m_actionPythonTerminal = {};
|
||||
QAction* m_actionNextTab = {};
|
||||
QAction* m_actionPreviousTab = {};
|
||||
|
||||
QMenu* m_menuHelp = {};
|
||||
QAction* m_actionHelp = {};
|
||||
QAction* m_actionAbout = {};
|
||||
};
|
||||
} // namespace ShaderManagementConsole
|
||||
|
||||
Reference in New Issue
Block a user