updated ME and SMC main window classes to use AtomToolsDocumentMainWindow

separated common and document menu creation

Signed-off-by: Guthrie Adams <guthadam@amazon.com>
This commit is contained in:
Guthrie Adams
2021-08-22 22:37:50 -05:00
parent 62a5c90616
commit 78f90f2707
8 changed files with 204 additions and 936 deletions
@@ -53,13 +53,10 @@ namespace AtomToolsFramework
void SelectNextTab();
virtual void OpenTabContextMenu() const;
virtual bool GetCreateFileInfo(AZStd::string& openPath, AZStd::string& savePath) const;
virtual bool GetOpenFileInfo(AZStd::string& openPath) const;
virtual QWidget* CreateViewForDocumemt(const AZ::Uuid& documentId) const;
virtual void OpenSettings() const;
virtual void OpenHelp() const;
virtual void OpenAbout() const;
virtual void OpenTabContextMenu();
virtual bool GetCreateFileInfo(AZStd::string& openPath, AZStd::string& savePath);
virtual bool GetOpenFileInfo(AZStd::string& openPath);
virtual QWidget* CreateViewForDocumemt(const AZ::Uuid& documentId);
// AtomToolsDocumentNotificationBus::Handler overrides...
void OnDocumentOpened(const AZ::Uuid& documentId) override;
@@ -70,10 +67,11 @@ namespace AtomToolsFramework
void closeEvent(QCloseEvent* closeEvent) override;
QMenu* m_menuFile = {};
template<typename Functor>
QAction* CreateAction(const QString& text, Functor functor, const QKeySequence& shortcut = 0);
QAction* m_actionNew = {};
QAction* m_actionOpen = {};
QAction* m_actionOpenRecent = {};
QAction* m_actionClose = {};
QAction* m_actionCloseAll = {};
QAction* m_actionCloseOthers = {};
@@ -81,20 +79,13 @@ namespace AtomToolsFramework
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_actionNextTab = {};
QAction* m_actionPreviousTab = {};
QMenu* m_menuHelp = {};
QAction* m_actionHelp = {};
QAction* m_actionAbout = {};
AzQtComponents::TabWidget* m_tabWidget = {};
};
} // namespace AtomToolsFramework
@@ -38,8 +38,20 @@ namespace AtomToolsFramework
void SetStatusWarning(const QString& message);
void SetStatusError(const QString& message);
AzQtComponents::FancyDocking* m_advancedDockManager = 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;
};
@@ -12,15 +12,11 @@
#include <AtomToolsFramework/Util/Util.h>
#include <AtomToolsFramework/Window/AtomToolsMainWindowNotificationBus.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/API/EditorPythonRunnerRequestsBus.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QApplication>
#include <QByteArray>
#include <QCloseEvent>
#include <QDesktopWidget>
#include <QFileDialog>
#include <QLayout>
#include <QMenu>
#include <QMenuBar>
@@ -45,10 +41,10 @@ namespace AtomToolsFramework
void AtomToolsDocumentMainWindow::AddDocumentMenus()
{
// Generating the main menu manually because it's easier and we will have some dynamic or data driven entries
m_menuFile = menuBar()->addMenu("&File");
QAction* insertPostion = !m_menuFile->actions().empty() ? m_menuFile->actions().front() : nullptr;
m_actionNew = m_menuFile->addAction("&New...", [this]() {
// 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 (GetCreateFileInfo(openPath, savePath))
@@ -57,20 +53,19 @@ namespace AtomToolsFramework
&AtomToolsDocumentSystemRequestBus::Events::CreateDocumentFromFile, openPath, savePath);
}
}, QKeySequence::New);
m_menuFile->insertAction(insertPostion, m_actionNew);
m_actionOpen = m_menuFile->addAction("&Open...", [this]() {
m_actionOpen = CreateAction("&Open...", [this]() {
AZStd::string openPath;
if (GetOpenFileInfo(openPath))
{
AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::OpenDocument, openPath);
}
}, QKeySequence::Open);
m_menuFile->insertAction(insertPostion, m_actionOpen);
m_menuFile->insertSeparator(insertPostion);
m_actionOpenRecent = m_menuFile->addAction("Open &Recent");
m_menuFile->addSeparator();
m_actionSave = m_menuFile->addAction("&Save", [this]() {
m_actionSave = CreateAction("&Save", [this]() {
const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex());
bool result = false;
AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsDocumentSystemRequestBus::Events::SaveDocument, documentId);
@@ -79,8 +74,9 @@ namespace AtomToolsFramework
SetStatusError(tr("Document save failed: %1").arg(GetDocumentPath(documentId)));
}
}, QKeySequence::Save);
m_menuFile->insertAction(insertPostion, m_actionSave);
m_actionSaveAsCopy = m_menuFile->addAction("Save &As...", [this]() {
m_actionSaveAsCopy = CreateAction("Save &As...", [this]() {
const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex());
const QString documentPath = GetDocumentPath(documentId);
@@ -92,8 +88,9 @@ namespace AtomToolsFramework
SetStatusError(tr("Document save failed: %1").arg(GetDocumentPath(documentId)));
}
}, QKeySequence::SaveAs);
m_menuFile->insertAction(insertPostion, m_actionSaveAsCopy);
m_actionSaveAsChild = m_menuFile->addAction("Save As &Child...", [this]() {
m_actionSaveAsChild = CreateAction("Save As &Child...", [this]() {
const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex());
const QString documentPath = GetDocumentPath(documentId);
@@ -105,8 +102,9 @@ namespace AtomToolsFramework
SetStatusError(tr("Document save failed: %1").arg(GetDocumentPath(documentId)));
}
});
m_menuFile->insertAction(insertPostion, m_actionSaveAsChild);
m_actionSaveAll = m_menuFile->addAction("Save A&ll", [this]() {
m_actionSaveAll = CreateAction("Save A&ll", [this]() {
bool result = false;
AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsDocumentSystemRequestBus::Events::SaveAllDocuments);
if (!result)
@@ -114,42 +112,30 @@ namespace AtomToolsFramework
SetStatusError(tr("Document save all failed"));
}
});
m_menuFile->insertAction(insertPostion, m_actionSaveAll);
m_menuFile->insertSeparator(insertPostion);
m_menuFile->addSeparator();
m_actionClose = m_menuFile->addAction("&Close", [this]() {
m_actionClose = CreateAction("&Close", [this]() {
const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex());
AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId);
}, QKeySequence::Close);
m_menuFile->insertAction(insertPostion, m_actionClose);
m_actionCloseAll = m_menuFile->addAction("Close All", [this]() {
m_actionCloseAll = CreateAction("Close All", [this]() {
AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::CloseAllDocuments);
});
m_menuFile->insertAction(insertPostion, m_actionCloseAll);
m_actionCloseOthers = m_menuFile->addAction("Close Others", [this]() {
m_actionCloseOthers = CreateAction("Close Others", [this]() {
const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex());
AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId);
});
m_menuFile->insertAction(insertPostion, m_actionCloseOthers);
m_menuFile->insertSeparator(insertPostion);
m_menuFile->addSeparator();
insertPostion = !m_menuEdit->actions().empty() ? m_menuEdit->actions().front() : nullptr;
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]() {
m_actionUndo = CreateAction("&Undo", [this]() {
const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex());
bool result = false;
AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsDocumentRequestBus::Events::Undo);
@@ -158,8 +144,9 @@ namespace AtomToolsFramework
SetStatusError(tr("Document undo failed: %1").arg(GetDocumentPath(documentId)));
}
}, QKeySequence::Undo);
m_menuEdit->insertAction(insertPostion, m_actionUndo);
m_actionRedo = m_menuEdit->addAction("&Redo", [this]() {
m_actionRedo = CreateAction("&Redo", [this]() {
const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex());
bool result = false;
AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsDocumentRequestBus::Events::Redo);
@@ -168,34 +155,24 @@ namespace AtomToolsFramework
SetStatusError(tr("Document redo failed: %1").arg(GetDocumentPath(documentId)));
}
}, QKeySequence::Redo);
m_menuEdit->insertAction(insertPostion, m_actionRedo);
m_menuEdit->insertSeparator(insertPostion);
m_menuEdit->addSeparator();
insertPostion = !m_menuView->actions().empty() ? m_menuView->actions().front() : nullptr;
m_actionSettings = m_menuEdit->addAction("&Settings...", [this]() {
OpenSettings();
}, QKeySequence::Preferences);
m_menuView = menuBar()->addMenu("&View");
m_menuView->addSeparator();
m_actionPreviousTab = m_menuView->addAction("&Previous Tab", [this]() {
m_actionPreviousTab = CreateAction(
"&Previous Tab",
[this]()
{
SelectPreviousTab();
}, Qt::CTRL | Qt::SHIFT | Qt::Key_Tab); //QKeySequence::PreviousChild is mapped incorrectly in Qt
m_menuView->insertAction(insertPostion, m_actionPreviousTab);
m_actionNextTab = m_menuView->addAction("&Next Tab", [this]() {
m_actionNextTab = CreateAction("&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]() {
OpenHelp();
});
m_actionAbout = m_menuHelp->addAction("&About...", [this]() {
OpenAbout();
});
m_menuView->insertAction(insertPostion, m_actionNextTab);
m_menuView->insertSeparator(insertPostion);
}
void AtomToolsDocumentMainWindow::AddDocumentTabBar()
@@ -343,7 +320,7 @@ namespace AtomToolsFramework
}
}
void AtomToolsDocumentMainWindow::OpenTabContextMenu() const
void AtomToolsDocumentMainWindow::OpenTabContextMenu()
{
const QTabBar* tabBar = m_tabWidget->tabBar();
const QPoint position = tabBar->mapFromGlobal(QCursor::pos());
@@ -370,20 +347,20 @@ namespace AtomToolsFramework
}
}
inline bool AtomToolsDocumentMainWindow::GetCreateFileInfo(AZStd::string& openPath, AZStd::string& savePath) const
inline bool AtomToolsDocumentMainWindow::GetCreateFileInfo(AZStd::string& openPath, AZStd::string& savePath)
{
AZ_UNUSED(openPath);
AZ_UNUSED(savePath);
return false;
}
inline bool AtomToolsDocumentMainWindow::GetOpenFileInfo(AZStd::string& openPath) const
inline bool AtomToolsDocumentMainWindow::GetOpenFileInfo(AZStd::string& openPath)
{
AZ_UNUSED(openPath);
return false;
}
inline QWidget* AtomToolsDocumentMainWindow::CreateViewForDocumemt(const AZ::Uuid& documentId) const
inline QWidget* AtomToolsDocumentMainWindow::CreateViewForDocumemt(const AZ::Uuid& documentId)
{
AZ_UNUSED(documentId);
auto contentWidget = new QWidget(centralWidget());
@@ -392,18 +369,6 @@ namespace AtomToolsFramework
return contentWidget;
}
inline void AtomToolsDocumentMainWindow::OpenSettings() const
{
}
inline void AtomToolsDocumentMainWindow::OpenHelp() const
{
}
inline void AtomToolsDocumentMainWindow::OpenAbout() const
{
}
void AtomToolsDocumentMainWindow::OnDocumentOpened(const AZ::Uuid& documentId)
{
bool isOpen = false;
@@ -434,7 +399,6 @@ namespace AtomToolsFramework
// 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);
@@ -444,17 +408,12 @@ namespace AtomToolsFramework
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_actionPreviousTab->setEnabled(m_tabWidget->count() > 1);
m_actionNextTab->setEnabled(m_tabWidget->count() > 1);
m_actionAbout->setEnabled(false);
activateWindow();
raise();
@@ -520,6 +479,15 @@ namespace AtomToolsFramework
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,10 @@
*/
#include <AtomToolsFramework/Window/AtomToolsMainWindow.h>
#include <AzToolsFramework/API/EditorPythonRunnerRequestsBus.h>
#include <QFileDialog>
#include <QMenu>
#include <QMenuBar>
#include <QStatusBar>
#include <QVBoxLayout>
@@ -24,13 +28,11 @@ namespace AtomToolsFramework
setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea);
setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
AddCommonMenus();
m_statusMessage = new QLabel(statusBar());
statusBar()->addPermanentWidget(m_statusMessage, 1);
auto menuBar = new QMenuBar(this);
menuBar->setObjectName("MenuBar");
setMenuBar(menuBar);
auto centralWidget = new QWidget(this);
auto centralWidgetLayout = new QVBoxLayout(centralWidget);
centralWidgetLayout->setMargin(0);
@@ -127,4 +129,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
@@ -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,15 +95,12 @@ 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)
{
@@ -146,16 +133,56 @@ namespace MaterialEditor
m_materialViewport->UnlockRenderTargetSize();
}
bool MaterialEditorWindow::GetCreateFileInfo(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::GetOpenFileInfo(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();
}
QWidget* MaterialEditorWindow::CreateViewForDocumemt(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 MaterialEditorWindow::OpenSettings()
{
SettingsDialog dialog(this);
dialog.exec();
}
void MaterialEditorWindow::OpenHelp()
{
HelpDialog dialog(this);
dialog.exec();
}
void MaterialEditorWindow::OpenAbout()
{
}
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 +190,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>
@@ -29,72 +27,32 @@ namespace MaterialEditor
* 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();
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 GetCreateFileInfo(AZStd::string& openPath, AZStd::string& savePath) override;
bool GetOpenFileInfo(AZStd::string& openPath) override;
QWidget* CreateViewForDocumemt(const AZ::Uuid& documentId) override;
void OpenSettings() override;
void OpenHelp() override;
void OpenAbout() 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
@@ -7,22 +7,13 @@
*/
#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 <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,34 @@ namespace ShaderManagementConsole
// Restore geometry and show the window
mainWindowWrapper->showFromSettings();
AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect();
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::CreateViewForDocumemt(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 +91,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 +109,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
@@ -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>
@@ -30,64 +28,20 @@ namespace ShaderManagementConsole
* 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();
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* CreateViewForDocumemt(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