Merge pull request #504 from aws-lumberyard-dev/Atom/guthadam/ATOM-15439

ATOM-15439 Implement basic local socket and server for IPC in material editor and other tools
This commit is contained in:
Guthrie Adams
2021-05-03 15:32:28 -05:00
committed by GitHub
18 changed files with 404 additions and 135 deletions
@@ -33,6 +33,7 @@ ly_add_target(
AZ::AzQtComponents AZ::AzQtComponents
3rdParty::Qt::Core 3rdParty::Qt::Core
3rdParty::Qt::Gui 3rdParty::Qt::Gui
3rdParty::Qt::Network
3rdParty::Qt::Widgets 3rdParty::Qt::Widgets
3rdParty::Python 3rdParty::Python
Gem::Atom_RPI.Edit Gem::Atom_RPI.Edit
@@ -0,0 +1,56 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <AzCore/std/functional.h>
#include <QByteArray>
#include <QLocalServer>
#include <QLocalSocket>
#include <QString>
#endif
namespace AtomToolsFramework
{
//! A named local server that will manage connections and forward recieved data
class LocalServer : public QObject
{
Q_OBJECT
public:
LocalServer();
~LocalServer();
//! Start a named local server
bool Connect(const QString& serverName);
//! Stop the server
void Disconnect();
//! Get server status
bool IsConnected() const;
using ReadHandler = AZStd::function<void(const QByteArray&)>;
//! Set a handler that recieved data will be forwarded to
void SetReadHandler(ReadHandler handler);
private:
void AddConnection(QLocalSocket* connection);
void ReadFromConnection(QLocalSocket* connection);
void DeleteConnection(QLocalSocket* connection);
QString m_serverName;
QLocalServer m_server;
ReadHandler m_readHandler;
};
} // namespace AtomToolsFramework
@@ -0,0 +1,45 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <QLocalSocket>
#endif
namespace AtomToolsFramework
{
//! LocalSocket enables interprocess communication by establ;ishing a connection and sending data to a LocalServer
class LocalSocket : public QObject
{
Q_OBJECT
public:
LocalSocket();
~LocalSocket();
//! Attempt to connect to a named local server
bool Connect(const QString& serverName);
//! Sever connection from server
void Disconnect();
//! Get the sockets connection status
bool IsConnected() const;
//! Send a stream of data to the connected local server
bool Send(const QByteArray& buffer);
private:
QString m_serverName;
QLocalSocket m_socket;
};
} // namespace AtomToolsFramework
@@ -0,0 +1,108 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AtomToolsFramework/Communication/LocalServer.h>
#include <AzCore/Debug/Trace.h>
#include <QString>
namespace AtomToolsFramework
{
LocalServer::LocalServer()
{
AZ_TracePrintf("AtomToolsFramework::LocalServer", "Creating local server\n");
m_server.setSocketOptions(QLocalServer::WorldAccessOption);
QObject::connect(&m_server, &QLocalServer::newConnection, this, [this]() { AddConnection(m_server.nextPendingConnection()); });
}
LocalServer::~LocalServer()
{
Disconnect();
}
bool LocalServer::Connect(const QString& serverName)
{
Disconnect();
m_serverName = serverName;
AZ_TracePrintf("AtomToolsFramework::LocalServer", "Starting: %s\n", m_serverName.toUtf8().constData());
if (m_server.listen(m_serverName))
{
AZ_TracePrintf("AtomToolsFramework::LocalServer", "Started: %s\n", m_serverName.toUtf8().constData());
return true;
}
if (m_server.serverError() == QAbstractSocket::AddressInUseError)
{
AZ_TracePrintf("AtomToolsFramework::LocalServer", "Restarting: %s\n", m_serverName.toUtf8().constData());
Disconnect();
AZ_TracePrintf("AtomToolsFramework::LocalServer", "Starting: %s\n", m_serverName.toUtf8().constData());
if (m_server.listen(m_serverName))
{
return true;
}
}
AZ_TracePrintf("AtomToolsFramework::LocalServer", "Starting failed: %s\n", m_serverName.toUtf8().constData());
Disconnect();
return false;
}
void LocalServer::Disconnect()
{
AZ_TracePrintf("AtomToolsFramework::LocalServer", "Disconnecting: %s\n", m_serverName.toUtf8().constData());
QLocalServer::removeServer(m_serverName);
}
bool LocalServer::IsConnected() const
{
return m_server.isListening();
}
void LocalServer::SetReadHandler(LocalServer::ReadHandler handler)
{
m_readHandler = handler;
}
void LocalServer::AddConnection(QLocalSocket* connection)
{
AZ_TracePrintf("AtomToolsFramework::LocalServer", "Connection added: %s\n", m_serverName.toUtf8().constData());
QObject::connect(connection, &QLocalSocket::readyRead, this, [this, connection]() { ReadFromConnection(connection); });
QObject::connect(connection, &QLocalSocket::disconnected, this, [this, connection]() { DeleteConnection(connection); });
}
void LocalServer::ReadFromConnection(QLocalSocket* connection)
{
if (connection)
{
AZ_TracePrintf("AtomToolsFramework::LocalServer", "Data received: %s\n", m_serverName.toUtf8().constData());
QByteArray buffer = connection->readAll();
if (m_readHandler)
{
m_readHandler(buffer);
}
}
}
void LocalServer::DeleteConnection(QLocalSocket* connection)
{
if (connection)
{
AZ_TracePrintf("AtomToolsFramework::LocalServer", "Deleting connection: %s\n", m_serverName.toUtf8().constData());
connection->deleteLater();
}
}
} // namespace AtomToolsFramework
#include <AtomToolsFramework/Communication/moc_LocalServer.cpp>
@@ -0,0 +1,86 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AtomToolsFramework/Communication/LocalSocket.h>
#include <AzCore/Debug/Trace.h>
#include <QByteArray>
#include <QString>
namespace AtomToolsFramework
{
LocalSocket::LocalSocket()
{
}
LocalSocket::~LocalSocket()
{
Disconnect();
}
bool LocalSocket::Connect(const QString& serverName)
{
Disconnect();
m_serverName = serverName;
AZ_TracePrintf("AtomToolsFramework::LocalSocket", "Connecting to: %s\n", m_serverName.toUtf8().constData());
m_socket.connectToServer(m_serverName);
if (IsConnected())
{
AZ_TracePrintf("AtomToolsFramework::LocalSocket", "Waiting for connection to: %s\n", m_serverName.toUtf8().constData());
if (m_socket.waitForConnected())
{
AZ_TracePrintf("AtomToolsFramework::LocalSocket", "Connected to: %s\n", m_serverName.toUtf8().constData());
return true;
}
}
AZ_TracePrintf("AtomToolsFramework::LocalSocket", "Connecting failed: %s\n", m_serverName.toUtf8().constData());
Disconnect();
return false;
}
void LocalSocket::Disconnect()
{
if (IsConnected())
{
AZ_TracePrintf("AtomToolsFramework::LocalSocket", "Disconnecting from: %s\n", m_serverName.toUtf8().constData());
m_socket.disconnectFromServer();
m_socket.waitForDisconnected();
AZ_TracePrintf("AtomToolsFramework::LocalSocket", "Closing socket\n");
m_socket.close();
}
}
bool LocalSocket::IsConnected() const
{
return m_socket.isOpen();
}
bool LocalSocket::Send(const QByteArray& buffer)
{
if (IsConnected())
{
AZ_TracePrintf("AtomToolsFramework::LocalSocket", "Sending data to: %s\n", m_serverName.toUtf8().constData());
m_socket.write(buffer);
AZ_TracePrintf("AtomToolsFramework::LocalSocket", "Waiting for write to: %s\n", m_serverName.toUtf8().constData());
m_socket.waitForBytesWritten();
return true;
}
return false;
}
} // namespace AtomToolsFramework
#include <AtomToolsFramework/Communication/moc_LocalSocket.cpp>
@@ -10,6 +10,8 @@
# #
set(FILES set(FILES
Include/AtomToolsFramework/Communication/LocalServer.h
Include/AtomToolsFramework/Communication/LocalSocket.h
Include/AtomToolsFramework/Debug/TraceRecorder.h Include/AtomToolsFramework/Debug/TraceRecorder.h
Include/AtomToolsFramework/DynamicProperty/DynamicProperty.h Include/AtomToolsFramework/DynamicProperty/DynamicProperty.h
Include/AtomToolsFramework/DynamicProperty/DynamicPropertyGroup.h Include/AtomToolsFramework/DynamicProperty/DynamicPropertyGroup.h
@@ -22,6 +24,8 @@ set(FILES
Include/AtomToolsFramework/Util/MaterialPropertyUtil.h Include/AtomToolsFramework/Util/MaterialPropertyUtil.h
Include/AtomToolsFramework/Util/Util.h Include/AtomToolsFramework/Util/Util.h
Include/AtomToolsFramework/Viewport/RenderViewportWidget.h Include/AtomToolsFramework/Viewport/RenderViewportWidget.h
Source/Communication/LocalServer.cpp
Source/Communication/LocalSocket.cpp
Source/Debug/TraceRecorder.cpp Source/Debug/TraceRecorder.cpp
Source/DynamicProperty/DynamicProperty.cpp Source/DynamicProperty/DynamicProperty.cpp
Source/DynamicProperty/DynamicPropertyGroup.cpp Source/DynamicProperty/DynamicPropertyGroup.cpp
@@ -93,6 +93,7 @@ ly_add_target(
ly_add_target( ly_add_target(
NAME MaterialEditor EXECUTABLE NAME MaterialEditor EXECUTABLE
NAMESPACE Gem NAMESPACE Gem
AUTOMOC
FILES_CMAKE FILES_CMAKE
materialeditor_files.cmake materialeditor_files.cmake
Source/Platform/${PAL_PLATFORM_NAME}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake Source/Platform/${PAL_PLATFORM_NAME}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
@@ -13,7 +13,6 @@
#include <Atom/Document/MaterialDocumentModule.h> #include <Atom/Document/MaterialDocumentModule.h>
#include <Document/MaterialDocumentSystemComponent.h> #include <Document/MaterialDocumentSystemComponent.h>
#include <AzFramework/TargetManagement/TargetManagementComponent.h>
#include <AzToolsFramework/UI/PropertyEditor/PropertyManagerComponent.h> #include <AzToolsFramework/UI/PropertyEditor/PropertyManagerComponent.h>
#include <AzToolsFramework/Asset/AssetSystemComponent.h> #include <AzToolsFramework/Asset/AssetSystemComponent.h>
@@ -32,7 +31,6 @@ namespace MaterialEditor
return AZ::ComponentTypeList{ return AZ::ComponentTypeList{
azrtti_typeid<AzToolsFramework::AssetSystem::AssetSystemComponent>(), azrtti_typeid<AzToolsFramework::AssetSystem::AssetSystemComponent>(),
azrtti_typeid<MaterialDocumentSystemComponent>(), azrtti_typeid<MaterialDocumentSystemComponent>(),
azrtti_typeid<AzFramework::TargetManagementComponent>(),
}; };
} }
} }
@@ -109,7 +109,6 @@ namespace MaterialEditor
void MaterialDocumentSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) void MaterialDocumentSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
{ {
required.push_back(AZ_CRC("TargetManagerService", 0x6d5708bc));
required.push_back(AZ_CRC("AssetProcessorToolsConnection", 0x734669bc)); required.push_back(AZ_CRC("AssetProcessorToolsConnection", 0x734669bc));
required.push_back(AZ_CRC("AssetDatabaseService", 0x3abf5601)); required.push_back(AZ_CRC("AssetDatabaseService", 0x3abf5601));
required.push_back(AZ_CRC("PropertyManagerService", 0x63a3d7ad)); required.push_back(AZ_CRC("PropertyManagerService", 0x63a3d7ad));
@@ -135,31 +134,16 @@ namespace MaterialEditor
m_documentMap.clear(); m_documentMap.clear();
MaterialDocumentSystemRequestBus::Handler::BusConnect(); MaterialDocumentSystemRequestBus::Handler::BusConnect();
MaterialDocumentNotificationBus::Handler::BusConnect(); MaterialDocumentNotificationBus::Handler::BusConnect();
AzFramework::TmMsgBus::Handler::BusConnect(AZ_CRC("OpenInMaterialEditor", 0x9f92aac8));
} }
void MaterialDocumentSystemComponent::Deactivate() void MaterialDocumentSystemComponent::Deactivate()
{ {
AZ::TickBus::Handler::BusDisconnect(); AZ::TickBus::Handler::BusDisconnect();
AzFramework::TmMsgBus::Handler::BusDisconnect();
MaterialDocumentNotificationBus::Handler::BusDisconnect(); MaterialDocumentNotificationBus::Handler::BusDisconnect();
MaterialDocumentSystemRequestBus::Handler::BusDisconnect(); MaterialDocumentSystemRequestBus::Handler::BusDisconnect();
m_documentMap.clear(); m_documentMap.clear();
} }
void MaterialDocumentSystemComponent::OnReceivedMsg(AzFramework::TmMsgPtr msg)
{
if (msg->GetId() == AZ_CRC("OpenInMaterialEditor", 0x9f92aac8))
{
const char* documentPath = reinterpret_cast<const char*>(msg->GetCustomBlob());
MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::OpenDocument, documentPath);
}
else
{
AZ_Assert(false, "We received a message of an unrecognized class type!");
}
}
AZ::Uuid MaterialDocumentSystemComponent::CreateDocument() AZ::Uuid MaterialDocumentSystemComponent::CreateDocument()
{ {
auto document = AZStd::make_unique<MaterialDocument>(); auto document = AZStd::make_unique<MaterialDocument>();
@@ -16,7 +16,6 @@
#include <AzCore/Component/TickBus.h> #include <AzCore/Component/TickBus.h>
#include <AzCore/std/smart_ptr/shared_ptr.h> #include <AzCore/std/smart_ptr/shared_ptr.h>
#include <AzCore/Asset/AssetCommon.h> #include <AzCore/Asset/AssetCommon.h>
#include <AzFramework/TargetManagement/TargetManagementAPI.h>
#include <Atom/Document/MaterialDocumentNotificationBus.h> #include <Atom/Document/MaterialDocumentNotificationBus.h>
#include <Atom/Document/MaterialDocumentSystemRequestBus.h> #include <Atom/Document/MaterialDocumentSystemRequestBus.h>
@@ -35,7 +34,6 @@ namespace MaterialEditor
class MaterialDocumentSystemComponent class MaterialDocumentSystemComponent
: public AZ::Component : public AZ::Component
, private AZ::TickBus::Handler , private AZ::TickBus::Handler
, private AzFramework::TmMsgBus::Handler
, private MaterialDocumentNotificationBus::Handler , private MaterialDocumentNotificationBus::Handler
, private MaterialDocumentSystemRequestBus::Handler , private MaterialDocumentSystemRequestBus::Handler
{ {
@@ -72,11 +70,6 @@ namespace MaterialEditor
void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// AzFramework::TmMsgBus::Handler overrides...
void OnReceivedMsg(AzFramework::TmMsgPtr msg) override;
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// MaterialDocumentSystemRequestBus::Handler overrides... // MaterialDocumentSystemRequestBus::Handler overrides...
AZ::Uuid CreateDocument() override; AZ::Uuid CreateDocument() override;
@@ -90,6 +90,14 @@ namespace MaterialEditor
}); });
} }
MaterialEditorApplication::~MaterialEditorApplication()
{
AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusDisconnect();
AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusDisconnect();
MaterialEditorWindowNotificationBus::Handler::BusDisconnect();
AZ::Debug::TraceMessageBus::Handler::BusDisconnect();
}
void MaterialEditorApplication::CreateReflectionManager() void MaterialEditorApplication::CreateReflectionManager()
{ {
Application::CreateReflectionManager(); Application::CreateReflectionManager();
@@ -299,12 +307,12 @@ namespace MaterialEditor
return false; return false;
} }
void MaterialEditorApplication::ProcessCommandLine() void MaterialEditorApplication::ProcessCommandLine(const AZ::CommandLine& commandLine)
{ {
const AZStd::string timeoputSwitchName = "timeout"; const AZStd::string timeoputSwitchName = "timeout";
if (m_commandLine.HasSwitch(timeoputSwitchName)) if (commandLine.HasSwitch(timeoputSwitchName))
{ {
const AZStd::string& timeoutValue = m_commandLine.GetSwitchValue(timeoputSwitchName, 0); const AZStd::string& timeoutValue = commandLine.GetSwitchValue(timeoputSwitchName, 0);
const uint32_t timeoutInMs = atoi(timeoutValue.c_str()); const uint32_t timeoutInMs = atoi(timeoutValue.c_str());
AZ_Printf("MaterialEditor", "Timeout scheduled, shutting down in %u ms", timeoutInMs); AZ_Printf("MaterialEditor", "Timeout scheduled, shutting down in %u ms", timeoutInMs);
QTimer::singleShot(timeoutInMs, [this] { QTimer::singleShot(timeoutInMs, [this] {
@@ -315,10 +323,10 @@ namespace MaterialEditor
// Process command line options for running one or more python scripts on startup // Process command line options for running one or more python scripts on startup
const AZStd::string runPythonScriptSwitchName = "runpython"; const AZStd::string runPythonScriptSwitchName = "runpython";
size_t runPythonScriptCount = m_commandLine.GetNumSwitchValues(runPythonScriptSwitchName); size_t runPythonScriptCount = commandLine.GetNumSwitchValues(runPythonScriptSwitchName);
for (size_t runPythonScriptIndex = 0; runPythonScriptIndex < runPythonScriptCount; ++runPythonScriptIndex) for (size_t runPythonScriptIndex = 0; runPythonScriptIndex < runPythonScriptCount; ++runPythonScriptIndex)
{ {
const AZStd::string runPythonScriptPath = m_commandLine.GetSwitchValue(runPythonScriptSwitchName, runPythonScriptIndex); const AZStd::string runPythonScriptPath = commandLine.GetSwitchValue(runPythonScriptSwitchName, runPythonScriptIndex);
AZStd::vector<AZStd::string_view> runPythonArgs; AZStd::vector<AZStd::string_view> runPythonArgs;
AZ_Printf("MaterialEditor", "Launching script: %s", runPythonScriptPath.c_str()); AZ_Printf("MaterialEditor", "Launching script: %s", runPythonScriptPath.c_str());
@@ -329,17 +337,17 @@ namespace MaterialEditor
} }
// Process command line options for opening one or more material documents on startup // Process command line options for opening one or more material documents on startup
size_t openDocumentCount = m_commandLine.GetNumMiscValues(); size_t openDocumentCount = commandLine.GetNumMiscValues();
for (size_t openDocumentIndex = 0; openDocumentIndex < openDocumentCount; ++openDocumentIndex) for (size_t openDocumentIndex = 0; openDocumentIndex < openDocumentCount; ++openDocumentIndex)
{ {
const AZStd::string openDocumentPath = m_commandLine.GetMiscValue(openDocumentIndex); const AZStd::string openDocumentPath = commandLine.GetMiscValue(openDocumentIndex);
AZ_Printf("MaterialEditor", "Opening document: %s", openDocumentPath.c_str()); AZ_Printf("MaterialEditor", "Opening document: %s", openDocumentPath.c_str());
MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath); MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath);
} }
const AZStd::string exitAfterCommandsSwitchName = "exitaftercommands"; const AZStd::string exitAfterCommandsSwitchName = "exitaftercommands";
if (m_commandLine.HasSwitch(exitAfterCommandsSwitchName)) if (commandLine.HasSwitch(exitAfterCommandsSwitchName))
{ {
ExitMainLoop(); ExitMainLoop();
} }
@@ -409,9 +417,50 @@ namespace MaterialEditor
bool MaterialEditorApplication::LaunchDiscoveryService() bool MaterialEditorApplication::LaunchDiscoveryService()
{ {
const QStringList arguments = { "-fail_silently" }; // Determine if this is the first launch of the tool by attempting to connect to a running server
if (m_socket.Connect(QApplication::applicationName()))
{
// If the server was located, the application is already running.
// Forward commandline options to other application instance.
QByteArray buffer;
buffer.append("ProcessCommandLine:");
for (int argi = 1; argi < m_argC; ++argi)
{
buffer.append(QString(m_argV[argi]).append("\n").toUtf8());
}
m_socket.Send(buffer);
m_socket.Disconnect();
return false;
}
return AtomToolsFramework::LaunchTool("GridHub", AZ_TRAIT_MATERIALEDITOR_EXT, arguments); // Setup server to handle basic commands
m_server.SetReadHandler([this](const QByteArray& buffer) {
// Handle commmand line params from connected socket
if (buffer.startsWith("ProcessCommandLine:"))
{
// Remove header and parse commands
AZStd::string params(buffer.data(), buffer.size());
params = params.substr(strlen("ProcessCommandLine:"));
AZStd::vector<AZStd::string> tokens;
AZ::StringFunc::Tokenize(params, tokens, "\n");
if (!tokens.empty())
{
AZ::CommandLine commandLine;
commandLine.Parse(tokens);
ProcessCommandLine(commandLine);
}
}
});
// Launch local server
if (!m_server.Connect(QApplication::applicationName()))
{
return false;
}
return true;
} }
void MaterialEditorApplication::StartInternal() void MaterialEditorApplication::StartInternal()
@@ -421,10 +470,14 @@ namespace MaterialEditor
return; return;
} }
//[GFX TODO][ATOM-415] Try to factor out some of this stuff with AtomSampleViewerApplication
WriteStartupLog(); WriteStartupLog();
if (!LaunchDiscoveryService())
{
ExitMainLoop();
return;
}
AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusConnect(); AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusConnect();
AzToolsFramework::AssetBrowser::AssetDatabaseLocationNotificationBus::Broadcast(&AzToolsFramework::AssetBrowser::AssetDatabaseLocationNotifications::OnDatabaseInitialized); AzToolsFramework::AssetBrowser::AssetDatabaseLocationNotificationBus::Broadcast(&AzToolsFramework::AssetBrowser::AssetDatabaseLocationNotifications::OnDatabaseInitialized);
@@ -434,8 +487,6 @@ namespace MaterialEditor
LoadSettings(); LoadSettings();
LaunchDiscoveryService();
MaterialEditorWindowNotificationBus::Handler::BusConnect(); MaterialEditorWindowNotificationBus::Handler::BusConnect();
MaterialEditor::MaterialEditorWindowFactoryRequestBus::Broadcast( MaterialEditor::MaterialEditorWindowFactoryRequestBus::Broadcast(
@@ -450,7 +501,7 @@ namespace MaterialEditor
} }
// Delay execution of commands and scripts post initialization // Delay execution of commands and scripts post initialization
QTimer::singleShot(0, [this]() { ProcessCommandLine(); }); QTimer::singleShot(0, [this]() { ProcessCommandLine(m_commandLine); });
} }
bool MaterialEditorApplication::GetAssetDatabaseLocation(AZStd::string& result) bool MaterialEditorApplication::GetAssetDatabaseLocation(AZStd::string& result)
@@ -12,22 +12,20 @@
#pragma once #pragma once
#include <Atom/Document/MaterialDocumentSystemRequestBus.h>
#include <Atom/Window/MaterialEditorWindowNotificationBus.h>
#include <AtomToolsFramework/Communication/LocalServer.h>
#include <AtomToolsFramework/Communication/LocalSocket.h>
#include <AzCore/Component/Entity.h> #include <AzCore/Component/Entity.h>
#include <AzCore/Component/TickBus.h> #include <AzCore/Component/TickBus.h>
#include <AzCore/UserSettings/UserSettingsProvider.h>
#include <AzCore/Debug/TraceMessageBus.h> #include <AzCore/Debug/TraceMessageBus.h>
#include <AzCore/UserSettings/UserSettingsProvider.h>
#include <AzFramework/Application/Application.h> #include <AzFramework/Application/Application.h>
#include <AzFramework/Asset/AssetSystemBus.h> #include <AzFramework/Asset/AssetSystemBus.h>
#include <AzFramework/Logging/LogFile.h> #include <AzFramework/Logging/LogFile.h>
#include <AzToolsFramework/API/AssetDatabaseBus.h> #include <AzToolsFramework/API/AssetDatabaseBus.h>
#include <AzToolsFramework/API/EditorPythonConsoleBus.h> #include <AzToolsFramework/API/EditorPythonConsoleBus.h>
#include <Atom/Document/MaterialDocumentSystemRequestBus.h>
#include <Atom/Window/MaterialEditorWindowNotificationBus.h>
#include <QApplication> #include <QApplication>
#include <QTimer> #include <QTimer>
@@ -51,7 +49,7 @@ namespace MaterialEditor
using Base = AzFramework::Application; using Base = AzFramework::Application;
MaterialEditorApplication(int* argc, char*** argv); MaterialEditorApplication(int* argc, char*** argv);
virtual ~MaterialEditorApplication() = default; virtual ~MaterialEditorApplication();
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// AzFramework::Application // AzFramework::Application
@@ -110,7 +108,7 @@ namespace MaterialEditor
void CompileCriticalAssets(); void CompileCriticalAssets();
void ProcessCommandLine(); void ProcessCommandLine(const AZ::CommandLine& commandLine);
void WriteStartupLog(); void WriteStartupLog();
void LoadSettings(); void LoadSettings();
@@ -138,5 +136,8 @@ namespace MaterialEditor
bool m_activatedLocalUserSettings = false; bool m_activatedLocalUserSettings = false;
QTimer m_timer; QTimer m_timer;
AtomToolsFramework::LocalSocket m_socket;
AtomToolsFramework::LocalServer m_server;
}; };
} // namespace MaterialEditor } // namespace MaterialEditor
@@ -1,30 +1,31 @@
/* /*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors. * its licensors.
* *
* For complete copyright and license terms please see the LICENSE at the root of this * For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License, * distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not * or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* *
*/ */
#if !defined(Q_MOC_RUN)
#include <MaterialEditorApplication.h>
#include <AzCore/IO/Path/Path.h> #include <AzCore/IO/Path/Path.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h> #include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzQtComponents/Components/StyleManager.h>
#include <AzQtComponents/Utilities/QtPluginPaths.h>
#include <AzQtComponents/Components/GlobalEventFilter.h> #include <AzQtComponents/Components/GlobalEventFilter.h>
#include <AzQtComponents/Components/StyledDockWidget.h>
#include <AzQtComponents/Components/O3DEStylesheet.h> #include <AzQtComponents/Components/O3DEStylesheet.h>
#include <AzQtComponents/Utilities/QtPluginPaths.h> #include <AzQtComponents/Components/StyleManager.h>
#include <AzQtComponents/Utilities/HandleDpiAwareness.h> #include <AzQtComponents/Components/StyledDockWidget.h>
#include <AzQtComponents/Components/WindowDecorationWrapper.h> #include <AzQtComponents/Components/WindowDecorationWrapper.h>
#include <AzQtComponents/Utilities/HandleDpiAwareness.h>
#include <AzQtComponents/Utilities/QtPluginPaths.h>
#include <QtWidgets/QApplication>
#include <QtGui/private/qhighdpiscaling_p.h> #include <QtGui/private/qhighdpiscaling_p.h>
#include <QtWidgets/QApplication>
#include <Source/MaterialEditorApplication.h> #endif
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
@@ -45,15 +46,16 @@ int main(int argc, char** argv)
AzQtComponents::Utilities::HandleDpiAwareness(AzQtComponents::Utilities::SystemDpiAware); AzQtComponents::Utilities::HandleDpiAwareness(AzQtComponents::Utilities::SystemDpiAware);
MaterialEditor::MaterialEditorApplication app(&argc, &argv); MaterialEditor::MaterialEditorApplication app(&argc, &argv);
auto globalEventFilter = new AzQtComponents::GlobalEventFilter(&app);
app.installEventFilter(globalEventFilter);
AZ::IO::FixedMaxPath engineRootPath; AZ::IO::FixedMaxPath engineRootPath;
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr) if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
{ {
settingsRegistry->Get(engineRootPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder); settingsRegistry->Get(engineRootPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder);
} }
auto globalEventFilter = new AzQtComponents::GlobalEventFilter(&app);
app.installEventFilter(globalEventFilter);
AzQtComponents::StyleManager styleManager(&app); AzQtComponents::StyleManager styleManager(&app);
styleManager.initialize(&app, engineRootPath); styleManager.initialize(&app, engineRootPath);
@@ -13,7 +13,6 @@
#include <Atom/Document/ShaderManagementConsoleDocumentModule.h> #include <Atom/Document/ShaderManagementConsoleDocumentModule.h>
#include <Document/ShaderManagementConsoleDocumentSystemComponent.h> #include <Document/ShaderManagementConsoleDocumentSystemComponent.h>
#include <AzFramework/TargetManagement/TargetManagementComponent.h>
#include <AzToolsFramework/UI/PropertyEditor/PropertyManagerComponent.h> #include <AzToolsFramework/UI/PropertyEditor/PropertyManagerComponent.h>
#include <AzToolsFramework/Asset/AssetSystemComponent.h> #include <AzToolsFramework/Asset/AssetSystemComponent.h>
@@ -32,7 +31,6 @@ namespace ShaderManagementConsole
return AZ::ComponentTypeList{ return AZ::ComponentTypeList{
azrtti_typeid<AzToolsFramework::AssetSystem::AssetSystemComponent>(), azrtti_typeid<AzToolsFramework::AssetSystem::AssetSystemComponent>(),
azrtti_typeid<ShaderManagementConsoleDocumentSystemComponent>(), azrtti_typeid<ShaderManagementConsoleDocumentSystemComponent>(),
azrtti_typeid<AzFramework::TargetManagementComponent>(),
}; };
} }
} }
@@ -105,7 +105,6 @@ namespace ShaderManagementConsole
void ShaderManagementConsoleDocumentSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) void ShaderManagementConsoleDocumentSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
{ {
required.push_back(AZ_CRC("TargetManagerService", 0x6d5708bc));
required.push_back(AZ_CRC("AssetProcessorToolsConnection", 0x734669bc)); required.push_back(AZ_CRC("AssetProcessorToolsConnection", 0x734669bc));
required.push_back(AZ_CRC("AssetDatabaseService", 0x3abf5601)); required.push_back(AZ_CRC("AssetDatabaseService", 0x3abf5601));
required.push_back(AZ_CRC("PropertyManagerService", 0x63a3d7ad)); required.push_back(AZ_CRC("PropertyManagerService", 0x63a3d7ad));
@@ -130,13 +129,11 @@ namespace ShaderManagementConsole
{ {
m_documentMap.clear(); m_documentMap.clear();
ShaderManagementConsoleDocumentSystemRequestBus::Handler::BusConnect(); ShaderManagementConsoleDocumentSystemRequestBus::Handler::BusConnect();
AzFramework::TmMsgBus::Handler::BusConnect(AZ_CRC("OpenInShaderManagementConsole", 0x9f92aac8));
} }
void ShaderManagementConsoleDocumentSystemComponent::Deactivate() void ShaderManagementConsoleDocumentSystemComponent::Deactivate()
{ {
ShaderManagementConsoleDocumentSystemRequestBus::Handler::BusDisconnect(); ShaderManagementConsoleDocumentSystemRequestBus::Handler::BusDisconnect();
AzFramework::TmMsgBus::Handler::BusDisconnect();
m_documentMap.clear(); m_documentMap.clear();
} }
@@ -159,19 +156,6 @@ namespace ShaderManagementConsole
return m_documentMap.erase(documentId) != 0; return m_documentMap.erase(documentId) != 0;
} }
void ShaderManagementConsoleDocumentSystemComponent::OnReceivedMsg(AzFramework::TmMsgPtr msg)
{
if (msg->GetId() == AZ_CRC("OpenInShaderManagementConsole", 0x9f92aac8))
{
const char* documentPath = reinterpret_cast<const char*>(msg->GetCustomBlob());
ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::OpenDocument, documentPath);
}
else
{
AZ_Assert(false, "We received a message of an unrecognized class type!");
}
}
AZ::Uuid ShaderManagementConsoleDocumentSystemComponent::OpenDocument(AZStd::string_view path) AZ::Uuid ShaderManagementConsoleDocumentSystemComponent::OpenDocument(AZStd::string_view path)
{ {
return OpenDocumentImpl(path, true); return OpenDocumentImpl(path, true);
@@ -14,7 +14,6 @@
#include <AzCore/Component/Component.h> #include <AzCore/Component/Component.h>
#include <AzCore/std/smart_ptr/shared_ptr.h> #include <AzCore/std/smart_ptr/shared_ptr.h>
#include <AzFramework/TargetManagement/TargetManagementAPI.h>
#include <Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h> #include <Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h>
#include <Atom/RPI.Public/WindowContext.h> #include <Atom/RPI.Public/WindowContext.h>
@@ -30,7 +29,6 @@ namespace ShaderManagementConsole
//! ShaderManagementConsoleDocumentSystemComponent is the central component of the Shader Management Console Core gem //! ShaderManagementConsoleDocumentSystemComponent is the central component of the Shader Management Console Core gem
class ShaderManagementConsoleDocumentSystemComponent class ShaderManagementConsoleDocumentSystemComponent
: public AZ::Component : public AZ::Component
, private AzFramework::TmMsgBus::Handler
, private ShaderManagementConsoleDocumentSystemRequestBus::Handler , private ShaderManagementConsoleDocumentSystemRequestBus::Handler
{ {
public: public:
@@ -55,11 +53,6 @@ namespace ShaderManagementConsole
void Deactivate() override; void Deactivate() override;
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// TmMsgBus::Handler overrides...
void OnReceivedMsg(AzFramework::TmMsgPtr msg) override;
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// ShaderManagementConsoleDocumentSystemRequestBus::Handler overrides... // ShaderManagementConsoleDocumentSystemRequestBus::Handler overrides...
AZ::Uuid CreateDocument() override; AZ::Uuid CreateDocument() override;
@@ -93,7 +93,6 @@ namespace AZ
void EditorMaterialSystemComponent::Activate() void EditorMaterialSystemComponent::Activate()
{ {
AzFramework::TargetManagerClient::Bus::Handler::BusConnect();
EditorMaterialSystemComponentRequestBus::Handler::BusConnect(); EditorMaterialSystemComponentRequestBus::Handler::BusConnect();
AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusConnect(); AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusConnect();
AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusConnect(); AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusConnect();
@@ -105,7 +104,6 @@ namespace AZ
void EditorMaterialSystemComponent::Deactivate() void EditorMaterialSystemComponent::Deactivate()
{ {
AzFramework::TargetManagerClient::Bus::Handler::BusDisconnect();
EditorMaterialSystemComponentRequestBus::Handler::BusDisconnect(); EditorMaterialSystemComponentRequestBus::Handler::BusDisconnect();
AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusDisconnect(); AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusDisconnect();
AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusDisconnect(); AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusDisconnect();
@@ -123,36 +121,11 @@ namespace AZ
void EditorMaterialSystemComponent::OpenInMaterialEditor(const AZStd::string& sourcePath) void EditorMaterialSystemComponent::OpenInMaterialEditor(const AZStd::string& sourcePath)
{ {
if (m_materialEditorTarget.IsValid()) AZ_TracePrintf("MaterialComponent", "Launching Material Editor");
{
AzFramework::TmMsg openDocumentMsg(AZ_CRC("OpenInMaterialEditor", 0x9f92aac8));
openDocumentMsg.AddCustomBlob(sourcePath.c_str(), sourcePath.size() + 1);
AzFramework::TargetManager::Bus::Broadcast(&AzFramework::TargetManager::SendTmMessage, m_materialEditorTarget, openDocumentMsg);
}
else
{
AZ_TracePrintf("MaterialComponent", "Launching Material Editor");
QStringList arguments; QStringList arguments;
arguments.append(sourcePath.c_str()); arguments.append(sourcePath.c_str());
AtomToolsFramework::LaunchTool("MaterialEditor", ".exe", arguments); AtomToolsFramework::LaunchTool("MaterialEditor", ".exe", arguments);
}
}
void EditorMaterialSystemComponent::TargetJoinedNetwork(AzFramework::TargetInfo info)
{
if (AZ::StringFunc::Equal(info.GetDisplayName(), "MaterialEditor"))
{
m_materialEditorTarget = info;
}
}
void EditorMaterialSystemComponent::TargetLeftNetwork(AzFramework::TargetInfo info)
{
if (AZ::StringFunc::Equal(info.GetDisplayName(), "MaterialEditor"))
{
m_materialEditorTarget = {};
}
} }
void EditorMaterialSystemComponent::OnApplicationAboutToStop() void EditorMaterialSystemComponent::OnApplicationAboutToStop()
@@ -14,7 +14,6 @@
#include <AzCore/Component/Component.h> #include <AzCore/Component/Component.h>
#include <AzFramework/Application/Application.h> #include <AzFramework/Application/Application.h>
#include <AzFramework/TargetManagement/TargetManagementAPI.h>
#include <AzToolsFramework/Thumbnails/Thumbnail.h> #include <AzToolsFramework/Thumbnails/Thumbnail.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h> #include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
@@ -32,7 +31,6 @@ namespace AZ
class EditorMaterialSystemComponent class EditorMaterialSystemComponent
: public AZ::Component : public AZ::Component
, private EditorMaterialSystemComponentRequestBus::Handler , private EditorMaterialSystemComponentRequestBus::Handler
, private AzFramework::TargetManagerClient::Bus::Handler
, private AzFramework::ApplicationLifecycleEvents::Bus::Handler , private AzFramework::ApplicationLifecycleEvents::Bus::Handler
, public AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler , public AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler
, public AzToolsFramework::EditorMenuNotificationBus::Handler , public AzToolsFramework::EditorMenuNotificationBus::Handler
@@ -57,10 +55,6 @@ namespace AZ
//! EditorMaterialSystemComponentRequestBus::Handler overrides... //! EditorMaterialSystemComponentRequestBus::Handler overrides...
void OpenInMaterialEditor(const AZStd::string& sourcePath) override; void OpenInMaterialEditor(const AZStd::string& sourcePath) override;
//! AzFramework::TargetManagerClient::Bus::Handler overrides...
void TargetJoinedNetwork(AzFramework::TargetInfo info) override;
void TargetLeftNetwork(AzFramework::TargetInfo info) override;
// AzFramework::ApplicationLifecycleEvents overrides... // AzFramework::ApplicationLifecycleEvents overrides...
void OnApplicationAboutToStop() override; void OnApplicationAboutToStop() override;
@@ -74,9 +68,6 @@ namespace AZ
void SetupThumbnails(); void SetupThumbnails();
void TeardownThumbnails(); void TeardownThumbnails();
// Material Editor target for interprocess communication with MaterialEditor
AzFramework::TargetInfo m_materialEditorTarget;
QAction* m_openMaterialEditorAction = nullptr; QAction* m_openMaterialEditorAction = nullptr;
AZStd::unique_ptr<MaterialBrowserInteractions> m_materialBrowserInteractions; AZStd::unique_ptr<MaterialBrowserInteractions> m_materialBrowserInteractions;