c6ba1ef064
• This change is partially to unblock physics tool prototyping. It introduces a tool ID that is passed down into systems and acts as a context for document, window, and other systems and buses. • The document system component is no longer a component. It is just a system class that can be constructed with a tool ID. Internally, it will connect to its buses and be addressable by tool ID. More than one can be instantiated, each with a unique tool ID. • These changes are still backward compatible because most of the buses were using broadcast for standalone applications. All of those calls have been updated but not all of the scripts, which should still work as is. • Got rid of the window factory request bus in favor of just instantiating the main window or any other UI in the application layer. • Fixed a couple of bugs that were discovered while making these changes. Signed-off-by: Guthrie Adams <guthadam@amazon.com>
253 lines
8.8 KiB
C++
253 lines
8.8 KiB
C++
/*
|
|
* 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 <Atom/RHI/Factory.h>
|
|
#include <AtomToolsFramework/PerformanceMonitor/PerformanceMonitorRequestBus.h>
|
|
#include <AtomToolsFramework/Window/AtomToolsMainWindow.h>
|
|
#include <AzCore/Name/Name.h>
|
|
#include <AzCore/Utils/Utils.h>
|
|
#include <AzToolsFramework/API/EditorPythonRunnerRequestsBus.h>
|
|
#include <AzToolsFramework/PythonTerminal/ScriptTermDialog.h>
|
|
|
|
#include <QFileDialog>
|
|
#include <QMenu>
|
|
#include <QMenuBar>
|
|
#include <QStatusBar>
|
|
#include <QVBoxLayout>
|
|
|
|
namespace AtomToolsFramework
|
|
{
|
|
AtomToolsMainWindow::AtomToolsMainWindow(const AZ::Crc32& toolId, QWidget* parent)
|
|
: AzQtComponents::DockMainWindow(parent)
|
|
, m_toolId(toolId)
|
|
, 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);
|
|
|
|
AddCommonMenus();
|
|
|
|
m_statusMessage = new QLabel(statusBar());
|
|
statusBar()->addPermanentWidget(m_statusMessage, 1);
|
|
|
|
auto centralWidget = new QWidget(this);
|
|
auto centralWidgetLayout = new QVBoxLayout(centralWidget);
|
|
centralWidgetLayout->setMargin(0);
|
|
centralWidgetLayout->setContentsMargins(0, 0, 0, 0);
|
|
centralWidget->setLayout(centralWidgetLayout);
|
|
setCentralWidget(centralWidget);
|
|
|
|
m_assetBrowser = new AtomToolsAssetBrowser(this);
|
|
AddDockWidget("Asset Browser", m_assetBrowser, Qt::BottomDockWidgetArea, Qt::Horizontal);
|
|
AddDockWidget("Python Terminal", new AzToolsFramework::CScriptTermDialog, Qt::BottomDockWidgetArea, Qt::Horizontal);
|
|
SetDockWidgetVisible("Python Terminal", false);
|
|
|
|
SetupMetrics();
|
|
UpdateWindowTitle();
|
|
resize(1280, 1024);
|
|
|
|
AtomToolsMainWindowRequestBus::Handler::BusConnect(m_toolId);
|
|
}
|
|
|
|
AtomToolsMainWindow::~AtomToolsMainWindow()
|
|
{
|
|
PerformanceMonitorRequestBus::Broadcast(&PerformanceMonitorRequestBus::Handler::SetProfilerEnabled, false);
|
|
AtomToolsMainWindowRequestBus::Handler::BusDisconnect();
|
|
}
|
|
|
|
void AtomToolsMainWindow::ActivateWindow()
|
|
{
|
|
show();
|
|
raise();
|
|
activateWindow();
|
|
}
|
|
|
|
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;
|
|
|
|
m_dockActions[name] = m_menuView->addAction(name.c_str(), [this, name](){
|
|
SetDockWidgetVisible(name, !IsDockWidgetVisible(name));
|
|
});
|
|
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);
|
|
}
|
|
auto dockActionItr = m_dockActions.find(name);
|
|
if (dockActionItr != m_dockActions.end())
|
|
{
|
|
delete dockActionItr->second;
|
|
m_dockActions.erase(dockActionItr);
|
|
}
|
|
}
|
|
|
|
void AtomToolsMainWindow::SetDockWidgetVisible(const AZStd::string& name, bool visible)
|
|
{
|
|
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::SetStatusMessage(const QString& message)
|
|
{
|
|
m_statusMessage->setText(QString("<font color=\"White\">%1</font>").arg(message));
|
|
}
|
|
|
|
void AtomToolsMainWindow::SetStatusWarning(const QString& message)
|
|
{
|
|
m_statusMessage->setText(QString("<font color=\"Yellow\">%1</font>").arg(message));
|
|
}
|
|
|
|
void AtomToolsMainWindow::SetStatusError(const QString& message)
|
|
{
|
|
m_statusMessage->setText(QString("<font color=\"Red\">%1</font>").arg(message));
|
|
}
|
|
|
|
void AtomToolsMainWindow::AddCommonMenus()
|
|
{
|
|
m_menuFile = menuBar()->addMenu("&File");
|
|
m_menuEdit = menuBar()->addMenu("&Edit");
|
|
m_menuView = menuBar()->addMenu("&View");
|
|
m_menuHelp = menuBar()->addMenu("&Help");
|
|
|
|
m_menuFile->addAction("Run &Python...", [this]() {
|
|
const QString script = QFileDialog::getOpenFileName(
|
|
this, QObject::tr("Run Script"), QString(AZ::Utils::GetProjectPath().c_str()), QString("*.py"));
|
|
if (!script.isEmpty())
|
|
{
|
|
AzToolsFramework::EditorPythonRunnerRequestBus::Broadcast(
|
|
&AzToolsFramework::EditorPythonRunnerRequestBus::Events::ExecuteByFilename, script.toUtf8().constData());
|
|
}
|
|
});
|
|
|
|
m_menuFile->addSeparator();
|
|
|
|
m_menuFile->addAction("E&xit", [this]() {
|
|
close();
|
|
}, QKeySequence::Quit);
|
|
|
|
m_menuEdit->addAction("&Settings...", [this]() {
|
|
OpenSettings();
|
|
}, QKeySequence::Preferences);
|
|
|
|
m_menuHelp->addAction("&Help...", [this]() {
|
|
OpenHelp();
|
|
});
|
|
|
|
m_menuHelp->addAction("&About...", [this]() {
|
|
OpenAbout();
|
|
});
|
|
}
|
|
|
|
void AtomToolsMainWindow::OpenSettings()
|
|
{
|
|
}
|
|
|
|
void AtomToolsMainWindow::OpenHelp()
|
|
{
|
|
}
|
|
|
|
void AtomToolsMainWindow::OpenAbout()
|
|
{
|
|
}
|
|
|
|
|
|
void AtomToolsMainWindow::SetupMetrics()
|
|
{
|
|
m_statusBarCpuTime = new QLabel(this);
|
|
statusBar()->addPermanentWidget(m_statusBarCpuTime);
|
|
m_statusBarGpuTime = new QLabel(this);
|
|
statusBar()->addPermanentWidget(m_statusBarGpuTime);
|
|
m_statusBarFps = new QLabel(this);
|
|
statusBar()->addPermanentWidget(m_statusBarFps);
|
|
|
|
static constexpr int UpdateIntervalMs = 1000;
|
|
m_metricsTimer.setInterval(UpdateIntervalMs);
|
|
m_metricsTimer.start();
|
|
connect(&m_metricsTimer, &QTimer::timeout, this, &AtomToolsMainWindow::UpdateMetrics);
|
|
|
|
PerformanceMonitorRequestBus::Broadcast(&PerformanceMonitorRequestBus::Handler::SetProfilerEnabled, true);
|
|
|
|
UpdateMetrics();
|
|
}
|
|
|
|
void AtomToolsMainWindow::UpdateMetrics()
|
|
{
|
|
PerformanceMetrics metrics = {};
|
|
PerformanceMonitorRequestBus::BroadcastResult(metrics, &PerformanceMonitorRequestBus::Handler::GetMetrics);
|
|
|
|
m_statusBarCpuTime->setText(tr("CPU Time %1 ms").arg(QString::number(metrics.m_cpuFrameTimeMs, 'f', 2)));
|
|
m_statusBarGpuTime->setText(tr("GPU Time %1 ms").arg(QString::number(metrics.m_gpuFrameTimeMs, 'f', 2)));
|
|
int frameRate = metrics.m_cpuFrameTimeMs > 0 ? aznumeric_cast<int>(1000 / metrics.m_cpuFrameTimeMs) : 0;
|
|
m_statusBarFps->setText(tr("FPS %1").arg(QString::number(frameRate)));
|
|
}
|
|
|
|
void AtomToolsMainWindow::UpdateWindowTitle()
|
|
{
|
|
AZ::Name apiName = AZ::RHI::Factory::Get().GetName();
|
|
if (!apiName.IsEmpty())
|
|
{
|
|
QString title = QString{ "%1 (%2)" }.arg(QApplication::applicationName()).arg(apiName.GetCStr());
|
|
setWindowTitle(title);
|
|
}
|
|
else
|
|
{
|
|
AZ_Assert(false, "Render API name not found");
|
|
setWindowTitle(QApplication::applicationName());
|
|
}
|
|
}
|
|
} // namespace AtomToolsFramework
|