Merge pull request #2689 from aws-lumberyard-dev/lawalfua/atomToolsMainWindow

AtomToolsMainWindow, making a base class for atom tools windows ATOM-415
This commit is contained in:
Guthrie Adams
2021-08-09 10:08:54 -05:00
committed by GitHub
28 changed files with 614 additions and 1078 deletions
@@ -9,12 +9,17 @@
#include <AtomToolsFramework/Communication/LocalServer.h>
#include <AtomToolsFramework/Communication/LocalSocket.h>
#include <AtomToolsFramework/Window/AtomToolsMainWindowNotificationBus.h>
#include <AzCore/Component/Entity.h>
#include <AzCore/Component/TickBus.h>
#include <AzCore/UserSettings/UserSettingsProvider.h>
#include <AzFramework/Application/Application.h>
#include <AzFramework/Asset/AssetSystemBus.h>
#include <AzQtComponents/Application/AzQtApplication.h>
#include <AzToolsFramework/API/AssetDatabaseBus.h>
#include <AzToolsFramework/API/EditorPythonConsoleBus.h>
#include <AzToolsFramework/Logger/TraceLogger.h>
@@ -31,6 +36,7 @@ namespace AtomToolsFramework
, protected AzFramework::AssetSystemStatusBus::Handler
, protected AzToolsFramework::EditorPythonConsoleNotificationBus::Handler
, protected AZ::UserSettingsOwnerRequestBus::Handler
, protected AtomToolsMainWindowNotificationBus::Handler
{
public:
AZ_TYPE_INFO(AtomTools::AtomToolsApplication, "{A0DF25BA-6F74-4F11-9F85-0F99278D5986}");
@@ -38,6 +44,7 @@ namespace AtomToolsFramework
using Base = AzFramework::Application;
AtomToolsApplication(int* argc, char*** argv);
~AtomToolsApplication();
//////////////////////////////////////////////////////////////////////////
// AzFramework::Application
@@ -52,6 +59,11 @@ namespace AtomToolsFramework
void Stop() override;
protected:
//////////////////////////////////////////////////////////////////////////
// AtomsToolMainWindowNotificationBus::Handler overrides...
void OnMainWindowClosing() override;
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// AssetDatabaseRequestsBus::Handler overrides...
bool GetAssetDatabaseLocation(AZStd::string& result) override;
@@ -0,0 +1,63 @@
/*
* 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
#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 <QMenuBar>
#include <QStatusBar>
#include <QToolBar>
namespace AtomToolsFramework
{
class AtomToolsMainWindow
: public AzQtComponents::DockMainWindow
, protected AtomToolsMainWindowRequestBus::Handler
{
public:
AtomToolsMainWindow(QWidget* parent = 0);
~AtomToolsMainWindow();
protected:
void ActivateWindow() override;
bool AddDockWidget(const AZStd::string& name, QWidget* widget, uint32_t area, uint32_t orientation) override;
void RemoveDockWidget(const AZStd::string& name) override;
void SetDockWidgetVisible(const AZStd::string& name, bool visible) override;
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();
AzQtComponents::FancyDocking* m_advancedDockManager = nullptr;
QWidget* m_centralWidget = nullptr;
QMenuBar* m_menuBar = nullptr;
AzQtComponents::TabWidget* m_tabWidget = nullptr;
QStatusBar* m_statusBar = nullptr;
AZStd::unordered_map<AZStd::string, AzQtComponents::StyledDockWidget*> m_dockWidgets;
};
} // namespace AtomToolsFramework
@@ -0,0 +1,30 @@
/*
* 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
#include <AzCore/EBus/EBus.h>
namespace AtomToolsFramework
{
//! AtomToolsMainWindowFactoryRequestBus provides
class AtomToolsMainWindowFactoryRequests : public AZ::EBusTraits
{
public:
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
/// Creates and shows main window
virtual void CreateMainWindow() = 0;
//! Destroys main window and releases all cached assets
virtual void DestroyMainWindow() = 0;
};
using AtomToolsMainWindowFactoryRequestBus = AZ::EBus<AtomToolsMainWindowFactoryRequests>;
} // namespace AtomToolsFramework
@@ -10,17 +10,16 @@
#include <AzCore/EBus/EBus.h>
namespace MaterialEditor
namespace AtomToolsFramework
{
class MaterialEditorWindowNotifications
: public AZ::EBusTraits
class AtomToolsMainWindowNotifications : public AZ::EBusTraits
{
public:
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
virtual void OnMaterialEditorWindowClosing() {};
virtual void OnMainWindowClosing(){};
};
using MaterialEditorWindowNotificationBus = AZ::EBus<MaterialEditorWindowNotifications>;
using AtomToolsMainWindowNotificationBus = AZ::EBus<AtomToolsMainWindowNotifications>;
} // namespace MaterialEditor
} // namespace AtomToolsFramework
@@ -8,17 +8,19 @@
#pragma once
//! Disables "unreferenced formal parameter" warning
#pragma warning(disable : 4100)
#include <AzCore/EBus/EBus.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/string/string.h>
class QWidget;
namespace MaterialEditor
namespace AtomToolsFramework
{
//! MaterialEditorWindowRequestBus provides
class MaterialEditorWindowRequests
: public AZ::EBusTraits
//! AtomToolsMainWindowRequestBus provides
class AtomToolsMainWindowRequests : public AZ::EBusTraits
{
public:
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
@@ -49,16 +51,16 @@ namespace MaterialEditor
//! Get a list of registered docked widget names
virtual AZStd::vector<AZStd::string> GetDockWidgetNames() const = 0;
//! Resizes the Material Editor window to achieve a requested size for the viewport render target.
//! Resizes the main window to achieve a requested size for the viewport render target.
//! (This indicates the size of the render target, not the desktop-scaled QT widget size).
virtual void ResizeViewportRenderTarget(uint32_t width, uint32_t height) = 0;
virtual void ResizeViewportRenderTarget(uint32_t width, uint32_t height) {};
//! Forces the viewport's render target to use the given resolution, ignoring the size of the viewport widget.
virtual void LockViewportRenderTargetSize(uint32_t width, uint32_t height) = 0;
virtual void LockViewportRenderTargetSize(uint32_t width, uint32_t height) {};
//! Releases the viewport's render target resolution lock, allowing it to match the viewport widget again.
virtual void UnlockViewportRenderTargetSize() = 0;
virtual void UnlockViewportRenderTargetSize() {};
};
using MaterialEditorWindowRequestBus = AZ::EBus<MaterialEditorWindowRequests>;
using AtomToolsMainWindowRequestBus = AZ::EBus<AtomToolsMainWindowRequests>;
} // namespace MaterialEditor
} // namespace AtomToolsFramework
@@ -10,6 +10,8 @@
#include <AtomToolsFramework/Util/Util.h>
#include <AtomToolsFramework/Application/AtomToolsApplication.h>
#include <AtomToolsFramework/Window/AtomToolsMainWindowFactoryRequestBus.h>
#include <AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h>
#include <AzCore/IO/Path/Path.h>
#include <AzCore/Utils/Utils.h>
@@ -66,6 +68,13 @@ namespace AtomToolsFramework
});
}
AtomToolsApplication ::~AtomToolsApplication()
{
AtomToolsMainWindowNotificationBus::Handler::BusDisconnect();
AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusDisconnect();
AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusDisconnect();
}
void AtomToolsApplication::CreateReflectionManager()
{
Base::CreateReflectionManager();
@@ -145,12 +154,21 @@ namespace AtomToolsFramework
m_timer.start();
}
void AtomToolsApplication::OnMainWindowClosing()
{
ExitMainLoop();
}
void AtomToolsApplication::Destroy()
{
// before modules are unloaded, destroy UI to free up any assets it cached
AtomToolsMainWindowFactoryRequestBus::Broadcast(&AtomToolsMainWindowFactoryRequestBus::Handler::DestroyMainWindow);
AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusDisconnect();
AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusDisconnect();
AtomToolsMainWindowNotificationBus::Handler::BusDisconnect();
AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::StartDisconnectingAssetProcessor);
Base::Destroy();
}
@@ -271,6 +289,13 @@ namespace AtomToolsFramework
void AtomToolsApplication::ProcessCommandLine(const AZ::CommandLine& commandLine)
{
const AZStd::string activateWindowSwitchName = "activatewindow";
if (commandLine.HasSwitch(activateWindowSwitchName))
{
AtomToolsFramework::AtomToolsMainWindowRequestBus::Broadcast(
&AtomToolsFramework::AtomToolsMainWindowRequestBus::Handler::ActivateWindow);
}
const AZStd::string timeoputSwitchName = "timeout";
if (commandLine.HasSwitch(timeoputSwitchName))
{
@@ -389,6 +414,10 @@ namespace AtomToolsFramework
LoadSettings();
AtomToolsMainWindowNotificationBus::Handler::BusConnect();
AtomToolsMainWindowFactoryRequestBus::Broadcast(&AtomToolsMainWindowFactoryRequestBus::Handler::CreateMainWindow);
auto editorPythonEventsInterface = AZ::Interface<AzToolsFramework::EditorPythonEventsInterface>::Get();
if (editorPythonEventsInterface)
{
@@ -436,6 +465,8 @@ namespace AtomToolsFramework
void AtomToolsApplication::Stop()
{
AtomToolsMainWindowFactoryRequestBus::Broadcast(&AtomToolsMainWindowFactoryRequestBus::Handler::DestroyMainWindow);
UnloadSettings();
Base::Stop();
}
@@ -445,7 +476,7 @@ namespace AtomToolsFramework
appType.m_maskValue = AZ::ApplicationTypeQuery::Masks::Game;
}
void AtomToolsApplication::OnTraceMessage([[maybe_unused]] AZStd::string_view message)
void AtomToolsApplication::OnTraceMessage([[maybe_unused]] AZStd::string_view message)
{
#if defined(AZ_ENABLE_TRACING)
AZStd::vector<AZStd::string> lines;
@@ -0,0 +1,239 @@
/*
* 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/Window/AtomToolsMainWindow.h>
namespace AtomToolsFramework
{
AtomToolsMainWindow::AtomToolsMainWindow(QWidget* parent)
: AzQtComponents::DockMainWindow(parent)
{
m_advancedDockManager = new AzQtComponents::FancyDocking(this);
setDockNestingEnabled(true);
setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea);
setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
m_statusBar = new QStatusBar(this);
m_statusBar->setObjectName("StatusBar");
statusBar()->addPermanentWidget(m_statusBar, 1);
m_centralWidget = new QWidget(this);
AtomToolsMainWindowRequestBus::Handler::BusConnect();
}
AtomToolsMainWindow::~AtomToolsMainWindow()
{
AtomToolsMainWindowRequestBus::Handler::BusDisconnect();
}
void AtomToolsMainWindow::ActivateWindow()
{
activateWindow();
raise();
}
bool AtomToolsMainWindow::AddDockWidget(const AZStd::string& name, QWidget* widget, uint32_t area, uint32_t orientation)
{
auto dockWidgetItr = m_dockWidgets.find(name);
if (dockWidgetItr != m_dockWidgets.end() || !widget)
{
return false;
}
auto dockWidget = new AzQtComponents::StyledDockWidget(name.c_str());
dockWidget->setObjectName(QString("%1_DockWidget").arg(name.c_str()));
dockWidget->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable);
widget->setObjectName(name.c_str());
widget->setParent(dockWidget);
widget->setMinimumSize(QSize(300, 300));
dockWidget->setWidget(widget);
addDockWidget(aznumeric_cast<Qt::DockWidgetArea>(area), dockWidget);
resizeDocks({ dockWidget }, { 400 }, aznumeric_cast<Qt::Orientation>(orientation));
m_dockWidgets[name] = dockWidget;
return true;
}
void AtomToolsMainWindow::RemoveDockWidget(const AZStd::string& name)
{
auto dockWidgetItr = m_dockWidgets.find(name);
if (dockWidgetItr != m_dockWidgets.end())
{
delete dockWidgetItr->second;
m_dockWidgets.erase(dockWidgetItr);
}
}
void AtomToolsMainWindow::SetDockWidgetVisible(const AZStd::string& name, bool visible)
{
auto dockWidgetItr = m_dockWidgets.find(name);
if (dockWidgetItr != m_dockWidgets.end())
{
dockWidgetItr->second->setVisible(visible);
}
}
bool AtomToolsMainWindow::IsDockWidgetVisible(const AZStd::string& name) const
{
auto dockWidgetItr = m_dockWidgets.find(name);
if (dockWidgetItr != m_dockWidgets.end())
{
return dockWidgetItr->second->isVisible();
}
return false;
}
AZStd::vector<AZStd::string> AtomToolsMainWindow::GetDockWidgetNames() const
{
AZStd::vector<AZStd::string> names;
names.reserve(m_dockWidgets.size());
for (const auto& dockWidgetPair : m_dockWidgets)
{
names.push_back(dockWidgetPair.first);
}
return names;
}
void AtomToolsMainWindow::CreateMenu()
{
m_menuBar = new QMenuBar(this);
m_menuBar->setObjectName("MenuBar");
setMenuBar(m_menuBar);
}
void AtomToolsMainWindow::CreateTabBar()
{
m_tabWidget = new AzQtComponents::TabWidget(m_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();
});
}
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 appended to the file name to denote modified document
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());
}
}
} // namespace AtomToolsFramework
@@ -24,6 +24,10 @@ set(FILES
Include/AtomToolsFramework/Viewport/RenderViewportWidget.h
Include/AtomToolsFramework/Viewport/ModularViewportCameraController.h
Include/AtomToolsFramework/Viewport/ModularViewportCameraControllerRequestBus.h
Include/AtomToolsFramework/Window/AtomToolsMainWindow.h
Include/AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h
Include/AtomToolsFramework/Window/AtomToolsMainWindowFactoryRequestBus.h
Include/AtomToolsFramework/Window/AtomToolsMainWindowNotificationBus.h
Source/Application/AtomToolsApplication.cpp
Source/Communication/LocalServer.cpp
Source/Communication/LocalSocket.cpp
@@ -40,4 +44,5 @@ set(FILES
Source/Util/Util.cpp
Source/Viewport/RenderViewportWidget.cpp
Source/Viewport/ModularViewportCameraController.cpp
)
Source/Window/AtomToolsMainWindow.cpp
)
@@ -1,31 +0,0 @@
/*
* 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
#include <AzCore/EBus/EBus.h>
namespace MaterialEditor
{
//! MaterialEditorWindowFactoryRequestBus provides
class MaterialEditorWindowFactoryRequests
: public AZ::EBusTraits
{
public:
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
/// Creates and shows the MaterialEditorWindow
virtual void CreateMaterialEditorWindow() = 0;
//! Destroys material editor window and releases all cached assets
virtual void DestroyMaterialEditorWindow() = 0;
};
using MaterialEditorWindowFactoryRequestBus = AZ::EBus<MaterialEditorWindowFactoryRequests>;
} // namespace MaterialEditor
@@ -6,48 +6,17 @@
*
*/
#include <AzCore/IO/Path/Path.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzCore/Utils/Utils.h>
#include <AzFramework/IO/LocalFileIO.h>
#include <AzFramework/Network/AssetProcessorConnection.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzToolsFramework/API/EditorPythonConsoleBus.h>
#include <AzToolsFramework/API/EditorPythonRunnerRequestsBus.h>
#include <AzToolsFramework/Asset/AssetSystemComponent.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserComponent.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
#include <AzToolsFramework/AzToolsFrameworkModule.h>
#include <AzToolsFramework/SourceControl/PerforceComponent.h>
#include <AzToolsFramework/SourceControl/SourceControlAPI.h>
#include <AzToolsFramework/Thumbnails/ThumbnailerComponent.h>
#include <AzToolsFramework/UI/PropertyEditor/PropertyManagerComponent.h>
#include <AzToolsFramework/UI/UICore/QTreeViewStateSaver.hxx>
#include <AzToolsFramework/UI/UICore/QWidgetSavedState.h>
#include <AtomToolsFramework/Util/Util.h>
#include <Atom/RPI.Edit/Common/AssetUtils.h>
#include <Atom/RPI.Public/RPISystemInterface.h>
#include <Atom/Document/MaterialDocumentModule.h>
#include <Atom/Document/MaterialDocumentSystemRequestBus.h>
#include <Atom/Viewport/MaterialViewportModule.h>
#include <Atom/Window/MaterialEditorWindowFactoryRequestBus.h>
#include <Atom/Window/MaterialEditorWindowModule.h>
#include <Atom/Window/MaterialEditorWindowRequestBus.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <MaterialEditorApplication.h>
#include <MaterialEditor_Traits_Platform.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QMessageBox>
#include <QObject>
AZ_POP_DISABLE_WARNING
namespace MaterialEditor
{
//! This function returns the build system target name of "MaterialEditor
//! This function returns the build system target name of "MaterialEditor"
AZStd::string MaterialEditorApplication::GetBuildTargetName() const
{
#if !defined(LY_CMAKE_TARGET)
@@ -77,11 +46,6 @@ namespace MaterialEditor
*AZ::SettingsRegistry::Get(), GetBuildTargetName());
}
MaterialEditorApplication::~MaterialEditorApplication()
{
MaterialEditorWindowNotificationBus::Handler::BusDisconnect();
}
void MaterialEditorApplication::CreateStaticModules(AZStd::vector<AZ::Module*>& outModules)
{
Base::CreateStaticModules(outModules);
@@ -90,37 +54,14 @@ namespace MaterialEditor
outModules.push_back(aznew MaterialEditorWindowModule);
}
void MaterialEditorApplication::OnMaterialEditorWindowClosing()
{
ExitMainLoop();
}
void MaterialEditorApplication::Destroy()
{
// before modules are unloaded, destroy UI to free up any assets it cached
MaterialEditor::MaterialEditorWindowFactoryRequestBus::Broadcast(
&MaterialEditor::MaterialEditorWindowFactoryRequestBus::Handler::DestroyMaterialEditorWindow);
MaterialEditorWindowNotificationBus::Handler::BusDisconnect();
Base::Destroy();
}
AZStd::vector<AZStd::string> MaterialEditorApplication::GetCriticalAssetFilters() const
{
return AZStd::vector<AZStd::string>({ "passes/", "config/", "MaterialEditor" });
return AZStd::vector<AZStd::string>({ "passes/", "config/", "MaterialEditor/" });
}
void MaterialEditorApplication::ProcessCommandLine(const AZ::CommandLine& commandLine)
{
const AZStd::string activateWindowSwitchName = "activatewindow";
if (commandLine.HasSwitch(activateWindowSwitchName))
{
MaterialEditor::MaterialEditorWindowRequestBus::Broadcast(
&MaterialEditor::MaterialEditorWindowRequestBus::Handler::ActivateWindow);
}
// Process command line options for opening one or more documents on startup
// Process command line options for opening one or more material documents on startup
size_t openDocumentCount = commandLine.GetNumMiscValues();
for (size_t openDocumentIndex = 0; openDocumentIndex < openDocumentCount; ++openDocumentIndex)
{
@@ -132,22 +73,4 @@ namespace MaterialEditor
Base::ProcessCommandLine(commandLine);
}
void MaterialEditorApplication::StartInternal()
{
Base::StartInternal();
MaterialEditorWindowNotificationBus::Handler::BusConnect();
MaterialEditor::MaterialEditorWindowFactoryRequestBus::Broadcast(
&MaterialEditor::MaterialEditorWindowFactoryRequestBus::Handler::CreateMaterialEditorWindow);
}
void MaterialEditorApplication::Stop()
{
MaterialEditor::MaterialEditorWindowFactoryRequestBus::Broadcast(
&MaterialEditor::MaterialEditorWindowFactoryRequestBus::Handler::DestroyMaterialEditorWindow);
Base::Stop();
}
} // namespace MaterialEditor
@@ -9,18 +9,14 @@
#pragma once
#include <Atom/Document/MaterialDocumentSystemRequestBus.h>
#include <Atom/Window/MaterialEditorWindowNotificationBus.h>
#include <AtomToolsFramework/Application/AtomToolsApplication.h>
#include <QTimer>
namespace MaterialEditor
{
class MaterialThumbnailRenderer;
class MaterialEditorApplication
: public AtomToolsFramework::AtomToolsApplication
, private MaterialEditorWindowNotificationBus::Handler
{
public:
AZ_TYPE_INFO(MaterialEditor::MaterialEditorApplication, "{30F90CA5-1253-49B5-8143-19CEE37E22BB}");
@@ -28,28 +24,15 @@ namespace MaterialEditor
using Base = AtomToolsFramework::AtomToolsApplication;
MaterialEditorApplication(int* argc, char*** argv);
virtual ~MaterialEditorApplication();
//////////////////////////////////////////////////////////////////////////
// AzFramework::Application
void CreateStaticModules(AZStd::vector<AZ::Module*>& outModules) override;
const char* GetCurrentConfigurationName() const override;
void Stop() override;
private:
//////////////////////////////////////////////////////////////////////////
// MaterialEditorWindowNotificationBus::Handler overrides...
void OnMaterialEditorWindowClosing() override;
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// AzFramework::Application overrides...
void Destroy() override;
//////////////////////////////////////////////////////////////////////////
void ProcessCommandLine(const AZ::CommandLine& commandLine) override;
void StartInternal() override;
AZStd::string GetBuildTargetName() const override;
AZStd::vector<AZStd::string> GetCriticalAssetFilters() const override;
};
};
} // namespace MaterialEditor
@@ -7,39 +7,27 @@
*/
#include <Atom/RHI/Factory.h>
#include <Atom/RPI.Edit/Common/AssetUtils.h>
#include <Atom/RPI.Edit/Common/JsonUtils.h>
#include <Atom/RPI.Edit/Material/MaterialSourceData.h>
#include <Atom/RPI.Edit/Material/MaterialTypeSourceData.h>
#include <Atom/RPI.Reflect/Image/StreamingImageAsset.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 <Atom/Document/MaterialDocumentRequestBus.h>
#include <Atom/Document/MaterialDocumentSystemRequestBus.h>
#include <Atom/Window/MaterialEditorWindowNotificationBus.h>
#include <Atom/Window/MaterialEditorWindowSettings.h>
#include <AtomToolsFramework/Util/Util.h>
#include <AzFramework/Application/Application.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzQtComponents/Components/StyleManager.h>
#include <AzQtComponents/Components/WindowDecorationWrapper.h>
#include <AzQtComponents/Utilities/QtPluginPaths.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/API/EditorPythonRunnerRequestsBus.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
#include <AzToolsFramework/PythonTerminal/ScriptTermDialog.h>
#include <Viewport/MaterialViewportWidget.h>
#include <Window/CreateMaterialDialog/CreateMaterialDialog.h>
#include <Window/HelpDialog/HelpDialog.h>
#include <Window/SettingsDialog/SettingsDialog.h>
#include <Window/MaterialBrowserWidget.h>
#include <Window/MaterialEditorWindow.h>
#include <Window/MaterialInspector/MaterialInspector.h>
#include <Window/PerformanceMonitor/PerformanceMonitorWidget.h>
#include <Window/SettingsDialog/SettingsDialog.h>
#include <Window/ViewportSettingsInspector/ViewportSettingsInspector.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
@@ -56,7 +44,7 @@ AZ_POP_DISABLE_WARNING
namespace MaterialEditor
{
MaterialEditorWindow::MaterialEditorWindow(QWidget* parent /* = 0 */)
: AzQtComponents::DockMainWindow(parent)
: AtomToolsFramework::AtomToolsMainWindow(parent)
{
resize(1280, 1024);
@@ -83,33 +71,19 @@ namespace MaterialEditor
setWindowTitle(QApplication::applicationName());
}
m_advancedDockManager = new AzQtComponents::FancyDocking(this);
setObjectName("MaterialEditorWindow");
setDockNestingEnabled(true);
setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea);
setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
m_menuBar = new QMenuBar(this);
m_menuBar->setObjectName("MenuBar");
setMenuBar(m_menuBar);
m_toolBar = new MaterialEditorToolBar(this);
m_toolBar->setObjectName("ToolBar");
addToolBar(m_toolBar);
m_centralWidget = new QWidget(this);
m_tabWidget = new AzQtComponents::TabWidget(m_centralWidget);
m_tabWidget->setObjectName("TabWidget");
m_tabWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred);
m_tabWidget->setContentsMargins(0, 0, 0, 0);
m_materialViewport = new MaterialViewportWidget(m_centralWidget);
m_materialViewport->setObjectName("Viewport");
m_materialViewport->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
CreateMenu();
CreateTabBar();
QVBoxLayout* vl = new QVBoxLayout(m_centralWidget);
vl->setMargin(0);
vl->setContentsMargins(0, 0, 0, 0);
@@ -118,13 +92,6 @@ namespace MaterialEditor
m_centralWidget->setLayout(vl);
setCentralWidget(m_centralWidget);
m_statusBar = new StatusBarWidget(this);
m_statusBar->setObjectName("StatusBar");
statusBar()->addPermanentWidget(m_statusBar, 1);
SetupMenu();
SetupTabs();
AddDockWidget("Asset Browser", new MaterialBrowserWidget, Qt::BottomDockWidgetArea, Qt::Vertical);
AddDockWidget("Inspector", new MaterialInspector, Qt::RightDockWidgetArea, Qt::Horizontal);
AddDockWidget("Viewport Settings", new ViewportSettingsInspector, Qt::LeftDockWidgetArea, Qt::Horizontal);
@@ -148,7 +115,6 @@ namespace MaterialEditor
m_advancedDockManager->restoreState(windowState);
}
MaterialEditorWindowRequestBus::Handler::BusConnect();
MaterialDocumentNotificationBus::Handler::BusConnect();
OnDocumentOpened(AZ::Uuid::CreateNull());
}
@@ -156,76 +122,9 @@ namespace MaterialEditor
MaterialEditorWindow::~MaterialEditorWindow()
{
MaterialDocumentNotificationBus::Handler::BusDisconnect();
MaterialEditorWindowRequestBus::Handler::BusDisconnect();
}
void MaterialEditorWindow::ActivateWindow()
{
activateWindow();
raise();
}
bool MaterialEditorWindow::AddDockWidget(const AZStd::string& name, QWidget* widget, uint32_t area, uint32_t orientation)
{
auto dockWidgetItr = m_dockWidgets.find(name);
if (dockWidgetItr != m_dockWidgets.end() || !widget)
{
return false;
}
auto dockWidget = new AzQtComponents::StyledDockWidget(name.c_str());
dockWidget->setObjectName(QString("%1_DockWidget").arg(name.c_str()));
dockWidget->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable);
widget->setObjectName(name.c_str());
widget->setParent(dockWidget);
widget->setMinimumSize(QSize(300, 300));
dockWidget->setWidget(widget);
addDockWidget(aznumeric_cast<Qt::DockWidgetArea>(area), dockWidget);
resizeDocks({ dockWidget }, { 400 }, aznumeric_cast<Qt::Orientation>(orientation));
m_dockWidgets[name] = dockWidget;
return true;
}
void MaterialEditorWindow::RemoveDockWidget(const AZStd::string& name)
{
auto dockWidgetItr = m_dockWidgets.find(name);
if (dockWidgetItr != m_dockWidgets.end())
{
delete dockWidgetItr->second;
m_dockWidgets.erase(dockWidgetItr);
}
}
void MaterialEditorWindow::SetDockWidgetVisible(const AZStd::string& name, bool visible)
{
auto dockWidgetItr = m_dockWidgets.find(name);
if (dockWidgetItr != m_dockWidgets.end())
{
dockWidgetItr->second->setVisible(visible);
}
}
bool MaterialEditorWindow::IsDockWidgetVisible(const AZStd::string& name) const
{
auto dockWidgetItr = m_dockWidgets.find(name);
if (dockWidgetItr != m_dockWidgets.end())
{
return dockWidgetItr->second->isVisible();
}
return false;
}
AZStd::vector<AZStd::string> MaterialEditorWindow::GetDockWidgetNames() const
{
AZStd::vector<AZStd::string> names;
names.reserve(m_dockWidgets.size());
for (const auto& dockWidgetPair : m_dockWidgets)
{
names.push_back(dockWidgetPair.first);
}
return names;
}
void MaterialEditorWindow::ResizeViewportRenderTarget(uint32_t width, uint32_t height)
{
QSize requestedViewportSize = QSize(width, height) / devicePixelRatioF();
@@ -274,7 +173,8 @@ namespace MaterialEditor
QByteArray windowState = m_advancedDockManager->saveState();
windowSettings->m_mainWindowState.assign(windowState.begin(), windowState.end());
MaterialEditorWindowNotificationBus::Broadcast(&MaterialEditorWindowNotifications::OnMaterialEditorWindowClosing);
AtomToolsFramework::AtomToolsMainWindowNotificationBus::Broadcast(
&AtomToolsFramework::AtomToolsMainWindowNotifications::OnMainWindowClosing);
}
void MaterialEditorWindow::OnDocumentOpened(const AZ::Uuid& documentId)
@@ -283,14 +183,31 @@ namespace MaterialEditor
MaterialDocumentRequestBus::EventResult(isOpen, documentId, &MaterialDocumentRequestBus::Events::IsOpen);
bool isSavable = false;
MaterialDocumentRequestBus::EventResult(isSavable, documentId, &MaterialDocumentRequestBus::Events::IsSavable);
bool isModified = false;
MaterialDocumentRequestBus::EventResult(isModified, documentId, &MaterialDocumentRequestBus::Events::IsModified);
bool canUndo = false;
MaterialDocumentRequestBus::EventResult(canUndo, documentId, &MaterialDocumentRequestBus::Events::CanUndo);
bool canRedo = false;
MaterialDocumentRequestBus::EventResult(canRedo, documentId, &MaterialDocumentRequestBus::Events::CanRedo);
AZStd::string absolutePath;
MaterialDocumentRequestBus::EventResult(absolutePath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath);
AZStd::string filename;
AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename);
// Update UI to display the new document
AddTabForDocumentId(documentId);
UpdateTabForDocumentId(documentId);
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(m_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;
@@ -330,7 +247,8 @@ namespace MaterialEditor
const QString documentPath = GetDocumentPath(documentId);
if (!documentPath.isEmpty())
{
m_statusBar->UpdateStatusInfo(QString("Material opened: %1").arg(documentPath));
const QString status = QString("Material closed: %1").arg(documentPath);
m_statusBar->setWindowIconText(QString("<font color=\"White\">%1</font>").arg(status));
}
}
@@ -339,12 +257,19 @@ namespace MaterialEditor
RemoveTabForDocumentId(documentId);
const QString documentPath = GetDocumentPath(documentId);
m_statusBar->UpdateStatusInfo(QString("Material closed: %1").arg(documentPath));
const QString status = QString("Material closed: %1").arg(documentPath);
m_statusBar->setWindowIconText(QString("<font color=\"White\">%1</font>").arg(status));
}
void MaterialEditorWindow::OnDocumentModified(const AZ::Uuid& documentId)
{
UpdateTabForDocumentId(documentId);
bool isModified = false;
MaterialDocumentRequestBus::EventResult(isModified, documentId, &MaterialDocumentRequestBus::Events::IsModified);
AZStd::string absolutePath;
MaterialDocumentRequestBus::EventResult(absolutePath, documentId, &MaterialDocumentRequestBus::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)
@@ -362,14 +287,23 @@ namespace MaterialEditor
void MaterialEditorWindow::OnDocumentSaved(const AZ::Uuid& documentId)
{
UpdateTabForDocumentId(documentId);
bool isModified = false;
MaterialDocumentRequestBus::EventResult(isModified, documentId, &MaterialDocumentRequestBus::Events::IsModified);
AZStd::string absolutePath;
MaterialDocumentRequestBus::EventResult(absolutePath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath);
AZStd::string filename;
AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename);
UpdateTabForDocumentId(documentId, filename, absolutePath, isModified);
const QString documentPath = GetDocumentPath(documentId);
m_statusBar->UpdateStatusInfo(QString("Material saved: %1").arg(documentPath));
const QString status = QString("Material closed: %1").arg(documentPath);
m_statusBar->setWindowIconText(QString("<font color=\"White\">%1</font>").arg(status));
}
void MaterialEditorWindow::SetupMenu()
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 = m_menuBar->addMenu("&File");
@@ -407,7 +341,8 @@ namespace MaterialEditor
if (!result)
{
const QString documentPath = GetDocumentPath(documentId);
m_statusBar->UpdateStatusError(QString("Failed to save material: %1").arg(documentPath));
const QString status = QString("Failed to save material: %1").arg(documentPath);
m_statusBar->setWindowIconText(QString("<font color=\"Red\">%1</font>").arg(status));
}
}, QKeySequence::Save);
@@ -420,7 +355,8 @@ namespace MaterialEditor
documentId, AtomToolsFramework::GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData());
if (!result)
{
m_statusBar->UpdateStatusError(QString("Failed to save material: %1").arg(documentPath));
const QString status = QString("Failed to save material: %1").arg(documentPath);
m_statusBar->setWindowIconText(QString("<font color=\"Red\">%1</font>").arg(status));
}
}, QKeySequence::SaveAs);
@@ -433,7 +369,8 @@ namespace MaterialEditor
documentId, AtomToolsFramework::GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData());
if (!result)
{
m_statusBar->UpdateStatusError(QString("Failed to save material: %1").arg(documentPath));
const QString status = QString("Failed to save material: %1").arg(documentPath);
m_statusBar->setWindowIconText(QString("<font color=\"Red\">%1</font>").arg(status));
}
});
@@ -442,7 +379,8 @@ namespace MaterialEditor
MaterialDocumentSystemRequestBus::BroadcastResult(result, &MaterialDocumentSystemRequestBus::Events::SaveAllDocuments);
if (!result)
{
m_statusBar->UpdateStatusError(QString("Failed to save materials."));
const QString status = QString("Failed to save materials.");
m_statusBar->setWindowIconText(QString("<font color=\"Red\">%1</font>").arg(status));
}
});
@@ -487,7 +425,8 @@ namespace MaterialEditor
if (!result)
{
const QString documentPath = GetDocumentPath(documentId);
m_statusBar->UpdateStatusError(QString("Failed to perform Undo in material: %1").arg(documentPath));
const QString status = QString("Failed to perform Undo in material: %1").arg(documentPath);
m_statusBar->setWindowIconText(QString("<font color=\"Red\">%1</font>").arg(status));
}
}, QKeySequence::Undo);
@@ -498,7 +437,8 @@ namespace MaterialEditor
if (!result)
{
const QString documentPath = GetDocumentPath(documentId);
m_statusBar->UpdateStatusError(QString("Failed to perform Undo in material: %1").arg(documentPath));
const QString status = QString("Failed to perform Undo in material: %1").arg(documentPath);
m_statusBar->setWindowIconText(QString("<font color=\"Red\">%1</font>").arg(status));
}
}, QKeySequence::Redo);
@@ -561,20 +501,9 @@ namespace MaterialEditor
});
}
void MaterialEditorWindow::SetupTabs()
void MaterialEditorWindow::CreateTabBar()
{
// 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();
});
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
@@ -590,107 +519,6 @@ namespace MaterialEditor
});
}
void MaterialEditorWindow::AddTabForDocumentId(const AZ::Uuid& documentId)
{
bool isOpen = false;
MaterialDocumentRequestBus::EventResult(isOpen, documentId, &MaterialDocumentRequestBus::Events::IsOpen);
if (documentId.IsNull() || !isOpen)
{
return;
}
// 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;
}
}
// Create a new tab for the document ID and assign it's label to the file name of the document.
AZStd::string absolutePath;
MaterialDocumentRequestBus::EventResult(absolutePath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath);
AZStd::string filename;
AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename);
// The tab widget requires a dummy page per tab
QWidget* placeHolderWidget = new QWidget(m_centralWidget);
placeHolderWidget->setContentsMargins(0, 0, 0, 0);
placeHolderWidget->resize(0, 0);
placeHolderWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
const int tabIndex = m_tabWidget->addTab(placeHolderWidget, filename.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, absolutePath.c_str());
m_tabWidget->setCurrentIndex(tabIndex);
m_tabWidget->setVisible(true);
m_tabWidget->repaint();
}
void MaterialEditorWindow::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 MaterialEditorWindow::UpdateTabForDocumentId(const AZ::Uuid& documentId)
{
// 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))
{
AZStd::string absolutePath;
MaterialDocumentRequestBus::EventResult(absolutePath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath);
AZStd::string filename;
AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename);
bool isModified = false;
MaterialDocumentRequestBus::EventResult(isModified, documentId, &MaterialDocumentRequestBus::Events::IsModified);
// We use an asterisk appended to the file name to denote modified document
if (isModified)
{
filename += " *";
}
m_tabWidget->setTabText(tabIndex, filename.c_str());
m_tabWidget->setTabToolTip(tabIndex, absolutePath.c_str());
m_tabWidget->repaint();
break;
}
}
}
}
QString MaterialEditorWindow::GetDocumentPath(const AZ::Uuid& documentId) const
{
AZStd::string absolutePath;
@@ -698,20 +526,6 @@ namespace MaterialEditor
return absolutePath.c_str();
}
AZ::Uuid MaterialEditorWindow::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 MaterialEditorWindow::OpenTabContextMenu()
{
const QTabBar* tabBar = m_tabWidget->tabBar();
@@ -738,23 +552,6 @@ namespace MaterialEditor
tabMenu.exec(QCursor::pos());
}
}
void MaterialEditorWindow::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 MaterialEditorWindow::SelectNextTab()
{
if (m_tabWidget->count() > 1)
{
m_tabWidget->setCurrentIndex((m_tabWidget->currentIndex() + 1) % m_tabWidget->count());
}
}
} // namespace MaterialEditor
#include <Window/moc_MaterialEditorWindow.cpp>
@@ -9,31 +9,16 @@
#pragma once
#if !defined(Q_MOC_RUN)
#include <AzCore/Memory/SystemAllocator.h>
#include <Atom/Document/MaterialDocumentNotificationBus.h>
#include <AtomToolsFramework/Window/AtomToolsMainWindow.h>
#include <AzCore/Memory/SystemAllocator.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <AzQtComponents/Components/DockMainWindow.h>
#include <AzQtComponents/Components/FancyDocking.h>
#include <AzQtComponents/Components/StyledDockWidget.h>
#include <AzQtComponents/Components/Widgets/TabWidget.h>
#include <Atom/Window/MaterialEditorWindowRequestBus.h>
#include <Viewport/MaterialViewportWidget.h>
#include <Window/ToolBar/MaterialEditorToolBar.h>
#include <Window/StatusBar/StatusBarWidget.h>
#include <QMenuBar>
#include <QToolBar>
#include <QStatusBar>
AZ_POP_DISABLE_WARNING
#endif
namespace AzToolsFramework
{
class CScriptTermDialog;
}
namespace MaterialEditor
{
/**
@@ -44,26 +29,19 @@ namespace MaterialEditor
* 3) MaterialPropertyInspector - The user edits the properties of the selected Material.
*/
class MaterialEditorWindow
: public AzQtComponents::DockMainWindow
, private MaterialEditorWindowRequestBus::Handler
: public AtomToolsFramework::AtomToolsMainWindow
, private MaterialDocumentNotificationBus::Handler
{
Q_OBJECT
public:
AZ_CLASS_ALLOCATOR(MaterialEditorWindow, AZ::SystemAllocator, 0);
using Base = AtomToolsFramework::AtomToolsMainWindow;
MaterialEditorWindow(QWidget* parent = 0);
~MaterialEditorWindow();
private:
// MaterialEditorWindowRequestBus::Handler overrides...
void ActivateWindow() override;
bool AddDockWidget(const AZStd::string& name, QWidget* widget, uint32_t area, uint32_t orientation) override;
void RemoveDockWidget(const AZStd::string& name) override;
void SetDockWidgetVisible(const AZStd::string& name, bool visible) override;
bool IsDockWidgetVisible(const AZStd::string& name) const override;
AZStd::vector<AZStd::string> GetDockWidgetNames() const override;
void ResizeViewportRenderTarget(uint32_t width, uint32_t height) override;
void LockViewportRenderTargetSize(uint32_t width, uint32_t height) override;
void UnlockViewportRenderTargetSize() override;
@@ -75,30 +53,18 @@ namespace MaterialEditor
void OnDocumentUndoStateChanged(const AZ::Uuid& documentId) override;
void OnDocumentSaved(const AZ::Uuid& documentId) override;
void SetupMenu();
void CreateMenu() override;
void CreateTabBar() override;
void SetupTabs();
void AddTabForDocumentId(const AZ::Uuid& documentId);
void RemoveTabForDocumentId(const AZ::Uuid& documentId);
void UpdateTabForDocumentId(const AZ::Uuid& documentId);
QString GetDocumentPath(const AZ::Uuid& documentId) const;
AZ::Uuid GetDocumentIdFromTab(const int tabIndex) const;
void OpenTabContextMenu();
void SelectPreviousTab();
void SelectNextTab();
void OpenTabContextMenu() override;
void closeEvent(QCloseEvent* closeEvent) override;
AzQtComponents::FancyDocking* m_advancedDockManager = nullptr;
QWidget* m_centralWidget = nullptr;
QMenuBar* m_menuBar = nullptr;
AzQtComponents::TabWidget* m_tabWidget = nullptr;
MaterialViewportWidget* m_materialViewport = nullptr;
MaterialEditorToolBar* m_toolBar = nullptr;
AZStd::unordered_map <AZStd::string, AzQtComponents::StyledDockWidget*> m_dockWidgets;
QMenu* m_menuFile = {};
QAction* m_actionNew = {};
QAction* m_actionOpen = {};
@@ -130,7 +96,5 @@ namespace MaterialEditor
QMenu* m_menuHelp = {};
QAction* m_actionHelp = {};
QAction* m_actionAbout = {};
StatusBarWidget* m_statusBar = {};
};
} // namespace MaterialEditor
@@ -6,8 +6,8 @@
*
*/
#include <Atom/Window/MaterialEditorWindowFactoryRequestBus.h>
#include <Atom/Window/MaterialEditorWindowSettings.h>
#include <AtomToolsFramework/Window/AtomToolsMainWindowFactoryRequestBus.h>
#include <AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/SerializeContext.h>
@@ -33,25 +33,25 @@ namespace MaterialEditor
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->EBus<MaterialEditorWindowFactoryRequestBus>("MaterialEditorWindowFactoryRequestBus")
behaviorContext->EBus<AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus>("MaterialEditorWindowAtomRequestBus")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Category, "Editor")
->Attribute(AZ::Script::Attributes::Module, "materialeditor")
->Event("CreateMaterialEditorWindow", &MaterialEditorWindowFactoryRequestBus::Events::CreateMaterialEditorWindow)
->Event("DestroyMaterialEditorWindow", &MaterialEditorWindowFactoryRequestBus::Events::DestroyMaterialEditorWindow)
->Event("CreateMaterialEditorWindow", &AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Events::CreateMainWindow)
->Event("DestroyMaterialEditorWindow", &AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Events::DestroyMainWindow)
;
behaviorContext->EBus<MaterialEditorWindowRequestBus>("MaterialEditorWindowRequestBus")
behaviorContext->EBus<AtomToolsFramework::AtomToolsMainWindowRequestBus>("MaterialEditorWindowRequestBus")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Category, "Editor")
->Attribute(AZ::Script::Attributes::Module, "materialeditor")
->Event("ActivateWindow", &MaterialEditorWindowRequestBus::Events::ActivateWindow)
->Event("SetDockWidgetVisible", &MaterialEditorWindowRequestBus::Events::SetDockWidgetVisible)
->Event("IsDockWidgetVisible", &MaterialEditorWindowRequestBus::Events::IsDockWidgetVisible)
->Event("GetDockWidgetNames", &MaterialEditorWindowRequestBus::Events::GetDockWidgetNames)
->Event("ResizeViewportRenderTarget", &MaterialEditorWindowRequestBus::Events::ResizeViewportRenderTarget)
->Event("LockViewportRenderTargetSize", &MaterialEditorWindowRequestBus::Events::LockViewportRenderTargetSize)
->Event("UnlockViewportRenderTargetSize", &MaterialEditorWindowRequestBus::Events::UnlockViewportRenderTargetSize)
->Event("ActivateWindow", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::ActivateWindow)
->Event("SetDockWidgetVisible", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::SetDockWidgetVisible)
->Event("IsDockWidgetVisible", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::IsDockWidgetVisible)
->Event("GetDockWidgetNames", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::GetDockWidgetNames)
->Event("ResizeViewportRenderTarget", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::ResizeViewportRenderTarget)
->Event("LockViewportRenderTargetSize", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::LockViewportRenderTargetSize)
->Event("UnlockViewportRenderTargetSize", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::UnlockViewportRenderTargetSize)
;
}
}
@@ -80,26 +80,26 @@ namespace MaterialEditor
void MaterialEditorWindowComponent::Activate()
{
AzToolsFramework::EditorWindowRequestBus::Handler::BusConnect();
MaterialEditorWindowFactoryRequestBus::Handler::BusConnect();
AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Handler::BusConnect();
AzToolsFramework::SourceControlConnectionRequestBus::Broadcast(&AzToolsFramework::SourceControlConnectionRequests::EnableSourceControl, true);
}
void MaterialEditorWindowComponent::Deactivate()
{
MaterialEditorWindowFactoryRequestBus::Handler::BusDisconnect();
AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Handler::BusDisconnect();
AzToolsFramework::EditorWindowRequestBus::Handler::BusDisconnect();
m_window.reset();
}
void MaterialEditorWindowComponent::CreateMaterialEditorWindow()
void MaterialEditorWindowComponent::CreateMainWindow()
{
m_materialEditorBrowserInteractions.reset(aznew MaterialEditorBrowserInteractions);
m_window.reset(aznew MaterialEditorWindow);
}
void MaterialEditorWindowComponent::DestroyMaterialEditorWindow()
void MaterialEditorWindowComponent::DestroyMainWindow()
{
m_window.reset();
}
@@ -11,7 +11,7 @@
#include <AzCore/Component/Component.h>
#include <AzToolsFramework/API/EditorWindowRequestBus.h>
#include <Atom/Window/MaterialEditorWindowFactoryRequestBus.h>
#include <AtomToolsFramework/Window/AtomToolsMainWindowFactoryRequestBus.h>
#include <Source/Window/MaterialEditorBrowserInteractions.h>
#include <Source/Window/MaterialEditorWindow.h>
@@ -22,7 +22,7 @@ namespace MaterialEditor
class MaterialEditorWindowComponent
: public AZ::Component
, private AzToolsFramework::EditorWindowRequestBus::Handler
, private MaterialEditorWindowFactoryRequestBus::Handler
, private AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Handler
{
public:
AZ_COMPONENT(MaterialEditorWindowComponent, "{03976F19-3C74-49FE-A15F-7D3CADBA616C}");
@@ -35,9 +35,9 @@ namespace MaterialEditor
private:
////////////////////////////////////////////////////////////////////////
// MaterialEditorWindowFactoryRequestBus::Handler overrides...
void CreateMaterialEditorWindow() override;
void DestroyMaterialEditorWindow() override;
// AtomToolsMainWindowFactoryRequestBus::Handler overrides...
void CreateMainWindow() override;
void DestroyMainWindow() override;
////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
@@ -1,37 +0,0 @@
/*
* 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 <Source/Window/StatusBar/StatusBarWidget.h>
#include <Source/Window/StatusBar/ui_StatusBarWidget.h>
namespace MaterialEditor
{
StatusBarWidget::StatusBarWidget(QWidget* parent)
: QWidget(parent)
, m_ui(new Ui::StatusBarWidget)
{
m_ui->setupUi(this);
}
StatusBarWidget::~StatusBarWidget() = default;
void StatusBarWidget::UpdateStatusInfo(const QString& status)
{
m_ui->m_statusLabel->setText(QString("<font color=\"White\">%1</font>").arg(status));
}
void StatusBarWidget::UpdateStatusWarning(const QString& status)
{
m_ui->m_statusLabel->setText(QString("<font color=\"Yellow\">%1</font>").arg(status));
}
void StatusBarWidget::UpdateStatusError(const QString& status)
{
m_ui->m_statusLabel->setText(QString("<font color=\"Red\">%1</font>").arg(status));
}
} // namespace MaterialEditor
#include <Source/Window/StatusBar/moc_StatusBarWidget.cpp>
@@ -1,42 +0,0 @@
/*
* 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 <AzCore/Memory/SystemAllocator.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QWidget>
AZ_POP_DISABLE_WARNING
#endif
namespace Ui
{
class StatusBarWidget;
}
namespace MaterialEditor
{
//! Status bar for MaterialEditor.
class StatusBarWidget
: public QWidget
{
Q_OBJECT
public:
StatusBarWidget(QWidget* parent = nullptr);
~StatusBarWidget();
void UpdateStatusInfo(const QString& status);
void UpdateStatusWarning(const QString& status);
void UpdateStatusError(const QString& status);
private:
QScopedPointer<Ui::StatusBarWidget> m_ui;
};
} // namespace MaterialEditor
@@ -1,82 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>StatusBarWidget</class>
<widget class="QWidget" name="StatusBarWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>691</width>
<height>165</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>Status Bar</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>2</number>
</property>
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="m_statusLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::MinimumExpanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources>
<include location="../MaterialEditor.qrc"/>
</resources>
<connections/>
</ui>
@@ -9,9 +9,6 @@
set(FILES
Include/Atom/Window/MaterialEditorWindowModule.h
Include/Atom/Window/MaterialEditorWindowSettings.h
Include/Atom/Window/MaterialEditorWindowNotificationBus.h
Include/Atom/Window/MaterialEditorWindowRequestBus.h
Include/Atom/Window/MaterialEditorWindowFactoryRequestBus.h
Source/Window/MaterialEditorBrowserInteractions.h
Source/Window/MaterialEditorBrowserInteractions.cpp
Source/Window/MaterialEditorWindow.h
@@ -48,9 +45,6 @@ set(FILES
Source/Window/ToolBar/ModelPresetComboBox.cpp
Source/Window/ToolBar/LightingPresetComboBox.h
Source/Window/ToolBar/LightingPresetComboBox.cpp
Source/Window/StatusBar/StatusBarWidget.cpp
Source/Window/StatusBar/StatusBarWidget.h
Source/Window/StatusBar/StatusBarWidget.ui
Source/Window/MaterialInspector/MaterialInspector.h
Source/Window/MaterialInspector/MaterialInspector.cpp
Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.h
@@ -1,26 +0,0 @@
/*
* 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
#include <AzCore/EBus/EBus.h>
namespace ShaderManagementConsole
{
class ShaderManagementConsoleWindowNotifications
: public AZ::EBusTraits
{
public:
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
virtual void OnShaderManagementConsoleWindowClosing() {};
};
using ShaderManagementConsoleWindowNotificationBus = AZ::EBus<ShaderManagementConsoleWindowNotifications>;
} // namespace ShaderManagementConsole
@@ -1,33 +0,0 @@
/*
* 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
#include <AzCore/EBus/EBus.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/Asset/AssetCommon.h>
namespace ShaderManagementConsole
{
//! ShaderManagementConsoleWindowRequestBus provides
class ShaderManagementConsoleWindowRequests
: public AZ::EBusTraits
{
public:
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
/// Creates and shows main window
virtual void CreateShaderManagementConsoleWindow() = 0;
//! Destroys main window
virtual void DestroyShaderManagementConsoleWindow() = 0;
};
using ShaderManagementConsoleWindowRequestBus = AZ::EBus<ShaderManagementConsoleWindowRequests>;
} // namespace ShaderManagementConsole
@@ -6,46 +6,16 @@
*
*/
#include <AzCore/IO/Path/Path.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzCore/Utils/Utils.h>
#include <AzFramework/IO/LocalFileIO.h>
#include <AzFramework/Network/AssetProcessorConnection.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzToolsFramework/API/EditorPythonConsoleBus.h>
#include <AzToolsFramework/API/EditorPythonRunnerRequestsBus.h>
#include <AzToolsFramework/Asset/AssetSystemComponent.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserComponent.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
#include <AzToolsFramework/AzToolsFrameworkModule.h>
#include <AzToolsFramework/SourceControl/PerforceComponent.h>
#include <AzToolsFramework/SourceControl/SourceControlAPI.h>
#include <AzToolsFramework/Thumbnails/ThumbnailerComponent.h>
#include <AzToolsFramework/UI/PropertyEditor/PropertyManagerComponent.h>
#include <AzToolsFramework/UI/UICore/QTreeViewStateSaver.hxx>
#include <AzToolsFramework/UI/UICore/QWidgetSavedState.h>
#include <AtomToolsFramework/Util/Util.h>
#include <Atom/RPI.Edit/Common/AssetUtils.h>
#include <Atom/RPI.Public/RPISystemInterface.h>
#include <Atom/Document/ShaderManagementConsoleDocumentModule.h>
#include <Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h>
#include <Atom/Window/ShaderManagementConsoleWindowModule.h>
#include <Atom/Window/ShaderManagementConsoleWindowRequestBus.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <ShaderManagementConsoleApplication.h>
#include <ShaderManagementConsole_Traits_Platform.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QMessageBox>
#include <QObject>
AZ_POP_DISABLE_WARNING
namespace ShaderManagementConsole
{
//! This function returns the build system target name of "ShaderManagementConsole
//! This function returns the build system target name of "ShaderManagementConsole"
AZStd::string ShaderManagementConsoleApplication::GetBuildTargetName() const
{
#if !defined(LY_CMAKE_TARGET)
@@ -75,11 +45,6 @@ namespace ShaderManagementConsole
*AZ::SettingsRegistry::Get(), GetBuildTargetName());
}
ShaderManagementConsoleApplication::~ShaderManagementConsoleApplication()
{
ShaderManagementConsoleWindowNotificationBus::Handler::BusDisconnect();
}
void ShaderManagementConsoleApplication::CreateStaticModules(AZStd::vector<AZ::Module*>& outModules)
{
Base::CreateStaticModules(outModules);
@@ -87,22 +52,6 @@ namespace ShaderManagementConsole
outModules.push_back(aznew ShaderManagementConsoleWindowModule);
}
void ShaderManagementConsoleApplication::OnShaderManagementConsoleWindowClosing()
{
ExitMainLoop();
}
void ShaderManagementConsoleApplication::Destroy()
{
// before modules are unloaded, destroy UI to free up any assets it cached
ShaderManagementConsole::ShaderManagementConsoleWindowRequestBus::Broadcast(
&ShaderManagementConsole::ShaderManagementConsoleWindowRequestBus::Handler::DestroyShaderManagementConsoleWindow);
ShaderManagementConsoleWindowNotificationBus::Handler::BusDisconnect();
Base::Destroy();
}
AZStd::vector<AZStd::string> ShaderManagementConsoleApplication::GetCriticalAssetFilters() const
{
return AZStd::vector<AZStd::string>({ "passes/", "config/" });
@@ -117,27 +66,10 @@ namespace ShaderManagementConsole
const AZStd::string openDocumentPath = commandLine.GetMiscValue(openDocumentIndex);
AZ_Printf(GetBuildTargetName().c_str(), "Opening document: %s", openDocumentPath.c_str());
ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath);
ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(
&ShaderManagementConsoleDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath);
}
Base::ProcessCommandLine(commandLine);
}
void ShaderManagementConsoleApplication::StartInternal()
{
Base::StartInternal();
ShaderManagementConsoleWindowNotificationBus::Handler::BusConnect();
ShaderManagementConsole::ShaderManagementConsoleWindowRequestBus::Broadcast(
&ShaderManagementConsole::ShaderManagementConsoleWindowRequestBus::Handler::CreateShaderManagementConsoleWindow);
}
void ShaderManagementConsoleApplication::Stop()
{
ShaderManagementConsole::ShaderManagementConsoleWindowRequestBus::Broadcast(
&ShaderManagementConsole::ShaderManagementConsoleWindowRequestBus::Handler::DestroyShaderManagementConsoleWindow);
Base::Stop();
}
} // namespace ShaderManagementConsole
@@ -9,16 +9,12 @@
#pragma once
#include <Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h>
#include <Atom/Window/ShaderManagementConsoleWindowNotificationBus.h>
#include <AtomToolsFramework/Application/AtomToolsApplication.h>
#include <QTimer>
namespace ShaderManagementConsole
{
class ShaderManagementConsoleApplication
: public AtomToolsFramework::AtomToolsApplication
, private ShaderManagementConsoleWindowNotificationBus::Handler
{
public:
AZ_TYPE_INFO(ShaderManagementConsole::ShaderManagementConsoleApplication, "{A31B1AEB-4DA3-49CD-884A-CC998FF7546F}");
@@ -26,28 +22,15 @@ namespace ShaderManagementConsole
using Base = AtomToolsFramework::AtomToolsApplication;
ShaderManagementConsoleApplication(int* argc, char*** argv);
virtual ~ShaderManagementConsoleApplication();
//////////////////////////////////////////////////////////////////////////
// AzFramework::Application
void CreateStaticModules(AZStd::vector<AZ::Module*>& outModules) override;
const char* GetCurrentConfigurationName() const override;
void Stop() override;
private:
//////////////////////////////////////////////////////////////////////////
// ShaderManagementConsoleWindowNotificationBus::Handler overrides...
void OnShaderManagementConsoleWindowClosing() override;
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// AzFramework::Application overrides...
void Destroy() override;
//////////////////////////////////////////////////////////////////////////
void ProcessCommandLine(const AZ::CommandLine& commandLine) override;
void StartInternal() override;
void ProcessCommandLine(const AZ::CommandLine& commandLine);
AZStd::string GetBuildTargetName() const override;
AZStd::vector<AZStd::string> GetCriticalAssetFilters() const override;
};
};
} // namespace ShaderManagementConsole
@@ -5,61 +5,47 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzCore/Name/Name.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzFramework/Application/Application.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.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 <Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h>
#include <Atom/Window/ShaderManagementConsoleWindowNotificationBus.h>
#include <Source/Window/ShaderManagementConsoleWindow.h>
#include <Window/ShaderManagementConsoleWindow.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QCloseEvent>
#include <QVariant>
#include <QFileDialog>
#include <QWindow>
#include <QVBoxLayout>
#include <QPushButton>
#include <QTableView>
#include <QHeaderView>
#include <QPushButton>
#include <QStandardItemModel>
#include <QTableView>
#include <QVBoxLayout>
#include <QVariant>
#include <QWindow>
AZ_POP_DISABLE_WARNING
namespace ShaderManagementConsole
{
ShaderManagementConsoleWindow::ShaderManagementConsoleWindow(QWidget* parent /* = 0 */)
: AzQtComponents::DockMainWindow(parent)
: AtomToolsFramework::AtomToolsMainWindow(parent)
{
setWindowTitle("Shader Management Console");
m_advancedDockManager = new AzQtComponents::FancyDocking(this);
setDockNestingEnabled(true);
setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea);
setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
m_menuBar = new QMenuBar(this);
setMenuBar(m_menuBar);
setObjectName("ShaderManagementConsoleWindow");
m_toolBar = new ShaderManagementConsoleToolBar(this);
m_toolBar->setObjectName("ToolBar");
addToolBar(m_toolBar);
m_centralWidget = new QWidget(this);
m_tabWidget = new AzQtComponents::TabWidget(m_centralWidget);
m_tabWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred);
m_tabWidget->setContentsMargins(0, 0, 0, 0);
CreateMenu();
CreateTabBar();
QVBoxLayout* vl = new QVBoxLayout(m_centralWidget);
vl->setMargin(0);
@@ -68,27 +54,8 @@ namespace ShaderManagementConsole
m_centralWidget->setLayout(vl);
setCentralWidget(m_centralWidget);
SetupMenu();
SetupTabs();
m_assetBrowserDockWidget = new AzQtComponents::StyledDockWidget("Asset Browser");
m_assetBrowserDockWidget->setObjectName(m_assetBrowserDockWidget->windowTitle());
m_assetBrowserDockWidget->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable);
m_assetBrowser = new ShaderManagementConsoleBrowserWidget(m_assetBrowserDockWidget);
m_assetBrowser->setMinimumSize(QSize(300, 300));
m_assetBrowserDockWidget->setWidget(m_assetBrowser);
addDockWidget(Qt::BottomDockWidgetArea, m_assetBrowserDockWidget);
resizeDocks({ m_assetBrowserDockWidget }, { 400 }, Qt::Vertical);
m_pythonTerminalDockWidget = new AzQtComponents::StyledDockWidget("Python Terminal");
m_pythonTerminalDockWidget->setObjectName(m_pythonTerminalDockWidget->windowTitle());
m_pythonTerminalDockWidget->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable);
m_pythonTerminal = new AzToolsFramework::CScriptTermDialog(m_pythonTerminalDockWidget);
m_pythonTerminal->setMinimumSize(QSize(300, 300));
m_pythonTerminalDockWidget->setWidget(m_pythonTerminal);
addDockWidget(Qt::BottomDockWidgetArea, m_pythonTerminalDockWidget);
resizeDocks({ m_pythonTerminalDockWidget }, { 400 }, Qt::Vertical);
m_pythonTerminalDockWidget->setVisible(false);
AddDockWidget("Asset Browser", new ShaderManagementConsoleBrowserWidget, Qt::BottomDockWidgetArea, Qt::Vertical);
AddDockWidget("Python Terminal", new AzToolsFramework::CScriptTermDialog, Qt::BottomDockWidgetArea, Qt::Horizontal);
ShaderManagementConsoleDocumentNotificationBus::Handler::BusConnect();
OnDocumentOpened(AZ::Uuid::CreateNull());
@@ -109,7 +76,8 @@ namespace ShaderManagementConsole
return;
}
ShaderManagementConsoleWindowNotificationBus::Broadcast(&ShaderManagementConsoleWindowNotifications::OnShaderManagementConsoleWindowClosing);
AtomToolsFramework::AtomToolsMainWindowNotificationBus::Broadcast(
&AtomToolsFramework::AtomToolsMainWindowNotifications::OnMainWindowClosing);
}
void ShaderManagementConsoleWindow::OnDocumentOpened(const AZ::Uuid& documentId)
@@ -118,14 +86,32 @@ namespace ShaderManagementConsole
ShaderManagementConsoleDocumentRequestBus::EventResult(isOpen, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsOpen);
bool isSavable = false;
ShaderManagementConsoleDocumentRequestBus::EventResult(isSavable, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsSavable);
bool isModified = false;
ShaderManagementConsoleDocumentRequestBus::EventResult(isModified, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsModified);
bool canUndo = false;
ShaderManagementConsoleDocumentRequestBus::EventResult(canUndo, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::CanUndo);
bool canRedo = false;
ShaderManagementConsoleDocumentRequestBus::EventResult(canRedo, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::CanRedo);
AZStd::string absolutePath;
ShaderManagementConsoleDocumentRequestBus::EventResult(absolutePath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath);
AZStd::string filename;
AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename);
// Update UI to display the new document
AddTabForDocumentId(documentId);
UpdateTabForDocumentId(documentId);
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(m_centralWidget);
contentWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
contentWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
contentWidget->setModel(CreateDocumentContent(documentId));
return contentWidget;
});
}
UpdateTabForDocumentId(documentId, filename, absolutePath, isModified);
const bool hasTabs = m_tabWidget->count() > 0;
@@ -144,7 +130,7 @@ namespace ShaderManagementConsole
m_actionUndo->setEnabled(canUndo);
m_actionRedo->setEnabled(canRedo);
m_actionPreferences->setEnabled(false);
m_actionSettings->setEnabled(false);
m_actionAssetBrowser->setEnabled(true);
m_actionPythonTerminal->setEnabled(true);
@@ -165,7 +151,13 @@ namespace ShaderManagementConsole
void ShaderManagementConsoleWindow::OnDocumentModified(const AZ::Uuid& documentId)
{
UpdateTabForDocumentId(documentId);
bool isModified = false;
ShaderManagementConsoleDocumentRequestBus::EventResult(isModified, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsModified);
AZStd::string absolutePath;
ShaderManagementConsoleDocumentRequestBus::EventResult(absolutePath, documentId, &ShaderManagementConsoleDocumentRequestBus::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)
@@ -183,11 +175,19 @@ namespace ShaderManagementConsole
void ShaderManagementConsoleWindow::OnDocumentSaved(const AZ::Uuid& documentId)
{
UpdateTabForDocumentId(documentId);
bool isModified = false;
ShaderManagementConsoleDocumentRequestBus::EventResult(isModified, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsModified);
AZStd::string absolutePath;
ShaderManagementConsoleDocumentRequestBus::EventResult(absolutePath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath);
AZStd::string filename;
AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename);
UpdateTabForDocumentId(documentId, filename, absolutePath, isModified);
}
void ShaderManagementConsoleWindow::SetupMenu()
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 = m_menuBar->addMenu("&File");
@@ -264,23 +264,26 @@ namespace ShaderManagementConsole
m_menuEdit->addSeparator();
m_actionPreferences = m_menuEdit->addAction("&Preferences...", [this]() {
m_actionSettings = m_menuEdit->addAction("&Preferences...", [this]() {
}, QKeySequence::Preferences);
m_actionPreferences->setEnabled(false);
m_actionSettings->setEnabled(false);
m_menuView = m_menuBar->addMenu("&View");
m_actionAssetBrowser = m_menuView->addAction("&Asset Browser", [this]() {
m_assetBrowserDockWidget->setVisible(!m_assetBrowserDockWidget->isVisible());
});
m_actionPythonTerminal = m_menuView->addAction("Python &Terminal", [this]() {
m_pythonTerminalDockWidget->setVisible(!m_pythonTerminalDockWidget->isVisible());
if (m_pythonTerminalDockWidget->isVisible())
m_actionAssetBrowser = m_menuView->addAction(
"&Asset Browser",
[this]()
{
// reposition console window on the bottom, otherwise it gets docked in some weird spot...
addDockWidget(Qt::BottomDockWidgetArea, m_pythonTerminalDockWidget);
}
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();
@@ -302,20 +305,9 @@ namespace ShaderManagementConsole
});
}
void ShaderManagementConsoleWindow::SetupTabs()
void ShaderManagementConsoleWindow::CreateTabBar()
{
// 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();
});
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
@@ -329,125 +321,6 @@ namespace ShaderManagementConsole
});
}
void ShaderManagementConsoleWindow::AddTabForDocumentId(const AZ::Uuid& documentId)
{
bool isOpen = false;
ShaderManagementConsoleDocumentRequestBus::EventResult(isOpen, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsOpen);
if (documentId.IsNull() || !isOpen)
{
return;
}
// 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;
}
}
// Create a new tab for the document ID and assign it's label to the file name of the document.
AZStd::string absolutePath;
ShaderManagementConsoleDocumentRequestBus::EventResult(absolutePath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath);
AZStd::string filename;
AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename);
// The document tab contains a table view.
auto tableView = new QTableView(m_centralWidget);
tableView->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
auto model = new QStandardItemModel();
tableView->setModel(model);
const int tabIndex = m_tabWidget->addTab(tableView, filename.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, absolutePath.c_str());
m_tabWidget->setCurrentIndex(tabIndex);
m_tabWidget->setVisible(true);
m_tabWidget->repaint();
CreateDocumentContent(documentId, model);
}
void ShaderManagementConsoleWindow::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 ShaderManagementConsoleWindow::UpdateTabForDocumentId(const AZ::Uuid& documentId)
{
// 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))
{
AZStd::string absolutePath;
ShaderManagementConsoleDocumentRequestBus::EventResult(absolutePath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath);
AZStd::string filename;
AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename);
bool isModified = false;
ShaderManagementConsoleDocumentRequestBus::EventResult(isModified, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsModified);
// We use an asterisk appended to the file name to denote modified document
if (isModified)
{
filename += " *";
}
m_tabWidget->setTabText(tabIndex, filename.c_str());
m_tabWidget->setTabToolTip(tabIndex, absolutePath.c_str());
m_tabWidget->repaint();
break;
}
}
}
}
AZ::Uuid ShaderManagementConsoleWindow::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 ShaderManagementConsoleWindow::OpenTabContextMenu()
{
const QTabBar* tabBar = m_tabWidget->tabBar();
@@ -472,23 +345,6 @@ namespace ShaderManagementConsole
}
}
void ShaderManagementConsoleWindow::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 ShaderManagementConsoleWindow::SelectNextTab()
{
if (m_tabWidget->count() > 1)
{
m_tabWidget->setCurrentIndex((m_tabWidget->currentIndex() + 1) % m_tabWidget->count());
}
}
void ShaderManagementConsoleWindow::SelectDocumentForTab(const int tabIndex)
{
const AZ::Uuid documentId = GetDocumentIdFromTab(tabIndex);
@@ -521,7 +377,7 @@ namespace ShaderManagementConsole
}
}
void ShaderManagementConsoleWindow::CreateDocumentContent(const AZ::Uuid& documentId, QStandardItemModel* model)
QStandardItemModel* ShaderManagementConsoleWindow::CreateDocumentContent(const AZ::Uuid& documentId)
{
AZStd::unordered_set<AZStd::string> optionNames;
@@ -540,6 +396,7 @@ namespace ShaderManagementConsole
size_t shaderVariantCount = 0;
ShaderManagementConsoleDocumentRequestBus::EventResult(shaderVariantCount, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderVariantCount);
auto model = new QStandardItemModel();
model->setRowCount(static_cast<int>(shaderVariantCount));
model->setColumnCount(static_cast<int>(optionNames.size()));
@@ -568,7 +425,9 @@ namespace ShaderManagementConsole
model->setItem(variantIndex, optionIndex, item);
}
}
return model;
}
} // namespace ShaderManagementConsole
#include <Source/Window/moc_ShaderManagementConsoleWindow.cpp>
#include <Window/moc_ShaderManagementConsoleWindow.cpp>
@@ -9,32 +9,20 @@
#pragma once
#if !defined(Q_MOC_RUN)
#include <AzCore/Memory/SystemAllocator.h>
#include <Atom/Document/ShaderManagementConsoleDocumentNotificationBus.h>
#include <Atom/RPI.Public/Shader/Shader.h>
#include <Atom/RPI.Edit/Shader/ShaderVariantListSourceData.h>
#include <Atom/RPI.Public/Shader/Shader.h>
#include <AtomToolsFramework/Window/AtomToolsMainWindow.h>
#include <AzCore/Memory/SystemAllocator.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <AzQtComponents/Components/DockMainWindow.h>
#include <AzQtComponents/Components/FancyDocking.h>
#include <AzQtComponents/Components/StyledDockWidget.h>
#include <AzQtComponents/Components/Widgets/TabWidget.h>
#include <Window/ShaderManagementConsoleBrowserWidget.h>
#include <Window/ToolBar/ShaderManagementConsoleToolBar.h>
#include <QMenuBar>
#include <QToolBar>
#include <QStandardItemModel>
AZ_POP_DISABLE_WARNING
#endif
namespace AzToolsFramework
{
class CScriptTermDialog;
}
namespace ShaderManagementConsole
{
/**
@@ -42,13 +30,15 @@ namespace ShaderManagementConsole
* its panels, managing selection of assets, and performing high-level actions like saving. It contains...
*/
class ShaderManagementConsoleWindow
: public AzQtComponents::DockMainWindow
: public AtomToolsFramework::AtomToolsMainWindow
, private ShaderManagementConsoleDocumentNotificationBus::Handler
{
Q_OBJECT
public:
AZ_CLASS_ALLOCATOR(ShaderManagementConsoleWindow, AZ::SystemAllocator, 0);
using Base = AtomToolsFramework::AtomToolsMainWindow;
ShaderManagementConsoleWindow(QWidget* parent = 0);
~ShaderManagementConsoleWindow();
@@ -60,17 +50,9 @@ namespace ShaderManagementConsole
void OnDocumentUndoStateChanged(const AZ::Uuid& documentId) override;
void OnDocumentSaved(const AZ::Uuid& documentId) override;
void SetupMenu();
void SetupTabs();
void AddTabForDocumentId(const AZ::Uuid& documentId);
void RemoveTabForDocumentId(const AZ::Uuid& documentId);
void UpdateTabForDocumentId(const AZ::Uuid& documentId);
AZ::Uuid GetDocumentIdFromTab(const int tabIndex) const;
void OpenTabContextMenu();
void SelectPreviousTab();
void SelectNextTab();
void CreateMenu() override;
void CreateTabBar() override;
void OpenTabContextMenu() override;
void SelectDocumentForTab(const int tabIndex);
void CloseDocumentForTab(const int tabIndex);
@@ -78,18 +60,9 @@ namespace ShaderManagementConsole
void closeEvent(QCloseEvent* closeEvent) override;
void CreateDocumentContent(const AZ::Uuid& documentId, QStandardItemModel* model);
QStandardItemModel* CreateDocumentContent(const AZ::Uuid& documentId);
AzQtComponents::FancyDocking* m_advancedDockManager = nullptr;
QMenuBar* m_menuBar = nullptr;
QWidget* m_centralWidget = nullptr;
AzQtComponents::TabWidget* m_tabWidget = nullptr;
ShaderManagementConsoleBrowserWidget* m_assetBrowser = nullptr;
ShaderManagementConsoleToolBar* m_toolBar = nullptr;
AzToolsFramework::CScriptTermDialog* m_pythonTerminal = nullptr;
AzQtComponents::StyledDockWidget* m_assetBrowserDockWidget = nullptr;
AzQtComponents::StyledDockWidget* m_pythonTerminalDockWidget = nullptr;
QMenu* m_menuFile = {};
QMenu* m_menuNew = {};
@@ -106,7 +79,7 @@ namespace ShaderManagementConsole
QMenu* m_menuEdit = {};
QAction* m_actionUndo = {};
QAction* m_actionRedo = {};
QAction* m_actionPreferences = {};
QAction* m_actionSettings = {};
QMenu* m_menuView = {};
QAction* m_actionAssetBrowser = {};
@@ -44,12 +44,12 @@ namespace ShaderManagementConsole
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->EBus<ShaderManagementConsoleWindowRequestBus>("ShaderManagementConsoleWindowRequestBus")
behaviorContext->EBus<AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus>("ShaderManagementConsoleWindowRequestBus")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation)
->Attribute(AZ::Script::Attributes::Category, "Editor")
->Attribute(AZ::Script::Attributes::Module, "shadermanagementconsole")
->Event("CreateShaderManagementConsoleWindow", &ShaderManagementConsoleWindowRequestBus::Events::CreateShaderManagementConsoleWindow)
->Event("DestroyShaderManagementConsoleWindow", &ShaderManagementConsoleWindowRequestBus::Events::DestroyShaderManagementConsoleWindow)
->Event("CreateShaderManagementConsoleWindow", &AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Events::CreateMainWindow)
->Event("DestroyShaderManagementConsoleWindow", &AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Events::DestroyMainWindow)
;
behaviorContext->EBus<ShaderManagementConsoleRequestBus>("ShaderManagementConsoleRequestBus")
@@ -87,7 +87,7 @@ namespace ShaderManagementConsole
void ShaderManagementConsoleWindowComponent::Activate()
{
AzToolsFramework::EditorWindowRequestBus::Handler::BusConnect();
ShaderManagementConsoleWindowRequestBus::Handler::BusConnect();
AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Handler::BusConnect();
ShaderManagementConsoleRequestBus::Handler::BusConnect();
AzToolsFramework::SourceControlConnectionRequestBus::Broadcast(&AzToolsFramework::SourceControlConnectionRequests::EnableSourceControl, true);
}
@@ -95,7 +95,7 @@ namespace ShaderManagementConsole
void ShaderManagementConsoleWindowComponent::Deactivate()
{
ShaderManagementConsoleRequestBus::Handler::BusDisconnect();
ShaderManagementConsoleWindowRequestBus::Handler::BusDisconnect();
AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Handler::BusDisconnect();
AzToolsFramework::EditorWindowRequestBus::Handler::BusDisconnect();
m_window.reset();
@@ -106,7 +106,7 @@ namespace ShaderManagementConsole
return m_window.get();
}
void ShaderManagementConsoleWindowComponent::CreateShaderManagementConsoleWindow()
void ShaderManagementConsoleWindowComponent::CreateMainWindow()
{
m_assetBrowserInteractions.reset(aznew ShaderManagementConsoleBrowserInteractions);
@@ -114,7 +114,7 @@ namespace ShaderManagementConsole
m_window->show();
}
void ShaderManagementConsoleWindowComponent::DestroyShaderManagementConsoleWindow()
void ShaderManagementConsoleWindowComponent::DestroyMainWindow()
{
m_window.reset();
}
@@ -13,7 +13,7 @@
#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
#include <Atom/Window/ShaderManagementConsoleWindowRequestBus.h>
#include <AtomToolsFramework/Window/AtomToolsMainWindowFactoryRequestBus.h>
#include <Atom/Core/ShaderManagementConsoleRequestBus.h>
#include <Source/Window/ShaderManagementConsoleBrowserInteractions.h>
#include <Source/Window/ShaderManagementConsoleWindow.h>
@@ -24,7 +24,7 @@ namespace ShaderManagementConsole
//! used for initialization and registration of other classes, including ShaderManagementConsoleWindow.
class ShaderManagementConsoleWindowComponent
: public AZ::Component
, private ShaderManagementConsoleWindowRequestBus::Handler
, private AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Handler
, private ShaderManagementConsoleRequestBus::Handler
, private AzToolsFramework::EditorWindowRequestBus::Handler
{
@@ -51,9 +51,9 @@ namespace ShaderManagementConsole
//////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// ShaderManagementConsoleWindowRequestBus::Handler overrides...
void CreateShaderManagementConsoleWindow() override;
void DestroyShaderManagementConsoleWindow() override;
// AtomToolsMainWindowFactoryRequestBus::Handler overrides...
void CreateMainWindow() override;
void DestroyMainWindow() override;
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
@@ -8,8 +8,6 @@
set(FILES
Include/Atom/Window/ShaderManagementConsoleWindowModule.h
Include/Atom/Window/ShaderManagementConsoleWindowNotificationBus.h
Include/Atom/Window/ShaderManagementConsoleWindowRequestBus.h
Include/Atom/Core/ShaderManagementConsoleRequestBus.h
Source/Window/ShaderManagementConsoleBrowserInteractions.h
Source/Window/ShaderManagementConsoleBrowserInteractions.cpp