Atom Tools: updated document and windows systems and buses to support multiple instances

• 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>
monroegm-disable-blank-issue-2
Guthrie Adams 4 years ago
parent 257f3cb1ce
commit c6ba1ef064

@ -162,11 +162,11 @@ def select_model_config(configname):
azlmbr.materialeditor.MaterialViewportRequestBus(azlmbr.bus.Broadcast, "SelectModelPresetByName", configname) azlmbr.materialeditor.MaterialViewportRequestBus(azlmbr.bus.Broadcast, "SelectModelPresetByName", configname)
def destroy_main_window(): def exit():
""" """
Closes the Material Editor window Closes the Material Editor
""" """
azlmbr.atomtools.AtomToolsMainWindowFactoryRequestBus(azlmbr.bus.Broadcast, "DestroyMainWindow") azlmbr.atomtools.general.exit()
def wait_for_condition(function, timeout_in_seconds=1.0): def wait_for_condition(function, timeout_in_seconds=1.0):

@ -214,7 +214,7 @@ def run():
(not material_editor.is_open(document1_id)) and (not material_editor.is_open(document1_id)) and
(not material_editor.is_open(document2_id)) and (not material_editor.is_open(document2_id)) and
(not material_editor.is_open(document3_id)), 2.0) (not material_editor.is_open(document3_id)), 2.0)
material_editor.destroy_main_window() material_editor.exit()
if __name__ == "__main__": if __name__ == "__main__":

@ -39,16 +39,16 @@ namespace AtomToolsFramework
{ {
public: public:
AZ_TYPE_INFO(AtomTools::AtomToolsApplication, "{A0DF25BA-6F74-4F11-9F85-0F99278D5986}"); AZ_TYPE_INFO(AtomTools::AtomToolsApplication, "{A0DF25BA-6F74-4F11-9F85-0F99278D5986}");
AZ_DISABLE_COPY_MOVE(AtomToolsApplication);
using Base = AzFramework::Application; using Base = AzFramework::Application;
AtomToolsApplication(int* argc, char*** argv); AtomToolsApplication(const AZStd::string& targetName, int* argc, char*** argv);
~AtomToolsApplication(); ~AtomToolsApplication();
virtual bool LaunchLocalServer(); virtual bool LaunchLocalServer();
////////////////////////////////////////////////////////////////////////// // AzFramework::Application overrides...
// AzFramework::Application
void CreateReflectionManager() override; void CreateReflectionManager() override;
void Reflect(AZ::ReflectContext* context) override; void Reflect(AZ::ReflectContext* context) override;
void RegisterCoreComponents() override; void RegisterCoreComponents() override;
@ -57,43 +57,25 @@ namespace AtomToolsFramework
const char* GetCurrentConfigurationName() const override; const char* GetCurrentConfigurationName() const override;
void StartCommon(AZ::Entity* systemEntity) override; void StartCommon(AZ::Entity* systemEntity) override;
void Tick() override; void Tick() override;
void Stop() override; void Destroy() override;
protected: protected:
//////////////////////////////////////////////////////////////////////////
// AtomsToolMainWindowNotificationBus::Handler overrides... // AtomsToolMainWindowNotificationBus::Handler overrides...
void OnMainWindowClosing() override; void OnMainWindowClosing() override;
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// AssetDatabaseRequestsBus::Handler overrides... // AssetDatabaseRequestsBus::Handler overrides...
bool GetAssetDatabaseLocation(AZStd::string& result) override; bool GetAssetDatabaseLocation(AZStd::string& result) override;
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// AzFramework::Application overrides...
void Destroy() override;
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// AZ::ComponentApplication overrides... // AZ::ComponentApplication overrides...
void QueryApplicationType(AZ::ApplicationTypeQuery& appType) const override; void QueryApplicationType(AZ::ApplicationTypeQuery& appType) const override;
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// AZ::UserSettingsOwnerRequestBus::Handler overrides... // AZ::UserSettingsOwnerRequestBus::Handler overrides...
void SaveSettings() override; void SaveSettings() override;
//////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// EditorPythonConsoleNotificationBus::Handler overrides... // EditorPythonConsoleNotificationBus::Handler overrides...
void OnTraceMessage(AZStd::string_view message) override; void OnTraceMessage(AZStd::string_view message) override;
void OnErrorMessage(AZStd::string_view message) override; void OnErrorMessage(AZStd::string_view message) override;
void OnExceptionMessage(AZStd::string_view message) override; void OnExceptionMessage(AZStd::string_view message) override;
////////////////////////////////////////////////////////////////////////
//! Executable target name generally used as a prefix for logging and other saved files
virtual AZStd::string GetBuildTargetName() const;
//! List of filters for assets that need to be pre-built to run the application //! List of filters for assets that need to be pre-built to run the application
virtual AZStd::vector<AZStd::string> GetCriticalAssetFilters() const; virtual AZStd::vector<AZStd::string> GetCriticalAssetFilters() const;
@ -121,5 +103,8 @@ namespace AtomToolsFramework
AtomToolsFramework::LocalSocket m_socket; AtomToolsFramework::LocalSocket m_socket;
AtomToolsFramework::LocalServer m_server; AtomToolsFramework::LocalServer m_server;
const AZStd::string m_targetName;
const AZ::Crc32 m_toolId = {};
}; };
} // namespace AtomToolsFramework } // namespace AtomToolsFramework

@ -23,9 +23,9 @@ namespace AtomToolsFramework
public: public:
AZ_RTTI(AtomToolsDocument, "{8992DF74-88EC-438C-B280-6E71D4C0880B}"); AZ_RTTI(AtomToolsDocument, "{8992DF74-88EC-438C-B280-6E71D4C0880B}");
AZ_CLASS_ALLOCATOR(AtomToolsDocument, AZ::SystemAllocator, 0); AZ_CLASS_ALLOCATOR(AtomToolsDocument, AZ::SystemAllocator, 0);
AZ_DISABLE_COPY(AtomToolsDocument); AZ_DISABLE_COPY_MOVE(AtomToolsDocument);
AtomToolsDocument(); AtomToolsDocument(const AZ::Crc32& toolId);
virtual ~AtomToolsDocument(); virtual ~AtomToolsDocument();
const AZ::Uuid& GetId() const; const AZ::Uuid& GetId() const;
@ -66,8 +66,10 @@ namespace AtomToolsFramework
//! This can be overridden to restore additional data. //! This can be overridden to restore additional data.
virtual bool ReopenRestoreState(); virtual bool ReopenRestoreState();
const AZ::Crc32 m_toolId = {};
//! The unique id of this document, used for all bus notifications and requests. //! The unique id of this document, used for all bus notifications and requests.
AZ::Uuid m_id = AZ::Uuid::CreateRandom(); const AZ::Uuid m_id = AZ::Uuid::CreateRandom();
//! The absolute path to the document source file. //! The absolute path to the document source file.
AZStd::string m_absolutePath; AZStd::string m_absolutePath;

@ -9,6 +9,7 @@
#pragma once #pragma once
#include <AtomToolsFramework/Application/AtomToolsApplication.h> #include <AtomToolsFramework/Application/AtomToolsApplication.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystem.h>
namespace AtomToolsFramework namespace AtomToolsFramework
{ {
@ -16,13 +17,20 @@ namespace AtomToolsFramework
: public AtomToolsApplication : public AtomToolsApplication
{ {
public: public:
AZ_TYPE_INFO(AtomToolsDocumentApplication, "{F4B43677-EB95-4CBB-8B8E-9EF4247E6F0D}"); AZ_TYPE_INFO(AtomToolsDocumentApplication, "{AC892170-D353-404A-A3D8-BB039C717295}");
AZ_DISABLE_COPY_MOVE(AtomToolsDocumentApplication);
using Base = AtomToolsApplication; using Base = AtomToolsApplication;
AtomToolsDocumentApplication(int* argc, char*** argv); AtomToolsDocumentApplication(const AZStd::string& targetName, int* argc, char*** argv);
protected:
// AtomToolsApplication overrides... // AtomToolsApplication overrides...
void Reflect(AZ::ReflectContext* context) override;
void StartCommon(AZ::Entity* systemEntity) override;
void Destroy() override;
void ProcessCommandLine(const AZ::CommandLine& commandLine) override; void ProcessCommandLine(const AZ::CommandLine& commandLine) override;
AZStd::unique_ptr<AtomToolsDocumentSystem> m_documentSystem;
}; };
} // namespace AtomToolsFramework } // namespace AtomToolsFramework

@ -28,7 +28,7 @@ namespace AtomToolsFramework
using Base = AtomToolsMainWindow; using Base = AtomToolsMainWindow;
AtomToolsDocumentMainWindow(QWidget* parent = 0); AtomToolsDocumentMainWindow(const AZ::Crc32& toolId, QWidget* parent = 0);
~AtomToolsDocumentMainWindow(); ~AtomToolsDocumentMainWindow();
protected: protected:

@ -18,8 +18,9 @@ namespace AtomToolsFramework
: public AZ::EBusTraits : public AZ::EBusTraits
{ {
public: public:
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple; static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
typedef AZ::Crc32 BusIdType;
//! Signal that a document was created //! Signal that a document was created
//! @param documentId unique id of document for which the notification is sent //! @param documentId unique id of document for which the notification is sent

@ -8,60 +8,34 @@
#pragma once #pragma once
#include <AzCore/Component/Component.h>
#include <AzCore/std/smart_ptr/shared_ptr.h>
#include <AzCore/Asset/AssetCommon.h>
#include <AtomToolsFramework/Document/AtomToolsDocument.h> #include <AtomToolsFramework/Document/AtomToolsDocument.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h> #include <AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h> #include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
#include <AzCore/Asset/AssetCommon.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include <AzCore/Memory/Memory.h>
#include <QFileInfo> #include <AzCore/RTTI/RTTI.h>
#include <QString> #include <AzCore/std/smart_ptr/shared_ptr.h>
AZ_POP_DISABLE_WARNING
namespace AtomToolsFramework namespace AtomToolsFramework
{ {
//! AtomToolsDocumentSystemComponent is the central component for managing documents //! AtomToolsDocumentSystem Is responsible for creation, management, and requests related to documents
class AtomToolsDocumentSystemComponent class AtomToolsDocumentSystem
: public AZ::Component : public AtomToolsDocumentNotificationBus::Handler
, private AtomToolsDocumentNotificationBus::Handler , public AtomToolsDocumentSystemRequestBus::Handler
, private AtomToolsDocumentSystemRequestBus::Handler
{ {
public: public:
AZ_COMPONENT(AtomToolsDocumentSystemComponent, "{343A3383-6A59-4343-851B-BF84FC6CB18E}"); AZ_CLASS_ALLOCATOR(AtomToolsFramework::AtomToolsDocumentSystem, AZ::SystemAllocator, 0);
AZ_RTTI(AtomToolsFramework::AtomToolsDocumentSystem, "{9D31F309-6B20-40C5-813C-F1226180E1F8}");
AtomToolsDocumentSystemComponent(); AZ_DISABLE_COPY_MOVE(AtomToolsDocumentSystem);
~AtomToolsDocumentSystemComponent() = default;
AtomToolsDocumentSystemComponent(const AtomToolsDocumentSystemComponent&) = delete;
AtomToolsDocumentSystemComponent& operator=(const AtomToolsDocumentSystemComponent&) = delete;
static void Reflect(AZ::ReflectContext* context); static void Reflect(AZ::ReflectContext* context);
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); AtomToolsDocumentSystem() = default;
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); AtomToolsDocumentSystem(const AZ::Crc32& toolId);
~AtomToolsDocumentSystem();
private:
////////////////////////////////////////////////////////////////////////
// AZ::Component interface implementation
void Init() override;
void Activate() override;
void Deactivate() override;
////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// AtomToolsDocumentNotificationBus::Handler overrides...
void OnDocumentDependencyModified(const AZ::Uuid& documentId) override;
void OnDocumentExternallyModified(const AZ::Uuid& documentId) override;
//////////////////////////////////////////////////////////////////////////
void QueueReopenDocuments();
void ReopenDocuments();
////////////////////////////////////////////////////////////////////////
// AtomToolsDocumentSystemRequestBus::Handler overrides... // AtomToolsDocumentSystemRequestBus::Handler overrides...
void RegisterDocumentType(AZStd::function<AtomToolsDocument*()> documentCreator) override; void RegisterDocumentType(const AtomToolsDocumentFactoryCallback& documentCreator) override;
AZ::Uuid CreateDocument() override; AZ::Uuid CreateDocument() override;
bool DestroyDocument(const AZ::Uuid& documentId) override; bool DestroyDocument(const AZ::Uuid& documentId) override;
AZ::Uuid OpenDocument(AZStd::string_view sourcePath) override; AZ::Uuid OpenDocument(AZStd::string_view sourcePath) override;
@ -74,11 +48,19 @@ namespace AtomToolsFramework
bool SaveDocumentAsChild(const AZ::Uuid& documentId, AZStd::string_view targetPath) override; bool SaveDocumentAsChild(const AZ::Uuid& documentId, AZStd::string_view targetPath) override;
bool SaveAllDocuments() override; bool SaveAllDocuments() override;
AZ::u32 GetDocumentCount() const override; AZ::u32 GetDocumentCount() const override;
////////////////////////////////////////////////////////////////////////
private:
// AtomToolsDocumentNotificationBus::Handler overrides...
void OnDocumentDependencyModified(const AZ::Uuid& documentId) override;
void OnDocumentExternallyModified(const AZ::Uuid& documentId) override;
void QueueReopenDocuments();
void ReopenDocuments();
AZ::Uuid OpenDocumentImpl(AZStd::string_view sourcePath, bool checkIfAlreadyOpen); AZ::Uuid OpenDocumentImpl(AZStd::string_view sourcePath, bool checkIfAlreadyOpen);
AZStd::function<AtomToolsDocument*()> m_documentCreator; const AZ::Crc32 m_toolId = {};
AtomToolsDocumentFactoryCallback m_documentCreator;
AZStd::unordered_map<AZ::Uuid, AZStd::shared_ptr<AtomToolsDocument>> m_documentMap; AZStd::unordered_map<AZ::Uuid, AZStd::shared_ptr<AtomToolsDocument>> m_documentMap;
AZStd::unordered_set<AZ::Uuid> m_documentIdsWithExternalChanges; AZStd::unordered_set<AZ::Uuid> m_documentIdsWithExternalChanges;
AZStd::unordered_set<AZ::Uuid> m_documentIdsWithDependencyChanges; AZStd::unordered_set<AZ::Uuid> m_documentIdsWithDependencyChanges;

@ -14,16 +14,19 @@ namespace AtomToolsFramework
{ {
class AtomToolsDocument; class AtomToolsDocument;
//! AtomToolsDocumentSystemRequestBus provides high level requests for menus, scripts, etc. using AtomToolsDocumentFactoryCallback = AZStd::function<AtomToolsDocument*(const AZ::Crc32&)>;
//! AtomToolsDocumentSystemRequestBus is an interface that provides requests for high level user interactions with a system of documents
class AtomToolsDocumentSystemRequests class AtomToolsDocumentSystemRequests
: public AZ::EBusTraits : public AZ::EBusTraits
{ {
public: public:
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
typedef AZ::Crc32 BusIdType;
//! Register a document factory function used to create specific document types //! Register a document factory function used to create specific document types
virtual void RegisterDocumentType(AZStd::function<AtomToolsDocument*()> documentCreator) = 0; virtual void RegisterDocumentType(const AtomToolsDocumentFactoryCallback& documentCreator) = 0;
//! Create a document //! Create a document
//! @return Uuid of new document, or null Uuid if failed //! @return Uuid of new document, or null Uuid if failed

@ -25,7 +25,7 @@ namespace AtomToolsFramework
, protected AtomToolsMainWindowRequestBus::Handler , protected AtomToolsMainWindowRequestBus::Handler
{ {
public: public:
AtomToolsMainWindow(QWidget* parent = 0); AtomToolsMainWindow(const AZ::Crc32& toolId, QWidget* parent = 0);
~AtomToolsMainWindow(); ~AtomToolsMainWindow();
protected: protected:
@ -48,6 +48,9 @@ namespace AtomToolsFramework
virtual void SetupMetrics(); virtual void SetupMetrics();
virtual void UpdateMetrics(); virtual void UpdateMetrics();
virtual void UpdateWindowTitle();
const AZ::Crc32 m_toolId = {};
AzQtComponents::FancyDocking* m_advancedDockManager = {}; AzQtComponents::FancyDocking* m_advancedDockManager = {};

@ -1,30 +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 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

@ -16,7 +16,8 @@ namespace AtomToolsFramework
{ {
public: public:
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple; static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
typedef AZ::Crc32 BusIdType;
virtual void OnMainWindowClosing(){}; virtual void OnMainWindowClosing(){};
}; };

@ -16,12 +16,14 @@ class QWidget;
namespace AtomToolsFramework namespace AtomToolsFramework
{ {
//! AtomToolsMainWindowRequestBus provides //! AtomToolsMainWindowRequestBus provides an interface to common main application window functions like adding docked windows,
//! resizing the viewport, and other operations
class AtomToolsMainWindowRequests : public AZ::EBusTraits class AtomToolsMainWindowRequests : public AZ::EBusTraits
{ {
public: public:
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
typedef AZ::Crc32 BusIdType;
//! Bring main window to foreground //! Bring main window to foreground
virtual void ActivateWindow() = 0; virtual void ActivateWindow() = 0;
@ -58,6 +60,7 @@ namespace AtomToolsFramework
//! Releases the viewport's render target resolution lock, allowing it to match the viewport widget again. //! Releases the viewport's render target resolution lock, allowing it to match the viewport widget again.
virtual void UnlockViewportRenderTargetSize() {}; virtual void UnlockViewportRenderTargetSize() {};
}; };
using AtomToolsMainWindowRequestBus = AZ::EBus<AtomToolsMainWindowRequests>; using AtomToolsMainWindowRequestBus = AZ::EBus<AtomToolsMainWindowRequests>;
} // namespace AtomToolsFramework } // namespace AtomToolsFramework

@ -9,7 +9,6 @@
#include <Atom/RPI.Public/RPISystemInterface.h> #include <Atom/RPI.Public/RPISystemInterface.h>
#include <AtomToolsFramework/Application/AtomToolsApplication.h> #include <AtomToolsFramework/Application/AtomToolsApplication.h>
#include <AtomToolsFramework/Util/Util.h> #include <AtomToolsFramework/Util/Util.h>
#include <AtomToolsFramework/Window/AtomToolsMainWindowFactoryRequestBus.h>
#include <AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h> #include <AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h>
#include <AzCore/Component/ComponentApplicationLifecycle.h> #include <AzCore/Component/ComponentApplicationLifecycle.h>
@ -46,26 +45,16 @@ AZ_POP_DISABLE_WARNING
namespace AtomToolsFramework namespace AtomToolsFramework
{ {
AZStd::string AtomToolsApplication::GetBuildTargetName() const AtomToolsApplication::AtomToolsApplication(const AZStd::string& targetName, int* argc, char*** argv)
{
return AZStd::string("AtomTools");
}
const char* AtomToolsApplication::GetCurrentConfigurationName() const
{
#if defined(_RELEASE)
return "ReleaseAtomTools";
#elif defined(_DEBUG)
return "DebugAtomTools";
#else
return "ProfileAtomTools";
#endif
}
AtomToolsApplication::AtomToolsApplication(int* argc, char*** argv)
: Application(argc, argv) : Application(argc, argv)
, AzQtApplication(*argc, *argv) , AzQtApplication(*argc, *argv)
, m_targetName(targetName)
, m_toolId(targetName)
{ {
// The settings registry has been created at this point, so add the CMake target
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddBuildSystemTargetSpecialization(
*AZ::SettingsRegistry::Get(), m_targetName);
// Suppress spam from the Source Control system // Suppress spam from the Source Control system
m_traceLogger.AddWindowFilter(AzToolsFramework::SCC_WINDOW); m_traceLogger.AddWindowFilter(AzToolsFramework::SCC_WINDOW);
@ -80,18 +69,26 @@ namespace AtomToolsFramework
m_styleManager.reset(new AzQtComponents::StyleManager(this)); m_styleManager.reset(new AzQtComponents::StyleManager(this));
m_styleManager->initialize(this, engineRootPath); m_styleManager->initialize(this, engineRootPath);
m_timer.setInterval(1); const AZ::u64 updateIntervalWhenActive =
GetSettingOrDefault<AZ::u64>("/O3DE/AtomToolsFramework/Application/UpdateIntervalWhenActive", 1);
const AZ::u64 updateIntervalWhenNotActive =
GetSettingOrDefault<AZ::u64>("/O3DE/AtomToolsFramework/Application/UpdateIntervalWhenNotActive", 64);
m_timer.setInterval(updateIntervalWhenActive);
connect(&m_timer, &QTimer::timeout, this, [this]() connect(&m_timer, &QTimer::timeout, this, [this]()
{ {
this->PumpSystemEventLoopUntilEmpty(); this->PumpSystemEventLoopUntilEmpty();
this->Tick(); this->Tick();
}); });
connect(this, &QGuiApplication::applicationStateChanged, this, [this]() connect(this, &QGuiApplication::applicationStateChanged, this, [this, updateIntervalWhenActive, updateIntervalWhenNotActive]()
{ {
// Limit the update interval when not in focus to reduce power consumption and interference with other applications // Limit the update interval when not in focus to reduce power consumption and interference with other applications
this->m_timer.setInterval((applicationState() & Qt::ApplicationActive) ? 1 : 32); this->m_timer.setInterval(
(applicationState() & Qt::ApplicationActive) ? updateIntervalWhenActive : updateIntervalWhenNotActive);
}); });
AtomToolsMainWindowNotificationBus::Handler::BusConnect(m_toolId);
} }
AtomToolsApplication ::~AtomToolsApplication() AtomToolsApplication ::~AtomToolsApplication()
@ -108,6 +105,17 @@ namespace AtomToolsFramework
GetSerializeContext()->CreateEditContext(); GetSerializeContext()->CreateEditContext();
} }
const char* AtomToolsApplication::GetCurrentConfigurationName() const
{
#if defined(_RELEASE)
return "ReleaseAtomTools";
#elif defined(_DEBUG)
return "DebugAtomTools";
#else
return "ProfileAtomTools";
#endif
}
void AtomToolsApplication::Reflect(AZ::ReflectContext* context) void AtomToolsApplication::Reflect(AZ::ReflectContext* context)
{ {
Base::Reflect(context); Base::Reflect(context);
@ -181,7 +189,7 @@ namespace AtomToolsFramework
Base::StartCommon(systemEntity); Base::StartCommon(systemEntity);
const bool clearLogFile = GetSettingOrDefault("/O3DE/AtomToolsFramework/Application/ClearLogOnStart", false); const bool clearLogFile = GetSettingOrDefault("/O3DE/AtomToolsFramework/Application/ClearLogOnStart", false);
m_traceLogger.OpenLogFile(GetBuildTargetName() + ".log", clearLogFile); m_traceLogger.OpenLogFile(m_targetName + ".log", clearLogFile);
ConnectToAssetProcessor(); ConnectToAssetProcessor();
@ -200,9 +208,6 @@ namespace AtomToolsFramework
LoadSettings(); LoadSettings();
AtomToolsMainWindowNotificationBus::Handler::BusConnect();
AtomToolsMainWindowFactoryRequestBus::Broadcast(&AtomToolsMainWindowFactoryRequestBus::Handler::CreateMainWindow);
auto editorPythonEventsInterface = AZ::Interface<AzToolsFramework::EditorPythonEventsInterface>::Get(); auto editorPythonEventsInterface = AZ::Interface<AzToolsFramework::EditorPythonEventsInterface>::Get();
if (editorPythonEventsInterface) if (editorPythonEventsInterface)
{ {
@ -218,16 +223,22 @@ namespace AtomToolsFramework
m_timer.start(); m_timer.start();
} }
void AtomToolsApplication::OnMainWindowClosing() void AtomToolsApplication::Tick()
{ {
ExitMainLoop(); TickSystem();
Base::Tick();
if (WasExitMainLoopRequested())
{
m_timer.disconnect();
quit();
}
} }
void AtomToolsApplication::Destroy() void AtomToolsApplication::Destroy()
{ {
// before modules are unloaded, destroy UI to free up any assets it cached
AtomToolsMainWindowFactoryRequestBus::Broadcast(&AtomToolsMainWindowFactoryRequestBus::Handler::DestroyMainWindow);
m_styleManager.reset(); m_styleManager.reset();
UnloadSettings();
AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusDisconnect(); AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusDisconnect();
AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusDisconnect(); AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusDisconnect();
@ -241,6 +252,11 @@ namespace AtomToolsFramework
#endif #endif
} }
void AtomToolsApplication::OnMainWindowClosing()
{
ExitMainLoop();
}
AZStd::vector<AZStd::string> AtomToolsApplication::GetCriticalAssetFilters() const AZStd::vector<AZStd::string> AtomToolsApplication::GetCriticalAssetFilters() const
{ {
return AZStd::vector<AZStd::string>({}); return AZStd::vector<AZStd::string>({});
@ -255,14 +271,12 @@ namespace AtomToolsFramework
// and able to negotiate a connection when running a debug build // and able to negotiate a connection when running a debug build
// and to negotiate a connection // and to negotiate a connection
const auto targetName = GetBuildTargetName();
AzFramework::AssetSystem::ConnectionSettings connectionSettings; AzFramework::AssetSystem::ConnectionSettings connectionSettings;
AzFramework::AssetSystem::ReadConnectionSettingsFromSettingsRegistry(connectionSettings); AzFramework::AssetSystem::ReadConnectionSettingsFromSettingsRegistry(connectionSettings);
connectionSettings.m_connectionDirection = connectionSettings.m_connectionDirection =
AzFramework::AssetSystem::ConnectionSettings::ConnectionDirection::ConnectToAssetProcessor; AzFramework::AssetSystem::ConnectionSettings::ConnectionDirection::ConnectToAssetProcessor;
connectionSettings.m_connectionIdentifier = targetName; connectionSettings.m_connectionIdentifier = m_targetName;
connectionSettings.m_loggingCallback = [targetName]([[maybe_unused]] AZStd::string_view logData) connectionSettings.m_loggingCallback = [targetName = m_targetName]([[maybe_unused]] AZStd::string_view logData)
{ {
AZ_UNUSED(targetName); // Prevent unused warning in release builds AZ_UNUSED(targetName); // Prevent unused warning in release builds
AZ_TracePrintf(targetName.c_str(), "%.*s", aznumeric_cast<int>(logData.size()), logData.data()); AZ_TracePrintf(targetName.c_str(), "%.*s", aznumeric_cast<int>(logData.size()), logData.data());
@ -279,7 +293,7 @@ namespace AtomToolsFramework
void AtomToolsApplication::CompileCriticalAssets() void AtomToolsApplication::CompileCriticalAssets()
{ {
AZ_TracePrintf(GetBuildTargetName().c_str(), "Compiling critical assets.\n"); AZ_TracePrintf(m_targetName.c_str(), "Compiling critical assets.\n");
QStringList failedAssets; QStringList failedAssets;
@ -288,7 +302,7 @@ namespace AtomToolsFramework
// So the asset id won't be found right after CompileAssetSync call. // So the asset id won't be found right after CompileAssetSync call.
for (const AZStd::string& assetFilters : GetCriticalAssetFilters()) for (const AZStd::string& assetFilters : GetCriticalAssetFilters())
{ {
AZ_TracePrintf(GetBuildTargetName().c_str(), "Compiling critical asset matching: %s.\n", assetFilters.c_str()); AZ_TracePrintf(m_targetName.c_str(), "Compiling critical asset matching: %s.\n", assetFilters.c_str());
// Wait for the asset be compiled // Wait for the asset be compiled
AzFramework::AssetSystem::AssetStatus status = AzFramework::AssetSystem::AssetStatus_Unknown; AzFramework::AssetSystem::AssetStatus status = AzFramework::AssetSystem::AssetStatus_Unknown;
@ -335,7 +349,7 @@ namespace AtomToolsFramework
AZ_Assert(context, "No serialize context"); AZ_Assert(context, "No serialize context");
char resolvedPath[AZ_MAX_PATH_LEN] = ""; char resolvedPath[AZ_MAX_PATH_LEN] = "";
AZStd::string fileName = "@user@/" + GetBuildTargetName() + "UserSettings.xml"; AZStd::string fileName = "@user@/" + m_targetName + "UserSettings.xml";
AZ::IO::FileIOBase::GetInstance()->ResolvePath( AZ::IO::FileIOBase::GetInstance()->ResolvePath(
fileName.c_str(), resolvedPath, AZ_ARRAY_SIZE(resolvedPath)); fileName.c_str(), resolvedPath, AZ_ARRAY_SIZE(resolvedPath));
@ -350,7 +364,7 @@ namespace AtomToolsFramework
AZ_Assert(context, "No serialize context"); AZ_Assert(context, "No serialize context");
char resolvedPath[AZ_MAX_PATH_LEN] = ""; char resolvedPath[AZ_MAX_PATH_LEN] = "";
AZStd::string fileName = "@user@/" + GetBuildTargetName() + "UserSettings.xml"; AZStd::string fileName = "@user@/" + m_targetName + "UserSettings.xml";
AZ::IO::FileIOBase::GetInstance()->ResolvePath(fileName.c_str(), resolvedPath, AZ_MAX_PATH_LEN); AZ::IO::FileIOBase::GetInstance()->ResolvePath(fileName.c_str(), resolvedPath, AZ_MAX_PATH_LEN);
@ -376,8 +390,7 @@ namespace AtomToolsFramework
const AZStd::string activateWindowSwitchName = "activatewindow"; const AZStd::string activateWindowSwitchName = "activatewindow";
if (commandLine.HasSwitch(activateWindowSwitchName)) if (commandLine.HasSwitch(activateWindowSwitchName))
{ {
AtomToolsFramework::AtomToolsMainWindowRequestBus::Broadcast( AtomToolsMainWindowRequestBus::Event(m_toolId, &AtomToolsMainWindowRequestBus::Handler::ActivateWindow);
&AtomToolsFramework::AtomToolsMainWindowRequestBus::Handler::ActivateWindow);
} }
const AZStd::string timeoputSwitchName = "timeout"; const AZStd::string timeoputSwitchName = "timeout";
@ -385,14 +398,11 @@ namespace AtomToolsFramework
{ {
const AZStd::string& timeoutValue = 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(GetBuildTargetName().c_str(), "Timeout scheduled, shutting down in %u ms", timeoutInMs); AZ_Printf(m_targetName.c_str(), "Timeout scheduled, shutting down in %u ms", timeoutInMs);
QTimer::singleShot( QTimer::singleShot(timeoutInMs, [this] {
timeoutInMs, AZ_Printf(m_targetName.c_str(), "Timeout reached, shutting down");
[this] ExitMainLoop();
{ });
AZ_Printf(GetBuildTargetName().c_str(), "Timeout reached, shutting down");
ExitMainLoop();
});
} }
// 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
@ -403,7 +413,7 @@ namespace AtomToolsFramework
const AZStd::string runPythonScriptPath = 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(GetBuildTargetName().c_str(), "Launching script: %s", runPythonScriptPath.c_str()); AZ_Printf(m_targetName.c_str(), "Launching script: %s", runPythonScriptPath.c_str());
AzToolsFramework::EditorPythonRunnerRequestBus::Broadcast( AzToolsFramework::EditorPythonRunnerRequestBus::Broadcast(
&AzToolsFramework::EditorPythonRunnerRequestBus::Events::ExecuteByFilenameWithArgs, runPythonScriptPath, runPythonArgs); &AzToolsFramework::EditorPythonRunnerRequestBus::Events::ExecuteByFilenameWithArgs, runPythonScriptPath, runPythonArgs);
} }
@ -486,27 +496,6 @@ namespace AtomToolsFramework
return false; return false;
} }
void AtomToolsApplication::Tick()
{
TickSystem();
Base::Tick();
if (WasExitMainLoopRequested())
{
m_timer.disconnect();
quit();
}
}
void AtomToolsApplication::Stop()
{
AtomToolsMainWindowFactoryRequestBus::Broadcast(&AtomToolsMainWindowFactoryRequestBus::Handler::DestroyMainWindow);
m_styleManager.reset();
UnloadSettings();
Base::Stop();
}
void AtomToolsApplication::QueryApplicationType(AZ::ApplicationTypeQuery& appType) const void AtomToolsApplication::QueryApplicationType(AZ::ApplicationTypeQuery& appType) const
{ {
appType.m_maskValue = AZ::ApplicationTypeQuery::Masks::Tool; appType.m_maskValue = AZ::ApplicationTypeQuery::Masks::Tool;
@ -524,7 +513,7 @@ namespace AtomToolsFramework
for (auto& line : lines) for (auto& line : lines)
{ {
AZ_TracePrintf(GetBuildTargetName().c_str(), "Python: %s\n", line.c_str()); AZ_TracePrintf(m_targetName.c_str(), "Python: %s\n", line.c_str());
} }
#endif #endif
} }
@ -537,7 +526,7 @@ namespace AtomToolsFramework
void AtomToolsApplication::OnExceptionMessage([[maybe_unused]] AZStd::string_view message) void AtomToolsApplication::OnExceptionMessage([[maybe_unused]] AZStd::string_view message)
{ {
AZ_Error(GetBuildTargetName().c_str(), false, "Python: " AZ_STRING_FORMAT, AZ_STRING_ARG(message)); AZ_Error(m_targetName.c_str(), false, "Python: " AZ_STRING_FORMAT, AZ_STRING_ARG(message));
} }
// Copied from PyIdleWaitFrames in CryEdit.cpp // Copied from PyIdleWaitFrames in CryEdit.cpp
@ -577,6 +566,8 @@ namespace AtomToolsFramework
void AtomToolsApplication::PyExit() void AtomToolsApplication::PyExit()
{ {
AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::ExitMainLoop); QTimer::singleShot(0, []() {
AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::ExitMainLoop);
});
} }
} // namespace AtomToolsFramework } // namespace AtomToolsFramework

@ -89,13 +89,14 @@ namespace AtomToolsFramework
void AtomToolsAssetBrowser::SelectEntries(const AZStd::string& absolutePath) void AtomToolsAssetBrowser::SelectEntries(const AZStd::string& absolutePath)
{ {
if (!absolutePath.empty()) AZ::TickBus::Handler::BusDisconnect();
m_pathToSelect = absolutePath;
if (!m_pathToSelect.empty() && AzFramework::StringFunc::Path::Normalize(m_pathToSelect))
{ {
// Selecting a new asset in the browser is not guaranteed to happen immediately. // Selecting a new asset in the browser is not guaranteed to happen immediately.
// The asset browser model notifications are sent before the model is updated. // The asset browser model notifications are sent before the model is updated.
// Instead of relying on the notifications, queue the selection and process it on tick until this change occurs. // Instead of relying on the notifications, queue the selection and process it on tick until this change occurs.
m_pathToSelect = absolutePath;
AzFramework::StringFunc::Path::Normalize(m_pathToSelect);
AZ::TickBus::Handler::BusConnect(); AZ::TickBus::Handler::BusConnect();
} }
} }
@ -201,25 +202,29 @@ namespace AtomToolsFramework
AZ_UNUSED(time); AZ_UNUSED(time);
AZ_UNUSED(deltaTime); AZ_UNUSED(deltaTime);
if (!m_pathToSelect.empty()) if (m_pathToSelect.empty())
{ {
// Attempt to select the new path AZ::TickBus::Handler::BusDisconnect();
AzToolsFramework::AssetBrowser::AssetBrowserViewRequestBus::Broadcast( m_pathToSelect.clear();
&AzToolsFramework::AssetBrowser::AssetBrowserViewRequestBus::Events::SelectFileAtPath, m_pathToSelect); return;
}
// Iterate over the selected entries to verify if the selection was made // Attempt to select the new path
for (const AssetBrowserEntry* entry : m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets()) AzToolsFramework::AssetBrowser::AssetBrowserViewRequestBus::Broadcast(
&AzToolsFramework::AssetBrowser::AssetBrowserViewRequestBus::Events::SelectFileAtPath, m_pathToSelect);
// Iterate over the selected entries to verify if the selection was made
for (const AssetBrowserEntry* entry : m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets())
{
if (entry)
{ {
if (entry) AZStd::string sourcePath = entry->GetFullPath();
AzFramework::StringFunc::Path::Normalize(sourcePath);
if (m_pathToSelect == sourcePath)
{ {
AZStd::string sourcePath = entry->GetFullPath(); // Once the selection is confirmed, cancel the operation and disconnect
AzFramework::StringFunc::Path::Normalize(sourcePath); AZ::TickBus::Handler::BusDisconnect();
if (m_pathToSelect == sourcePath) m_pathToSelect.clear();
{
// Once the selection is confirmed, cancel the operation and disconnect
AZ::TickBus::Handler::BusDisconnect();
m_pathToSelect.clear();
}
} }
} }
} }

@ -8,7 +8,6 @@
#include <AtomToolsFrameworkModule.h> #include <AtomToolsFrameworkModule.h>
#include <AtomToolsFrameworkSystemComponent.h> #include <AtomToolsFrameworkSystemComponent.h>
#include <Document/AtomToolsDocumentSystemComponent.h>
#include <Window/AtomToolsMainWindowSystemComponent.h> #include <Window/AtomToolsMainWindowSystemComponent.h>
#include <PerformanceMonitor/PerformanceMonitorSystemComponent.h> #include <PerformanceMonitor/PerformanceMonitorSystemComponent.h>
#include <PreviewRenderer/PreviewRendererSystemComponent.h> #include <PreviewRenderer/PreviewRendererSystemComponent.h>
@ -19,7 +18,6 @@ namespace AtomToolsFramework
{ {
m_descriptors.insert(m_descriptors.end(), { m_descriptors.insert(m_descriptors.end(), {
AtomToolsFrameworkSystemComponent::CreateDescriptor(), AtomToolsFrameworkSystemComponent::CreateDescriptor(),
AtomToolsDocumentSystemComponent::CreateDescriptor(),
AtomToolsMainWindowSystemComponent::CreateDescriptor(), AtomToolsMainWindowSystemComponent::CreateDescriptor(),
PerformanceMonitorSystemComponent::CreateDescriptor(), PerformanceMonitorSystemComponent::CreateDescriptor(),
PreviewRendererSystemComponent::CreateDescriptor(), PreviewRendererSystemComponent::CreateDescriptor(),
@ -30,7 +28,6 @@ namespace AtomToolsFramework
{ {
return AZ::ComponentTypeList{ return AZ::ComponentTypeList{
azrtti_typeid<AtomToolsFrameworkSystemComponent>(), azrtti_typeid<AtomToolsFrameworkSystemComponent>(),
azrtti_typeid<AtomToolsDocumentSystemComponent>(),
azrtti_typeid<AtomToolsMainWindowSystemComponent>(), azrtti_typeid<AtomToolsMainWindowSystemComponent>(),
azrtti_typeid<PerformanceMonitorSystemComponent>(), azrtti_typeid<PerformanceMonitorSystemComponent>(),
azrtti_typeid<PreviewRendererSystemComponent>(), azrtti_typeid<PreviewRendererSystemComponent>(),

@ -13,17 +13,18 @@
namespace AtomToolsFramework namespace AtomToolsFramework
{ {
AtomToolsDocument::AtomToolsDocument() AtomToolsDocument::AtomToolsDocument(const AZ::Crc32& toolId)
: m_toolId(toolId)
{ {
AtomToolsDocumentRequestBus::Handler::BusConnect(m_id); AtomToolsDocumentRequestBus::Handler::BusConnect(m_id);
AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsDocumentNotificationBus::Events::OnDocumentCreated, m_id); AtomToolsDocumentNotificationBus::Event(m_toolId, &AtomToolsDocumentNotificationBus::Events::OnDocumentCreated, m_id);
} }
AtomToolsDocument::~AtomToolsDocument() AtomToolsDocument::~AtomToolsDocument()
{ {
AzToolsFramework::AssetSystemBus::Handler::BusDisconnect(); AtomToolsDocumentNotificationBus::Event(m_toolId, &AtomToolsDocumentNotificationBus::Events::OnDocumentDestroyed, m_id);
AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsDocumentNotificationBus::Events::OnDocumentDestroyed, m_id);
AtomToolsDocumentRequestBus::Handler::BusDisconnect(); AtomToolsDocumentRequestBus::Handler::BusDisconnect();
AzToolsFramework::AssetSystemBus::Handler::BusDisconnect();
} }
const AZ::Uuid& AtomToolsDocument::GetId() const const AZ::Uuid& AtomToolsDocument::GetId() const
@ -80,10 +81,10 @@ namespace AtomToolsFramework
return false; return false;
} }
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( AtomToolsFramework::AtomToolsDocumentNotificationBus::Event(
&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentModified, m_id); m_toolId, &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentModified, m_id);
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( AtomToolsFramework::AtomToolsDocumentNotificationBus::Event(
&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id); m_toolId, &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id);
return true; return true;
} }
@ -169,8 +170,8 @@ namespace AtomToolsFramework
AZ_TracePrintf("AtomToolsDocument", "Document closed: '%s'.\n", m_absolutePath.c_str()); AZ_TracePrintf("AtomToolsDocument", "Document closed: '%s'.\n", m_absolutePath.c_str());
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( AtomToolsFramework::AtomToolsDocumentNotificationBus::Event(
&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentClosed, m_id); m_toolId, &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentClosed, m_id);
// Clearing after notification so paths are still available // Clearing after notification so paths are still available
Clear(); Clear();
@ -211,8 +212,8 @@ namespace AtomToolsFramework
// The history index is one beyond the last executed command. Decrement the index then execute undo. // The history index is one beyond the last executed command. Decrement the index then execute undo.
m_undoHistory[--m_undoHistoryIndex].first(); m_undoHistory[--m_undoHistoryIndex].first();
AZ_TracePrintf("AtomToolsDocument", "Document undo: '%s'.\n", m_absolutePath.c_str()); AZ_TracePrintf("AtomToolsDocument", "Document undo: '%s'.\n", m_absolutePath.c_str());
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( AtomToolsFramework::AtomToolsDocumentNotificationBus::Event(
&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id); m_toolId, &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id);
return true; return true;
} }
return false; return false;
@ -225,8 +226,8 @@ namespace AtomToolsFramework
// Execute the current redo command then move the history index to the next position. // Execute the current redo command then move the history index to the next position.
m_undoHistory[m_undoHistoryIndex++].second(); m_undoHistory[m_undoHistoryIndex++].second();
AZ_TracePrintf("AtomToolsDocument", "Document redo: '%s'.\n", m_absolutePath.c_str()); AZ_TracePrintf("AtomToolsDocument", "Document redo: '%s'.\n", m_absolutePath.c_str());
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( AtomToolsFramework::AtomToolsDocumentNotificationBus::Event(
&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id); m_toolId, &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id);
return true; return true;
} }
return false; return false;
@ -259,8 +260,8 @@ namespace AtomToolsFramework
{ {
AZ_TracePrintf("AtomToolsDocument", "Document opened: '%s'.\n", m_absolutePath.c_str()); AZ_TracePrintf("AtomToolsDocument", "Document opened: '%s'.\n", m_absolutePath.c_str());
AzToolsFramework::AssetSystemBus::Handler::BusConnect(); AzToolsFramework::AssetSystemBus::Handler::BusConnect();
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( AtomToolsFramework::AtomToolsDocumentNotificationBus::Event(
&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, m_id); m_toolId, &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, m_id);
return true; return true;
} }
@ -282,8 +283,8 @@ namespace AtomToolsFramework
&AzToolsFramework::SourceControlCommandBus::Events::RequestEdit, m_savePathNormalized.c_str(), true, &AzToolsFramework::SourceControlCommandBus::Events::RequestEdit, m_savePathNormalized.c_str(), true,
[](bool, const AzToolsFramework::SourceControlFileInfo&) {}); [](bool, const AzToolsFramework::SourceControlFileInfo&) {});
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( AtomToolsFramework::AtomToolsDocumentNotificationBus::Event(
&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentSaved, m_id); m_toolId, &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentSaved, m_id);
return true; return true;
} }
@ -319,8 +320,8 @@ namespace AtomToolsFramework
// Assign the index to the end of history // Assign the index to the end of history
m_undoHistoryIndex = aznumeric_cast<int>(m_undoHistory.size()); m_undoHistoryIndex = aznumeric_cast<int>(m_undoHistory.size());
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( AtomToolsFramework::AtomToolsDocumentNotificationBus::Event(
&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id); m_toolId, &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id);
} }
void AtomToolsDocument::SourceFileChanged(AZStd::string relativePath, AZStd::string scanFolder, [[maybe_unused]] AZ::Uuid sourceUUID) void AtomToolsDocument::SourceFileChanged(AZStd::string relativePath, AZStd::string scanFolder, [[maybe_unused]] AZ::Uuid sourceUUID)
@ -333,16 +334,16 @@ namespace AtomToolsFramework
if (!m_ignoreSourceFileChangeToSelf) if (!m_ignoreSourceFileChangeToSelf)
{ {
AZ_TracePrintf("AtomToolsDocument", "Document changed externally: '%s'.\n", m_absolutePath.c_str()); AZ_TracePrintf("AtomToolsDocument", "Document changed externally: '%s'.\n", m_absolutePath.c_str());
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( AtomToolsFramework::AtomToolsDocumentNotificationBus::Event(
&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentExternallyModified, m_id); m_toolId, &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentExternallyModified, m_id);
} }
m_ignoreSourceFileChangeToSelf = false; m_ignoreSourceFileChangeToSelf = false;
} }
else if (m_sourceDependencies.find(sourcePath) != m_sourceDependencies.end()) else if (m_sourceDependencies.find(sourcePath) != m_sourceDependencies.end())
{ {
AZ_TracePrintf("AtomToolsDocument", "Document dependency changed: '%s'.\n", m_absolutePath.c_str()); AZ_TracePrintf("AtomToolsDocument", "Document dependency changed: '%s'.\n", m_absolutePath.c_str());
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( AtomToolsFramework::AtomToolsDocumentNotificationBus::Event(
&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentDependencyModified, m_id); m_toolId, &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentDependencyModified, m_id);
} }
} }

@ -11,11 +11,29 @@
namespace AtomToolsFramework namespace AtomToolsFramework
{ {
AtomToolsDocumentApplication::AtomToolsDocumentApplication(int* argc, char*** argv) AtomToolsDocumentApplication::AtomToolsDocumentApplication(const AZStd::string& targetName, int* argc, char*** argv)
: Base(argc, argv) : Base(targetName, argc, argv)
{ {
} }
void AtomToolsDocumentApplication::Reflect(AZ::ReflectContext* context)
{
Base::Reflect(context);
AtomToolsDocumentSystem::Reflect(context);
}
void AtomToolsDocumentApplication::StartCommon(AZ::Entity* systemEntity)
{
Base::StartCommon(systemEntity);
m_documentSystem.reset(aznew AtomToolsDocumentSystem(m_toolId));
}
void AtomToolsDocumentApplication::Destroy()
{
m_documentSystem.reset();
Base::Destroy();
}
void AtomToolsDocumentApplication::ProcessCommandLine(const AZ::CommandLine& commandLine) void AtomToolsDocumentApplication::ProcessCommandLine(const AZ::CommandLine& commandLine)
{ {
// Process command line options for opening documents on startup // Process command line options for opening documents on startup
@ -24,8 +42,8 @@ namespace AtomToolsFramework
{ {
const AZStd::string openDocumentPath = commandLine.GetMiscValue(openDocumentIndex); const AZStd::string openDocumentPath = commandLine.GetMiscValue(openDocumentIndex);
AZ_Printf(GetBuildTargetName().c_str(), "Opening document: %s", openDocumentPath.c_str()); AZ_Printf(m_targetName.c_str(), "Opening document: %s", openDocumentPath.c_str());
AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath); AtomToolsDocumentSystemRequestBus::Event(m_toolId, &AtomToolsDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath);
} }
Base::ProcessCommandLine(commandLine); Base::ProcessCommandLine(commandLine);

@ -25,13 +25,13 @@ AZ_POP_DISABLE_WARNING
namespace AtomToolsFramework namespace AtomToolsFramework
{ {
AtomToolsDocumentMainWindow::AtomToolsDocumentMainWindow(QWidget* parent /* = 0 */) AtomToolsDocumentMainWindow::AtomToolsDocumentMainWindow(const AZ::Crc32& toolId, QWidget* parent /* = 0 */)
: AtomToolsMainWindow(parent) : AtomToolsMainWindow(toolId, parent)
{ {
setObjectName("AtomToolsDocumentMainWindow"); setObjectName("AtomToolsDocumentMainWindow");
AddDocumentMenus(); AddDocumentMenus();
AddDocumentTabBar(); AddDocumentTabBar();
AtomToolsDocumentNotificationBus::Handler::BusConnect(); AtomToolsDocumentNotificationBus::Handler::BusConnect(m_toolId);
} }
AtomToolsDocumentMainWindow::~AtomToolsDocumentMainWindow() AtomToolsDocumentMainWindow::~AtomToolsDocumentMainWindow()
@ -49,8 +49,8 @@ namespace AtomToolsFramework
AZStd::string savePath; AZStd::string savePath;
if (GetCreateDocumentParams(openPath, savePath)) if (GetCreateDocumentParams(openPath, savePath))
{ {
AtomToolsDocumentSystemRequestBus::Broadcast( AtomToolsDocumentSystemRequestBus::Event(
&AtomToolsDocumentSystemRequestBus::Events::CreateDocumentFromFile, openPath, savePath); m_toolId, &AtomToolsDocumentSystemRequestBus::Events::CreateDocumentFromFile, openPath, savePath);
} }
}, QKeySequence::New); }, QKeySequence::New);
m_menuFile->insertAction(insertPostion, m_actionNew); m_menuFile->insertAction(insertPostion, m_actionNew);
@ -59,7 +59,7 @@ namespace AtomToolsFramework
AZStd::string openPath; AZStd::string openPath;
if (GetOpenDocumentParams(openPath)) if (GetOpenDocumentParams(openPath))
{ {
AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::OpenDocument, openPath); AtomToolsDocumentSystemRequestBus::Event(m_toolId, &AtomToolsDocumentSystemRequestBus::Events::OpenDocument, openPath);
} }
}, QKeySequence::Open); }, QKeySequence::Open);
m_menuFile->insertAction(insertPostion, m_actionOpen); m_menuFile->insertAction(insertPostion, m_actionOpen);
@ -68,7 +68,8 @@ namespace AtomToolsFramework
m_actionSave = CreateAction("&Save", [this]() { m_actionSave = CreateAction("&Save", [this]() {
const AZ::Uuid documentId = GetDocumentTabId(m_tabWidget->currentIndex()); const AZ::Uuid documentId = GetDocumentTabId(m_tabWidget->currentIndex());
bool result = false; bool result = false;
AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsDocumentSystemRequestBus::Events::SaveDocument, documentId); AtomToolsDocumentSystemRequestBus::EventResult(
result, m_toolId, &AtomToolsDocumentSystemRequestBus::Events::SaveDocument, documentId);
if (!result) if (!result)
{ {
SetStatusError(tr("Document save failed: %1").arg(GetDocumentPath(documentId))); SetStatusError(tr("Document save failed: %1").arg(GetDocumentPath(documentId)));
@ -81,8 +82,9 @@ namespace AtomToolsFramework
const QString documentPath = GetDocumentPath(documentId); const QString documentPath = GetDocumentPath(documentId);
bool result = false; bool result = false;
AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsDocumentSystemRequestBus::Events::SaveDocumentAsCopy, AtomToolsDocumentSystemRequestBus::EventResult(
documentId, GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData()); result, m_toolId, &AtomToolsDocumentSystemRequestBus::Events::SaveDocumentAsCopy, documentId,
GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData());
if (!result) if (!result)
{ {
SetStatusError(tr("Document save failed: %1").arg(GetDocumentPath(documentId))); SetStatusError(tr("Document save failed: %1").arg(GetDocumentPath(documentId)));
@ -95,8 +97,9 @@ namespace AtomToolsFramework
const QString documentPath = GetDocumentPath(documentId); const QString documentPath = GetDocumentPath(documentId);
bool result = false; bool result = false;
AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsDocumentSystemRequestBus::Events::SaveDocumentAsChild, AtomToolsDocumentSystemRequestBus::EventResult(
documentId, GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData()); result, m_toolId, &AtomToolsDocumentSystemRequestBus::Events::SaveDocumentAsChild, documentId,
GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData());
if (!result) if (!result)
{ {
SetStatusError(tr("Document save failed: %1").arg(GetDocumentPath(documentId))); SetStatusError(tr("Document save failed: %1").arg(GetDocumentPath(documentId)));
@ -106,7 +109,8 @@ namespace AtomToolsFramework
m_actionSaveAll = CreateAction("Save A&ll", [this]() { m_actionSaveAll = CreateAction("Save A&ll", [this]() {
bool result = false; bool result = false;
AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsDocumentSystemRequestBus::Events::SaveAllDocuments); AtomToolsDocumentSystemRequestBus::EventResult(
result, m_toolId, &AtomToolsDocumentSystemRequestBus::Events::SaveAllDocuments);
if (!result) if (!result)
{ {
SetStatusError(tr("Document save all failed")); SetStatusError(tr("Document save all failed"));
@ -117,18 +121,19 @@ namespace AtomToolsFramework
m_actionClose = CreateAction("&Close", [this]() { m_actionClose = CreateAction("&Close", [this]() {
const AZ::Uuid documentId = GetDocumentTabId(m_tabWidget->currentIndex()); const AZ::Uuid documentId = GetDocumentTabId(m_tabWidget->currentIndex());
AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId); AtomToolsDocumentSystemRequestBus::Event(m_toolId, &AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId);
}, QKeySequence::Close); }, QKeySequence::Close);
m_menuFile->insertAction(insertPostion, m_actionClose); m_menuFile->insertAction(insertPostion, m_actionClose);
m_actionCloseAll = CreateAction("Close All", []() { m_actionCloseAll = CreateAction("Close All", [this]() {
AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::CloseAllDocuments); AtomToolsDocumentSystemRequestBus::Event(m_toolId, &AtomToolsDocumentSystemRequestBus::Events::CloseAllDocuments);
}); });
m_menuFile->insertAction(insertPostion, m_actionCloseAll); m_menuFile->insertAction(insertPostion, m_actionCloseAll);
m_actionCloseOthers = CreateAction("Close Others", [this]() { m_actionCloseOthers = CreateAction("Close Others", [this]() {
const AZ::Uuid documentId = GetDocumentTabId(m_tabWidget->currentIndex()); const AZ::Uuid documentId = GetDocumentTabId(m_tabWidget->currentIndex());
AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId); AtomToolsDocumentSystemRequestBus::Event(
m_toolId, &AtomToolsDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId);
}); });
m_menuFile->insertAction(insertPostion, m_actionCloseOthers); m_menuFile->insertAction(insertPostion, m_actionCloseOthers);
m_menuFile->insertSeparator(insertPostion); m_menuFile->insertSeparator(insertPostion);
@ -194,12 +199,12 @@ namespace AtomToolsFramework
// This should automatically clear the active document // This should automatically clear the active document
connect(m_tabWidget, &QTabWidget::currentChanged, this, [this](int tabIndex) { connect(m_tabWidget, &QTabWidget::currentChanged, this, [this](int tabIndex) {
const AZ::Uuid documentId = GetDocumentTabId(tabIndex); const AZ::Uuid documentId = GetDocumentTabId(tabIndex);
AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, documentId); AtomToolsDocumentNotificationBus::Event(m_toolId,&AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, documentId);
}); });
connect(m_tabWidget, &QTabWidget::tabCloseRequested, this, [this](int tabIndex) { connect(m_tabWidget, &QTabWidget::tabCloseRequested, this, [this](int tabIndex) {
const AZ::Uuid documentId = GetDocumentTabId(tabIndex); const AZ::Uuid documentId = GetDocumentTabId(tabIndex);
AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId); AtomToolsDocumentSystemRequestBus::Event(m_toolId, &AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId);
}); });
// Add context menu for right-clicking on tabs // Add context menu for right-clicking on tabs
@ -341,15 +346,18 @@ namespace AtomToolsFramework
const QString selectActionName = (currentTabIndex == clickedTabIndex) ? "Select in Browser" : "Select"; const QString selectActionName = (currentTabIndex == clickedTabIndex) ? "Select in Browser" : "Select";
tabMenu.addAction(selectActionName, [this, clickedTabIndex]() { tabMenu.addAction(selectActionName, [this, clickedTabIndex]() {
const AZ::Uuid documentId = GetDocumentTabId(clickedTabIndex); const AZ::Uuid documentId = GetDocumentTabId(clickedTabIndex);
AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, documentId); AtomToolsDocumentNotificationBus::Event(
m_toolId, &AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, documentId);
}); });
tabMenu.addAction("Close", [this, clickedTabIndex]() { tabMenu.addAction("Close", [this, clickedTabIndex]() {
const AZ::Uuid documentId = GetDocumentTabId(clickedTabIndex); const AZ::Uuid documentId = GetDocumentTabId(clickedTabIndex);
AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId); AtomToolsDocumentSystemRequestBus::Event(
m_toolId, &AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId);
}); });
auto closeOthersAction = tabMenu.addAction("Close Others", [this, clickedTabIndex]() { auto closeOthersAction = tabMenu.addAction("Close Others", [this, clickedTabIndex]() {
const AZ::Uuid documentId = GetDocumentTabId(clickedTabIndex); const AZ::Uuid documentId = GetDocumentTabId(clickedTabIndex);
AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId); AtomToolsDocumentSystemRequestBus::Event(
m_toolId, &AtomToolsDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId);
}); });
closeOthersAction->setEnabled(tabBar->count() > 1); closeOthersAction->setEnabled(tabBar->count() > 1);
tabMenu.exec(QCursor::pos()); tabMenu.exec(QCursor::pos());
@ -472,14 +480,14 @@ namespace AtomToolsFramework
void AtomToolsDocumentMainWindow::closeEvent(QCloseEvent* closeEvent) void AtomToolsDocumentMainWindow::closeEvent(QCloseEvent* closeEvent)
{ {
bool didClose = true; bool didClose = true;
AtomToolsDocumentSystemRequestBus::BroadcastResult(didClose, &AtomToolsDocumentSystemRequestBus::Events::CloseAllDocuments); AtomToolsDocumentSystemRequestBus::EventResult(didClose, m_toolId, &AtomToolsDocumentSystemRequestBus::Events::CloseAllDocuments);
if (!didClose) if (!didClose)
{ {
closeEvent->ignore(); closeEvent->ignore();
return; return;
} }
AtomToolsMainWindowNotificationBus::Broadcast(&AtomToolsMainWindowNotifications::OnMainWindowClosing); AtomToolsMainWindowNotificationBus::Event(m_toolId, &AtomToolsMainWindowNotifications::OnMainWindowClosing);
} }
template<typename Functor> template<typename Functor>

@ -9,6 +9,7 @@
#include <AtomToolsFramework/Debug/TraceRecorder.h> #include <AtomToolsFramework/Debug/TraceRecorder.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h> #include <AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h> #include <AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystem.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h> #include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
#include <AtomToolsFramework/Util/Util.h> #include <AtomToolsFramework/Util/Util.h>
#include <AzCore/RTTI/BehaviorContext.h> #include <AzCore/RTTI/BehaviorContext.h>
@ -17,7 +18,6 @@
#include <AzFramework/Asset/AssetSystemBus.h> #include <AzFramework/Asset/AssetSystemBus.h>
#include <AzFramework/StringFunc/StringFunc.h> #include <AzFramework/StringFunc/StringFunc.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h> #include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <Document/AtomToolsDocumentSystemComponent.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QApplication> #include <QApplication>
@ -28,20 +28,16 @@ AZ_POP_DISABLE_WARNING
namespace AtomToolsFramework namespace AtomToolsFramework
{ {
AtomToolsDocumentSystemComponent::AtomToolsDocumentSystemComponent() void AtomToolsDocumentSystem::Reflect(AZ::ReflectContext* context)
{ {
} if (auto serialize = azrtti_cast<AZ::SerializeContext*>(context))
void AtomToolsDocumentSystemComponent::Reflect(AZ::ReflectContext* context)
{
if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
{ {
serialize->Class<AtomToolsDocumentSystemComponent, AZ::Component>() serialize->Class<AtomToolsDocumentSystem>()
->Version(0); ->Version(0);
if (AZ::EditContext* ec = serialize->GetEditContext()) if (auto editContext = serialize->GetEditContext())
{ {
ec->Class<AtomToolsDocumentSystemComponent>("AtomToolsDocumentSystemComponent", "") editContext->Class<AtomToolsDocumentSystem>("AtomToolsDocumentSystem", "")
->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("System")) ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("System"))
->Attribute(AZ::Edit::Attributes::AutoExpand, true) ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
@ -49,7 +45,7 @@ namespace AtomToolsFramework
} }
} }
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context)) if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{ {
behaviorContext->EBus<AtomToolsDocumentSystemRequestBus>("AtomToolsDocumentSystemRequestBus") behaviorContext->EBus<AtomToolsDocumentSystemRequestBus>("AtomToolsDocumentSystemRequestBus")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
@ -93,40 +89,26 @@ namespace AtomToolsFramework
} }
} }
void AtomToolsDocumentSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) AtomToolsDocumentSystem::AtomToolsDocumentSystem(const AZ::Crc32& toolId)
{ : m_toolId(toolId)
provided.push_back(AZ_CRC_CE("AtomToolsDocumentSystemService"));
}
void AtomToolsDocumentSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
{ {
incompatible.push_back(AZ_CRC_CE("AtomToolsDocumentSystemService")); AtomToolsDocumentSystemRequestBus::Handler::BusConnect(m_toolId);
AtomToolsDocumentNotificationBus::Handler::BusConnect(m_toolId);
} }
void AtomToolsDocumentSystemComponent::Init() AtomToolsDocumentSystem::~AtomToolsDocumentSystem()
{
}
void AtomToolsDocumentSystemComponent::Activate()
{ {
m_documentMap.clear(); m_documentMap.clear();
AtomToolsDocumentSystemRequestBus::Handler::BusConnect();
AtomToolsDocumentNotificationBus::Handler::BusConnect();
}
void AtomToolsDocumentSystemComponent::Deactivate()
{
AtomToolsDocumentNotificationBus::Handler::BusDisconnect(); AtomToolsDocumentNotificationBus::Handler::BusDisconnect();
AtomToolsDocumentSystemRequestBus::Handler::BusDisconnect(); AtomToolsDocumentSystemRequestBus::Handler::BusDisconnect();
m_documentMap.clear();
} }
void AtomToolsDocumentSystemComponent::RegisterDocumentType(AZStd::function<AtomToolsDocument*()> documentCreator) void AtomToolsDocumentSystem::RegisterDocumentType(const AtomToolsDocumentFactoryCallback& documentCreator)
{ {
m_documentCreator = documentCreator; m_documentCreator = documentCreator;
} }
AZ::Uuid AtomToolsDocumentSystemComponent::CreateDocument() AZ::Uuid AtomToolsDocumentSystem::CreateDocument()
{ {
if (!m_documentCreator) if (!m_documentCreator)
{ {
@ -134,7 +116,7 @@ namespace AtomToolsFramework
return AZ::Uuid::CreateNull(); return AZ::Uuid::CreateNull();
} }
AZStd::unique_ptr<AtomToolsDocument> document(m_documentCreator()); AZStd::unique_ptr<AtomToolsDocument> document(m_documentCreator(m_toolId));
if (!document) if (!document)
{ {
AZ_Error("AtomToolsDocument", false, "Failed to create new document"); AZ_Error("AtomToolsDocument", false, "Failed to create new document");
@ -146,112 +128,17 @@ namespace AtomToolsFramework
return documentId; return documentId;
} }
bool AtomToolsDocumentSystemComponent::DestroyDocument(const AZ::Uuid& documentId) bool AtomToolsDocumentSystem::DestroyDocument(const AZ::Uuid& documentId)
{ {
return m_documentMap.erase(documentId) != 0; return m_documentMap.erase(documentId) != 0;
} }
void AtomToolsDocumentSystemComponent::OnDocumentExternallyModified(const AZ::Uuid& documentId) AZ::Uuid AtomToolsDocumentSystem::OpenDocument(AZStd::string_view sourcePath)
{
m_documentIdsWithExternalChanges.insert(documentId);
QueueReopenDocuments();
}
void AtomToolsDocumentSystemComponent::OnDocumentDependencyModified(const AZ::Uuid& documentId)
{
m_documentIdsWithDependencyChanges.insert(documentId);
QueueReopenDocuments();
}
void AtomToolsDocumentSystemComponent::QueueReopenDocuments()
{
if (!m_queueReopenDocuments)
{
m_queueReopenDocuments = true;
QTimer::singleShot(0, [this] { ReopenDocuments(); });
}
}
void AtomToolsDocumentSystemComponent::ReopenDocuments()
{
const bool enableHotReload = GetSettingOrDefault<bool>("/O3DE/AtomToolsFramework/DocumentSystem/EnableHotReload", true);
if (!enableHotReload)
{
m_documentIdsWithDependencyChanges.clear();
m_documentIdsWithExternalChanges.clear();
m_queueReopenDocuments = false;
}
const bool enableHotReloadPrompts =
GetSettingOrDefault<bool>("/O3DE/AtomToolsFramework/DocumentSystem/EnableHotReloadPrompts", true);
for (const AZ::Uuid& documentId : m_documentIdsWithExternalChanges)
{
m_documentIdsWithDependencyChanges.erase(documentId);
AZStd::string documentPath;
AtomToolsDocumentRequestBus::EventResult(documentPath, documentId, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
if (enableHotReloadPrompts &&
(QMessageBox::question(QApplication::activeWindow(),
QString("Document was externally modified"),
QString("Would you like to reopen the document:\n%1?").arg(documentPath.c_str()),
QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes))
{
continue;
}
AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount);
bool openResult = false;
AtomToolsDocumentRequestBus::EventResult(openResult, documentId, &AtomToolsDocumentRequestBus::Events::Open, documentPath);
if (!openResult)
{
QMessageBox::critical(
QApplication::activeWindow(), QString("Document could not be opened"),
QString("Failed to open: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str()));
AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId);
}
}
for (const AZ::Uuid& documentId : m_documentIdsWithDependencyChanges)
{
AZStd::string documentPath;
AtomToolsDocumentRequestBus::EventResult(documentPath, documentId, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
if (enableHotReloadPrompts &&
(QMessageBox::question(QApplication::activeWindow(),
QString("Document dependencies have changed"),
QString("Would you like to update the document with these changes:\n%1?").arg(documentPath.c_str()),
QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes))
{
continue;
}
AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount);
bool openResult = false;
AtomToolsDocumentRequestBus::EventResult(openResult, documentId, &AtomToolsDocumentRequestBus::Events::Reopen);
if (!openResult)
{
QMessageBox::critical(
QApplication::activeWindow(), QString("Document could not be opened"),
QString("Failed to open: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str()));
AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId);
}
}
m_documentIdsWithDependencyChanges.clear();
m_documentIdsWithExternalChanges.clear();
m_queueReopenDocuments = false;
}
AZ::Uuid AtomToolsDocumentSystemComponent::OpenDocument(AZStd::string_view sourcePath)
{ {
return OpenDocumentImpl(sourcePath, true); return OpenDocumentImpl(sourcePath, true);
} }
AZ::Uuid AtomToolsDocumentSystemComponent::CreateDocumentFromFile(AZStd::string_view sourcePath, AZStd::string_view targetPath) AZ::Uuid AtomToolsDocumentSystem::CreateDocumentFromFile(AZStd::string_view sourcePath, AZStd::string_view targetPath)
{ {
const AZ::Uuid documentId = OpenDocumentImpl(sourcePath, false); const AZ::Uuid documentId = OpenDocumentImpl(sourcePath, false);
if (documentId.IsNull()) if (documentId.IsNull())
@ -266,18 +153,18 @@ namespace AtomToolsFramework
} }
// Send document open notification after creating new one // Send document open notification after creating new one
AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, documentId); AtomToolsDocumentNotificationBus::Event(m_toolId, &AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, documentId);
return documentId; return documentId;
} }
bool AtomToolsDocumentSystemComponent::CloseDocument(const AZ::Uuid& documentId) bool AtomToolsDocumentSystem::CloseDocument(const AZ::Uuid& documentId)
{ {
bool isOpen = false; bool isOpen = false;
AtomToolsDocumentRequestBus::EventResult(isOpen, documentId, &AtomToolsDocumentRequestBus::Events::IsOpen); AtomToolsDocumentRequestBus::EventResult(isOpen, documentId, &AtomToolsDocumentRequestBus::Events::IsOpen);
if (!isOpen) if (!isOpen)
{ {
// immediately destroy unopened documents // immediately destroy unopened documents
AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::DestroyDocument, documentId); DestroyDocument(documentId);
return true; return true;
} }
@ -289,8 +176,8 @@ namespace AtomToolsFramework
if (isModified) if (isModified)
{ {
auto selection = QMessageBox::question(QApplication::activeWindow(), auto selection = QMessageBox::question(QApplication::activeWindow(),
QString("Document has unsaved changes"), QObject::tr("Document has unsaved changes"),
QString("Do you want to save changes to\n%1?").arg(documentPath.c_str()), QObject::tr("Do you want to save changes to\n%1?").arg(documentPath.c_str()),
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
if (selection == QMessageBox::Cancel) if (selection == QMessageBox::Cancel)
{ {
@ -307,23 +194,24 @@ namespace AtomToolsFramework
} }
} }
AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); TraceRecorder traceRecorder(m_maxMessageBoxLineCount);
bool closeResult = true; bool closeResult = true;
AtomToolsDocumentRequestBus::EventResult(closeResult, documentId, &AtomToolsDocumentRequestBus::Events::Close); AtomToolsDocumentRequestBus::EventResult(closeResult, documentId, &AtomToolsDocumentRequestBus::Events::Close);
if (!closeResult) if (!closeResult)
{ {
QMessageBox::critical( QMessageBox::critical(
QApplication::activeWindow(), QString("Document could not be closed"), QApplication::activeWindow(),
QString("Failed to close: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str())); QObject::tr("Document could not be closed"),
QObject::tr("Failed to close: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str()));
return false; return false;
} }
AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::DestroyDocument, documentId); DestroyDocument(documentId);
return true; return true;
} }
bool AtomToolsDocumentSystemComponent::CloseAllDocuments() bool AtomToolsDocumentSystem::CloseAllDocuments()
{ {
bool result = true; bool result = true;
auto documentMap = m_documentMap; auto documentMap = m_documentMap;
@ -338,7 +226,7 @@ namespace AtomToolsFramework
return result; return result;
} }
bool AtomToolsDocumentSystemComponent::CloseAllDocumentsExcept(const AZ::Uuid& documentId) bool AtomToolsDocumentSystem::CloseAllDocumentsExcept(const AZ::Uuid& documentId)
{ {
bool result = true; bool result = true;
auto documentMap = m_documentMap; auto documentMap = m_documentMap;
@ -356,7 +244,7 @@ namespace AtomToolsFramework
return result; return result;
} }
bool AtomToolsDocumentSystemComponent::SaveDocument(const AZ::Uuid& documentId) bool AtomToolsDocumentSystem::SaveDocument(const AZ::Uuid& documentId)
{ {
AZStd::string saveDocumentPath; AZStd::string saveDocumentPath;
AtomToolsDocumentRequestBus::EventResult(saveDocumentPath, documentId, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath); AtomToolsDocumentRequestBus::EventResult(saveDocumentPath, documentId, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
@ -369,26 +257,30 @@ namespace AtomToolsFramework
const QFileInfo saveInfo(saveDocumentPath.c_str()); const QFileInfo saveInfo(saveDocumentPath.c_str());
if (saveInfo.exists() && !saveInfo.isWritable()) if (saveInfo.exists() && !saveInfo.isWritable())
{ {
QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str())); QMessageBox::critical(
QApplication::activeWindow(),
QObject::tr("Document could not be saved"),
QObject::tr("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str()));
return false; return false;
} }
AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); TraceRecorder traceRecorder(m_maxMessageBoxLineCount);
bool result = false; bool result = false;
AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsDocumentRequestBus::Events::Save); AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsDocumentRequestBus::Events::Save);
if (!result) if (!result)
{ {
QMessageBox::critical( QMessageBox::critical(
QApplication::activeWindow(), QString("Document could not be saved"), QApplication::activeWindow(),
QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str())); QObject::tr("Document could not be saved"),
QObject::tr("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str()));
return false; return false;
} }
return true; return true;
} }
bool AtomToolsDocumentSystemComponent::SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath) bool AtomToolsDocumentSystem::SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath)
{ {
AZStd::string saveDocumentPath = targetPath; AZStd::string saveDocumentPath = targetPath;
if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath)) if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath))
@ -399,26 +291,29 @@ namespace AtomToolsFramework
const QFileInfo saveInfo(saveDocumentPath.c_str()); const QFileInfo saveInfo(saveDocumentPath.c_str());
if (saveInfo.exists() && !saveInfo.isWritable()) if (saveInfo.exists() && !saveInfo.isWritable())
{ {
QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str())); QMessageBox::critical(QApplication::activeWindow(),
QObject::tr("Document could not be saved"),
QObject::tr("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str()));
return false; return false;
} }
AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); TraceRecorder traceRecorder(m_maxMessageBoxLineCount);
bool result = false; bool result = false;
AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsDocumentRequestBus::Events::SaveAsCopy, saveDocumentPath); AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsDocumentRequestBus::Events::SaveAsCopy, saveDocumentPath);
if (!result) if (!result)
{ {
QMessageBox::critical( QMessageBox::critical(
QApplication::activeWindow(), QString("Document could not be saved"), QApplication::activeWindow(),
QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str())); QObject::tr("Document could not be saved"),
QObject::tr("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str()));
return false; return false;
} }
return true; return true;
} }
bool AtomToolsDocumentSystemComponent::SaveDocumentAsChild(const AZ::Uuid& documentId, AZStd::string_view targetPath) bool AtomToolsDocumentSystem::SaveDocumentAsChild(const AZ::Uuid& documentId, AZStd::string_view targetPath)
{ {
AZStd::string saveDocumentPath = targetPath; AZStd::string saveDocumentPath = targetPath;
if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath)) if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath))
@ -429,26 +324,30 @@ namespace AtomToolsFramework
const QFileInfo saveInfo(saveDocumentPath.c_str()); const QFileInfo saveInfo(saveDocumentPath.c_str());
if (saveInfo.exists() && !saveInfo.isWritable()) if (saveInfo.exists() && !saveInfo.isWritable())
{ {
QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str())); QMessageBox::critical(
QApplication::activeWindow(),
QObject::tr("Document could not be saved"),
QObject::tr("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str()));
return false; return false;
} }
AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); TraceRecorder traceRecorder(m_maxMessageBoxLineCount);
bool result = false; bool result = false;
AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsDocumentRequestBus::Events::SaveAsChild, saveDocumentPath); AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsDocumentRequestBus::Events::SaveAsChild, saveDocumentPath);
if (!result) if (!result)
{ {
QMessageBox::critical( QMessageBox::critical(
QApplication::activeWindow(), QString("Document could not be saved"), QApplication::activeWindow(),
QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str())); QObject::tr("Document could not be saved"),
QObject::tr("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str()));
return false; return false;
} }
return true; return true;
} }
bool AtomToolsDocumentSystemComponent::SaveAllDocuments() bool AtomToolsDocumentSystem::SaveAllDocuments()
{ {
bool result = true; bool result = true;
for (const auto& documentPair : m_documentMap) for (const auto& documentPair : m_documentMap)
@ -462,12 +361,110 @@ namespace AtomToolsFramework
return result; return result;
} }
AZ::u32 AtomToolsDocumentSystemComponent::GetDocumentCount() const AZ::u32 AtomToolsDocumentSystem::GetDocumentCount() const
{ {
return aznumeric_cast<AZ::u32>(m_documentMap.size()); return aznumeric_cast<AZ::u32>(m_documentMap.size());
} }
AZ::Uuid AtomToolsDocumentSystemComponent::OpenDocumentImpl(AZStd::string_view sourcePath, bool checkIfAlreadyOpen)
void AtomToolsDocumentSystem::OnDocumentExternallyModified(const AZ::Uuid& documentId)
{
m_documentIdsWithExternalChanges.insert(documentId);
QueueReopenDocuments();
}
void AtomToolsDocumentSystem::OnDocumentDependencyModified(const AZ::Uuid& documentId)
{
m_documentIdsWithDependencyChanges.insert(documentId);
QueueReopenDocuments();
}
void AtomToolsDocumentSystem::QueueReopenDocuments()
{
if (!m_queueReopenDocuments)
{
m_queueReopenDocuments = true;
QTimer::singleShot(0, [this] { ReopenDocuments(); });
}
}
void AtomToolsDocumentSystem::ReopenDocuments()
{
const bool enableHotReload = GetSettingOrDefault<bool>("/O3DE/AtomToolsFramework/AtomToolsDocumentSystem/EnableHotReload", true);
if (!enableHotReload)
{
m_documentIdsWithDependencyChanges.clear();
m_documentIdsWithExternalChanges.clear();
m_queueReopenDocuments = false;
}
const bool enableHotReloadPrompts =
GetSettingOrDefault<bool>("/O3DE/AtomToolsFramework/AtomToolsDocumentSystem/EnableHotReloadPrompts", true);
for (const AZ::Uuid& documentId : m_documentIdsWithExternalChanges)
{
m_documentIdsWithDependencyChanges.erase(documentId);
AZStd::string documentPath;
AtomToolsDocumentRequestBus::EventResult(documentPath, documentId, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
if (enableHotReloadPrompts &&
(QMessageBox::question(QApplication::activeWindow(),
QObject::tr("Document was externally modified"),
QObject::tr("Would you like to reopen the document:\n%1?").arg(documentPath.c_str()),
QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes))
{
continue;
}
TraceRecorder traceRecorder(m_maxMessageBoxLineCount);
bool openResult = false;
AtomToolsDocumentRequestBus::EventResult(openResult, documentId, &AtomToolsDocumentRequestBus::Events::Open, documentPath);
if (!openResult)
{
QMessageBox::critical(
QApplication::activeWindow(),
QObject::tr("Document could not be opened"),
QObject::tr("Failed to open: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str()));
CloseDocument(documentId);
}
}
for (const AZ::Uuid& documentId : m_documentIdsWithDependencyChanges)
{
AZStd::string documentPath;
AtomToolsDocumentRequestBus::EventResult(documentPath, documentId, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
if (enableHotReloadPrompts &&
(QMessageBox::question(QApplication::activeWindow(),
QObject::tr("Document dependencies have changed"),
QObject::tr("Would you like to update the document with these changes:\n%1?").arg(documentPath.c_str()),
QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes))
{
continue;
}
TraceRecorder traceRecorder(m_maxMessageBoxLineCount);
bool openResult = false;
AtomToolsDocumentRequestBus::EventResult(openResult, documentId, &AtomToolsDocumentRequestBus::Events::Reopen);
if (!openResult)
{
QMessageBox::critical(
QApplication::activeWindow(),
QObject::tr("Document could not be opened"),
QObject::tr("Failed to open: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str()));
CloseDocument(documentId);
}
}
m_documentIdsWithDependencyChanges.clear();
m_documentIdsWithExternalChanges.clear();
m_queueReopenDocuments = false;
}
AZ::Uuid AtomToolsDocumentSystem::OpenDocumentImpl(AZStd::string_view sourcePath, bool checkIfAlreadyOpen)
{ {
AZStd::string requestedPath = sourcePath; AZStd::string requestedPath = sourcePath;
if (requestedPath.empty()) if (requestedPath.empty())
@ -477,7 +474,9 @@ namespace AtomToolsFramework
if (!AzFramework::StringFunc::Path::Normalize(requestedPath)) if (!AzFramework::StringFunc::Path::Normalize(requestedPath))
{ {
QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document path is invalid:\n%1").arg(requestedPath.c_str())); QMessageBox::critical(QApplication::activeWindow(),
QObject::tr("Document could not be opened"),
QObject::tr("Document path is invalid:\n%1").arg(requestedPath.c_str()));
return AZ::Uuid::CreateNull(); return AZ::Uuid::CreateNull();
} }
@ -490,21 +489,22 @@ namespace AtomToolsFramework
AtomToolsDocumentRequestBus::EventResult(openDocumentPath, documentPair.first, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath); AtomToolsDocumentRequestBus::EventResult(openDocumentPath, documentPair.first, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
if (openDocumentPath == requestedPath) if (openDocumentPath == requestedPath)
{ {
AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, documentPair.first); AtomToolsDocumentNotificationBus::Event(
m_toolId, &AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, documentPair.first);
return documentPair.first; return documentPair.first;
} }
} }
} }
AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); TraceRecorder traceRecorder(m_maxMessageBoxLineCount);
AZ::Uuid documentId = AZ::Uuid::CreateNull(); AZ::Uuid documentId = CreateDocument();
AtomToolsDocumentSystemRequestBus::BroadcastResult(documentId, &AtomToolsDocumentSystemRequestBus::Events::CreateDocument);
if (documentId.IsNull()) if (documentId.IsNull())
{ {
QMessageBox::critical( QMessageBox::critical(
QApplication::activeWindow(), QString("Document could not be created"), QApplication::activeWindow(),
QString("Failed to create: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str())); QObject::tr("Document could not be opened"),
QObject::tr("Failed to create: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str()));
return AZ::Uuid::CreateNull(); return AZ::Uuid::CreateNull();
} }
@ -513,18 +513,20 @@ namespace AtomToolsFramework
if (!openResult) if (!openResult)
{ {
QMessageBox::critical( QMessageBox::critical(
QApplication::activeWindow(), QString("Document could not be opened"), QApplication::activeWindow(),
QString("Failed to open: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str())); QObject::tr("Document could not be opened"),
AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::DestroyDocument, documentId); QObject::tr("Failed to open: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str()));
DestroyDocument(documentId);
return AZ::Uuid::CreateNull(); return AZ::Uuid::CreateNull();
} }
else if (traceRecorder.GetWarningCount(true) > 0) else if (traceRecorder.GetWarningCount(true) > 0)
{ {
QMessageBox::warning( QMessageBox::warning(
QApplication::activeWindow(), QString("Document opened with warnings"), QApplication::activeWindow(),
QString("Warnings encountered: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str())); QObject::tr("Document opened with warnings"),
QObject::tr("Warnings encountered: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str()));
} }
return documentId; return documentId;
} }
} } // namespace AtomToolsFramework

@ -6,8 +6,11 @@
* *
*/ */
#include <Atom/RHI/Factory.h>
#include <AtomToolsFramework/PerformanceMonitor/PerformanceMonitorRequestBus.h> #include <AtomToolsFramework/PerformanceMonitor/PerformanceMonitorRequestBus.h>
#include <AtomToolsFramework/Window/AtomToolsMainWindow.h> #include <AtomToolsFramework/Window/AtomToolsMainWindow.h>
#include <AzCore/Name/Name.h>
#include <AzCore/Utils/Utils.h>
#include <AzToolsFramework/API/EditorPythonRunnerRequestsBus.h> #include <AzToolsFramework/API/EditorPythonRunnerRequestsBus.h>
#include <AzToolsFramework/PythonTerminal/ScriptTermDialog.h> #include <AzToolsFramework/PythonTerminal/ScriptTermDialog.h>
@ -19,11 +22,11 @@
namespace AtomToolsFramework namespace AtomToolsFramework
{ {
AtomToolsMainWindow::AtomToolsMainWindow(QWidget* parent) AtomToolsMainWindow::AtomToolsMainWindow(const AZ::Crc32& toolId, QWidget* parent)
: AzQtComponents::DockMainWindow(parent) : AzQtComponents::DockMainWindow(parent)
, m_toolId(toolId)
, m_advancedDockManager(new AzQtComponents::FancyDocking(this))
{ {
m_advancedDockManager = new AzQtComponents::FancyDocking(this);
setDockNestingEnabled(true); setDockNestingEnabled(true);
setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea); setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea); setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
@ -42,20 +45,21 @@ namespace AtomToolsFramework
centralWidget->setLayout(centralWidgetLayout); centralWidget->setLayout(centralWidgetLayout);
setCentralWidget(centralWidget); setCentralWidget(centralWidget);
m_assetBrowser = new AtomToolsFramework::AtomToolsAssetBrowser(this); m_assetBrowser = new AtomToolsAssetBrowser(this);
AddDockWidget("Asset Browser", m_assetBrowser, Qt::BottomDockWidgetArea, Qt::Horizontal); AddDockWidget("Asset Browser", m_assetBrowser, Qt::BottomDockWidgetArea, Qt::Horizontal);
AddDockWidget("Python Terminal", new AzToolsFramework::CScriptTermDialog, Qt::BottomDockWidgetArea, Qt::Horizontal); AddDockWidget("Python Terminal", new AzToolsFramework::CScriptTermDialog, Qt::BottomDockWidgetArea, Qt::Horizontal);
SetDockWidgetVisible("Python Terminal", false); SetDockWidgetVisible("Python Terminal", false);
SetupMetrics(); SetupMetrics();
UpdateWindowTitle();
resize(1280, 1024);
AtomToolsMainWindowRequestBus::Handler::BusConnect(); AtomToolsMainWindowRequestBus::Handler::BusConnect(m_toolId);
} }
AtomToolsMainWindow::~AtomToolsMainWindow() AtomToolsMainWindow::~AtomToolsMainWindow()
{ {
AtomToolsFramework::PerformanceMonitorRequestBus::Broadcast( PerformanceMonitorRequestBus::Broadcast(&PerformanceMonitorRequestBus::Handler::SetProfilerEnabled, false);
&AtomToolsFramework::PerformanceMonitorRequestBus::Handler::SetProfilerEnabled, false);
AtomToolsMainWindowRequestBus::Handler::BusDisconnect(); AtomToolsMainWindowRequestBus::Handler::BusDisconnect();
} }
@ -160,10 +164,12 @@ namespace AtomToolsFramework
m_menuHelp = menuBar()->addMenu("&Help"); m_menuHelp = menuBar()->addMenu("&Help");
m_menuFile->addAction("Run &Python...", [this]() { m_menuFile->addAction("Run &Python...", [this]() {
const QString script = QFileDialog::getOpenFileName(this, "Run Script", QString(), QString("*.py")); const QString script = QFileDialog::getOpenFileName(
this, QObject::tr("Run Script"), QString(AZ::Utils::GetProjectPath().c_str()), QString("*.py"));
if (!script.isEmpty()) if (!script.isEmpty())
{ {
AzToolsFramework::EditorPythonRunnerRequestBus::Broadcast(&AzToolsFramework::EditorPythonRunnerRequestBus::Events::ExecuteByFilename, script.toUtf8().constData()); AzToolsFramework::EditorPythonRunnerRequestBus::Broadcast(
&AzToolsFramework::EditorPythonRunnerRequestBus::Events::ExecuteByFilename, script.toUtf8().constData());
} }
}); });
@ -213,21 +219,34 @@ namespace AtomToolsFramework
m_metricsTimer.start(); m_metricsTimer.start();
connect(&m_metricsTimer, &QTimer::timeout, this, &AtomToolsMainWindow::UpdateMetrics); connect(&m_metricsTimer, &QTimer::timeout, this, &AtomToolsMainWindow::UpdateMetrics);
AtomToolsFramework::PerformanceMonitorRequestBus::Broadcast( PerformanceMonitorRequestBus::Broadcast(&PerformanceMonitorRequestBus::Handler::SetProfilerEnabled, true);
&AtomToolsFramework::PerformanceMonitorRequestBus::Handler::SetProfilerEnabled, true);
UpdateMetrics(); UpdateMetrics();
} }
void AtomToolsMainWindow::UpdateMetrics() void AtomToolsMainWindow::UpdateMetrics()
{ {
AtomToolsFramework::PerformanceMetrics metrics = {}; PerformanceMetrics metrics = {};
AtomToolsFramework::PerformanceMonitorRequestBus::BroadcastResult( PerformanceMonitorRequestBus::BroadcastResult(metrics, &PerformanceMonitorRequestBus::Handler::GetMetrics);
metrics, &AtomToolsFramework::PerformanceMonitorRequestBus::Handler::GetMetrics);
m_statusBarCpuTime->setText(tr("CPU Time %1 ms").arg(QString::number(metrics.m_cpuFrameTimeMs, 'f', 2))); 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))); 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; int frameRate = metrics.m_cpuFrameTimeMs > 0 ? aznumeric_cast<int>(1000 / metrics.m_cpuFrameTimeMs) : 0;
m_statusBarFps->setText(tr("FPS %1").arg(QString::number(frameRate))); 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 } // namespace AtomToolsFramework

@ -6,7 +6,6 @@
* *
*/ */
#include <AtomToolsFramework/Window/AtomToolsMainWindowFactoryRequestBus.h>
#include <AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h> #include <AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h>
#include <AzCore/RTTI/BehaviorContext.h> #include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h> #include <AzCore/Serialization/EditContext.h>
@ -25,14 +24,6 @@ namespace AtomToolsFramework
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context)) if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{ {
behaviorContext->EBus<AtomToolsMainWindowFactoryRequestBus>("AtomToolsMainWindowFactoryRequestBus")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Category, "Editor")
->Attribute(AZ::Script::Attributes::Module, "atomtools")
->Event("CreateMainWindow", &AtomToolsMainWindowFactoryRequestBus::Events::CreateMainWindow)
->Event("DestroyMainWindow", &AtomToolsMainWindowFactoryRequestBus::Events::DestroyMainWindow)
;
behaviorContext->EBus<AtomToolsMainWindowRequestBus>("AtomToolsMainWindowRequestBus") behaviorContext->EBus<AtomToolsMainWindowRequestBus>("AtomToolsMainWindowRequestBus")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Category, "Editor") ->Attribute(AZ::Script::Attributes::Category, "Editor")

@ -15,6 +15,7 @@ set(FILES
Include/AtomToolsFramework/Communication/LocalSocket.h Include/AtomToolsFramework/Communication/LocalSocket.h
Include/AtomToolsFramework/Debug/TraceRecorder.h Include/AtomToolsFramework/Debug/TraceRecorder.h
Include/AtomToolsFramework/Document/AtomToolsDocument.h Include/AtomToolsFramework/Document/AtomToolsDocument.h
Include/AtomToolsFramework/Document/AtomToolsDocumentSystem.h
Include/AtomToolsFramework/Document/AtomToolsDocumentApplication.h Include/AtomToolsFramework/Document/AtomToolsDocumentApplication.h
Include/AtomToolsFramework/Document/AtomToolsDocumentMainWindow.h Include/AtomToolsFramework/Document/AtomToolsDocumentMainWindow.h
Include/AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h Include/AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h
@ -38,7 +39,6 @@ set(FILES
Include/AtomToolsFramework/Viewport/ModularViewportCameraControllerRequestBus.h Include/AtomToolsFramework/Viewport/ModularViewportCameraControllerRequestBus.h
Include/AtomToolsFramework/Window/AtomToolsMainWindow.h Include/AtomToolsFramework/Window/AtomToolsMainWindow.h
Include/AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h Include/AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h
Include/AtomToolsFramework/Window/AtomToolsMainWindowFactoryRequestBus.h
Include/AtomToolsFramework/Window/AtomToolsMainWindowNotificationBus.h Include/AtomToolsFramework/Window/AtomToolsMainWindowNotificationBus.h
Source/Application/AtomToolsApplication.cpp Source/Application/AtomToolsApplication.cpp
Source/AssetBrowser/AtomToolsAssetBrowser.cpp Source/AssetBrowser/AtomToolsAssetBrowser.cpp
@ -53,8 +53,7 @@ set(FILES
Source/Document/AtomToolsDocument.cpp Source/Document/AtomToolsDocument.cpp
Source/Document/AtomToolsDocumentApplication.cpp Source/Document/AtomToolsDocumentApplication.cpp
Source/Document/AtomToolsDocumentMainWindow.cpp Source/Document/AtomToolsDocumentMainWindow.cpp
Source/Document/AtomToolsDocumentSystemComponent.cpp Source/Document/AtomToolsDocumentSystem.cpp
Source/Document/AtomToolsDocumentSystemComponent.h
Source/DynamicProperty/DynamicProperty.cpp Source/DynamicProperty/DynamicProperty.cpp
Source/DynamicProperty/DynamicPropertyGroup.cpp Source/DynamicProperty/DynamicPropertyGroup.cpp
Source/Inspector/InspectorWidget.cpp Source/Inspector/InspectorWidget.cpp

@ -21,8 +21,8 @@
namespace MaterialEditor namespace MaterialEditor
{ {
MaterialDocument::MaterialDocument() MaterialDocument::MaterialDocument(const AZ::Crc32& toolId)
: AtomToolsFramework::AtomToolsDocument() : AtomToolsFramework::AtomToolsDocument(toolId)
{ {
MaterialDocumentRequestBus::Handler::BusConnect(m_id); MaterialDocumentRequestBus::Handler::BusConnect(m_id);
} }
@ -86,12 +86,12 @@ namespace MaterialEditor
} }
} }
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( AtomToolsFramework::AtomToolsDocumentNotificationBus::Event(
&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentObjectInfoChanged, m_id, m_toolId, &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentObjectInfoChanged, m_id,
GetObjectInfoFromDynamicPropertyGroup(group.get()), false); GetObjectInfoFromDynamicPropertyGroup(group.get()), false);
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( AtomToolsFramework::AtomToolsDocumentNotificationBus::Event(
&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentModified, m_id); m_toolId, &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentModified, m_id);
return false; return false;
} }
} }
@ -826,8 +826,8 @@ namespace MaterialEditor
if (groupChange || groupRebuilt) if (groupChange || groupRebuilt)
{ {
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( AtomToolsFramework::AtomToolsDocumentNotificationBus::Event(
&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentObjectInfoChanged, m_id, m_toolId, &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentObjectInfoChanged, m_id,
GetObjectInfoFromDynamicPropertyGroup(group.get()), groupRebuilt); GetObjectInfoFromDynamicPropertyGroup(group.get()), groupRebuilt);
} }
return true; return true;

@ -31,9 +31,9 @@ namespace MaterialEditor
public: public:
AZ_RTTI(MaterialDocument, "{DBA269AE-892B-415C-8FA1-166B94B0E045}"); AZ_RTTI(MaterialDocument, "{DBA269AE-892B-415C-8FA1-166B94B0E045}");
AZ_CLASS_ALLOCATOR(MaterialDocument, AZ::SystemAllocator, 0); AZ_CLASS_ALLOCATOR(MaterialDocument, AZ::SystemAllocator, 0);
AZ_DISABLE_COPY(MaterialDocument); AZ_DISABLE_COPY_MOVE(MaterialDocument);
MaterialDocument(); MaterialDocument(const AZ::Crc32& toolId);
virtual ~MaterialDocument(); virtual ~MaterialDocument();
// AtomToolsFramework::AtomToolsDocument overrides... // AtomToolsFramework::AtomToolsDocument overrides...

@ -42,24 +42,26 @@ void InitMaterialEditorResources()
namespace MaterialEditor namespace MaterialEditor
{ {
static const char* GetBuildTargetName()
{
#if !defined(LY_CMAKE_TARGET)
#error "LY_CMAKE_TARGET must be defined in order to add this source file to a CMake executable target"
#endif
return LY_CMAKE_TARGET;
}
MaterialEditorApplication::MaterialEditorApplication(int* argc, char*** argv) MaterialEditorApplication::MaterialEditorApplication(int* argc, char*** argv)
: Base(argc, argv) : Base(GetBuildTargetName(), argc, argv)
{ {
InitMaterialEditorResources(); InitMaterialEditorResources();
QApplication::setApplicationName("O3DE Material Editor"); QApplication::setApplicationName("O3DE Material Editor");
// The settings registry has been created at this point, so add the CMake target
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddBuildSystemTargetSpecialization(
*AZ::SettingsRegistry::Get(), GetBuildTargetName());
AzToolsFramework::EditorWindowRequestBus::Handler::BusConnect(); AzToolsFramework::EditorWindowRequestBus::Handler::BusConnect();
AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Handler::BusConnect();
} }
MaterialEditorApplication::~MaterialEditorApplication() MaterialEditorApplication::~MaterialEditorApplication()
{ {
AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Handler::BusDisconnect();
AzToolsFramework::EditorWindowRequestBus::Handler::BusDisconnect(); AzToolsFramework::EditorWindowRequestBus::Handler::BusDisconnect();
m_window.reset(); m_window.reset();
} }
@ -101,35 +103,20 @@ namespace MaterialEditor
{ {
Base::StartCommon(systemEntity); Base::StartCommon(systemEntity);
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast( AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Event(
&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Handler::RegisterDocumentType, m_toolId, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Handler::RegisterDocumentType,
[]() { return aznew MaterialDocument(); }); [](const AZ::Crc32& toolId) { return aznew MaterialDocument(toolId); });
}
AZStd::string MaterialEditorApplication::GetBuildTargetName() const
{
#if !defined(LY_CMAKE_TARGET)
#error "LY_CMAKE_TARGET must be defined in order to add this source file to a CMake executable target"
#endif
//! Returns the build system target name of "MaterialEditor"
return AZStd::string{ LY_CMAKE_TARGET };
}
AZStd::vector<AZStd::string> MaterialEditorApplication::GetCriticalAssetFilters() const m_window.reset(aznew MaterialEditorWindow(m_toolId));
{
return AZStd::vector<AZStd::string>({ "passes/", "config/", "MaterialEditor/" });
}
void MaterialEditorApplication::CreateMainWindow()
{
m_window.reset(aznew MaterialEditorWindow);
m_assetBrowserInteractions.reset(aznew AtomToolsFramework::AtomToolsAssetBrowserInteractions); m_assetBrowserInteractions.reset(aznew AtomToolsFramework::AtomToolsAssetBrowserInteractions);
m_assetBrowserInteractions->RegisterContextMenuActions( m_assetBrowserInteractions->RegisterContextMenuActions(
[](const AtomToolsFramework::AtomToolsAssetBrowserInteractions::AssetBrowserEntryVector& entries) [](const AtomToolsFramework::AtomToolsAssetBrowserInteractions::AssetBrowserEntryVector& entries)
{ {
return entries.front()->GetEntryType() == AzToolsFramework::AssetBrowser::AssetBrowserEntry::AssetEntryType::Source; return entries.front()->GetEntryType() == AzToolsFramework::AssetBrowser::AssetBrowserEntry::AssetEntryType::Source;
}, },
[]([[maybe_unused]] QWidget* caller, QMenu* menu, const AtomToolsFramework::AtomToolsAssetBrowserInteractions::AssetBrowserEntryVector& entries) [this]([[maybe_unused]] QWidget* caller, QMenu* menu, const AtomToolsFramework::AtomToolsAssetBrowserInteractions::AssetBrowserEntryVector& entries)
{ {
const bool isMaterial = AzFramework::StringFunc::Path::IsExtension( const bool isMaterial = AzFramework::StringFunc::Path::IsExtension(
entries.front()->GetFullPath().c_str(), AZ::RPI::MaterialSourceData::Extension); entries.front()->GetFullPath().c_str(), AZ::RPI::MaterialSourceData::Extension);
@ -137,17 +124,17 @@ namespace MaterialEditor
entries.front()->GetFullPath().c_str(), AZ::RPI::MaterialTypeSourceData::Extension); entries.front()->GetFullPath().c_str(), AZ::RPI::MaterialTypeSourceData::Extension);
if (isMaterial || isMaterialType) if (isMaterial || isMaterialType)
{ {
menu->addAction(QObject::tr("Open"), [entries]() menu->addAction(QObject::tr("Open"), [entries, this]()
{ {
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast( AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Event(
&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, m_toolId, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument,
entries.front()->GetFullPath()); entries.front()->GetFullPath());
}); });
const QString createActionName = const QString createActionName =
isMaterialType ? QObject::tr("Create Material...") : QObject::tr("Create Child Material..."); isMaterialType ? QObject::tr("Create Material...") : QObject::tr("Create Child Material...");
menu->addAction(createActionName, [entries]() menu->addAction(createActionName, [entries, this]()
{ {
const QString defaultPath = AtomToolsFramework::GetUniqueFileInfo( const QString defaultPath = AtomToolsFramework::GetUniqueFileInfo(
QString(AZ::Utils::GetProjectPath().c_str()) + QString(AZ::Utils::GetProjectPath().c_str()) +
@ -155,8 +142,8 @@ namespace MaterialEditor
AZ_CORRECT_FILESYSTEM_SEPARATOR + "untitled." + AZ_CORRECT_FILESYSTEM_SEPARATOR + "untitled." +
AZ::RPI::MaterialSourceData::Extension).absoluteFilePath(); AZ::RPI::MaterialSourceData::Extension).absoluteFilePath();
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast( AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Event(
&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CreateDocumentFromFile, m_toolId, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CreateDocumentFromFile,
entries.front()->GetFullPath(), entries.front()->GetFullPath(),
AtomToolsFramework::GetSaveFileInfo(defaultPath).absoluteFilePath().toUtf8().constData()); AtomToolsFramework::GetSaveFileInfo(defaultPath).absoluteFilePath().toUtf8().constData());
}); });
@ -175,9 +162,9 @@ namespace MaterialEditor
{ {
return entries.front()->GetEntryType() == AzToolsFramework::AssetBrowser::AssetBrowserEntry::AssetEntryType::Folder; return entries.front()->GetEntryType() == AzToolsFramework::AssetBrowser::AssetBrowserEntry::AssetEntryType::Folder;
}, },
[](QWidget* caller, QMenu* menu, const AtomToolsFramework::AtomToolsAssetBrowserInteractions::AssetBrowserEntryVector& entries) [this](QWidget* caller, QMenu* menu, const AtomToolsFramework::AtomToolsAssetBrowserInteractions::AssetBrowserEntryVector& entries)
{ {
menu->addAction(QObject::tr("Create Material..."), [caller, entries]() menu->addAction(QObject::tr("Create Material..."), [caller, entries, this]()
{ {
CreateMaterialDialog createDialog(entries.front()->GetFullPath().c_str(), caller); CreateMaterialDialog createDialog(entries.front()->GetFullPath().c_str(), caller);
createDialog.adjustSize(); createDialog.adjustSize();
@ -186,8 +173,8 @@ namespace MaterialEditor
!createDialog.m_materialFileInfo.absoluteFilePath().isEmpty() && !createDialog.m_materialFileInfo.absoluteFilePath().isEmpty() &&
!createDialog.m_materialTypeFileInfo.absoluteFilePath().isEmpty()) !createDialog.m_materialTypeFileInfo.absoluteFilePath().isEmpty())
{ {
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast( AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Event(
&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CreateDocumentFromFile, m_toolId, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CreateDocumentFromFile,
createDialog.m_materialTypeFileInfo.absoluteFilePath().toUtf8().constData(), createDialog.m_materialTypeFileInfo.absoluteFilePath().toUtf8().constData(),
createDialog.m_materialFileInfo.absoluteFilePath().toUtf8().constData()); createDialog.m_materialFileInfo.absoluteFilePath().toUtf8().constData());
} }
@ -195,9 +182,15 @@ namespace MaterialEditor
}); });
} }
void MaterialEditorApplication::DestroyMainWindow() void MaterialEditorApplication::Destroy()
{ {
m_window.reset(); m_window.reset();
Base::Destroy();
}
AZStd::vector<AZStd::string> MaterialEditorApplication::GetCriticalAssetFilters() const
{
return AZStd::vector<AZStd::string>({ "passes/", "config/", "MaterialEditor/" });
} }
QWidget* MaterialEditorApplication::GetAppMainWindow() QWidget* MaterialEditorApplication::GetAppMainWindow()

@ -10,7 +10,6 @@
#include <AtomToolsFramework/AssetBrowser/AtomToolsAssetBrowserInteractions.h> #include <AtomToolsFramework/AssetBrowser/AtomToolsAssetBrowserInteractions.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentApplication.h> #include <AtomToolsFramework/Document/AtomToolsDocumentApplication.h>
#include <AtomToolsFramework/Window/AtomToolsMainWindowFactoryRequestBus.h>
#include <AzToolsFramework/API/EditorWindowRequestBus.h> #include <AzToolsFramework/API/EditorWindowRequestBus.h>
#include <Window/MaterialEditorWindow.h> #include <Window/MaterialEditorWindow.h>
@ -21,7 +20,6 @@ namespace MaterialEditor
class MaterialEditorApplication class MaterialEditorApplication
: public AtomToolsFramework::AtomToolsDocumentApplication : public AtomToolsFramework::AtomToolsDocumentApplication
, private AzToolsFramework::EditorWindowRequestBus::Handler , private AzToolsFramework::EditorWindowRequestBus::Handler
, private AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Handler
{ {
public: public:
AZ_TYPE_INFO(MaterialEditor::MaterialEditorApplication, "{30F90CA5-1253-49B5-8143-19CEE37E22BB}"); AZ_TYPE_INFO(MaterialEditor::MaterialEditorApplication, "{30F90CA5-1253-49B5-8143-19CEE37E22BB}");
@ -36,15 +34,11 @@ namespace MaterialEditor
void CreateStaticModules(AZStd::vector<AZ::Module*>& outModules) override; void CreateStaticModules(AZStd::vector<AZ::Module*>& outModules) override;
const char* GetCurrentConfigurationName() const override; const char* GetCurrentConfigurationName() const override;
void StartCommon(AZ::Entity* systemEntity) override; void StartCommon(AZ::Entity* systemEntity) override;
void Destroy() override;
// AtomToolsFramework::AtomToolsApplication overrides... // AtomToolsFramework::AtomToolsApplication overrides...
AZStd::string GetBuildTargetName() const override;
AZStd::vector<AZStd::string> GetCriticalAssetFilters() const override; AZStd::vector<AZStd::string> GetCriticalAssetFilters() const override;
// AtomToolsMainWindowFactoryRequestBus::Handler overrides...
void CreateMainWindow() override;
void DestroyMainWindow() override;
// AzToolsFramework::EditorWindowRequests::Bus::Handler // AzToolsFramework::EditorWindowRequests::Bus::Handler
QWidget* GetAppMainWindow() override; QWidget* GetAppMainWindow() override;

@ -60,9 +60,10 @@ namespace MaterialEditor
{ {
static constexpr float DepthNear = 0.01f; static constexpr float DepthNear = 0.01f;
MaterialViewportWidget::MaterialViewportWidget(QWidget* parent) MaterialViewportWidget::MaterialViewportWidget(const AZ::Crc32& toolId, QWidget* parent)
: AtomToolsFramework::RenderViewportWidget(parent) : AtomToolsFramework::RenderViewportWidget(parent)
, m_ui(new Ui::MaterialViewportWidget) , m_ui(new Ui::MaterialViewportWidget)
, m_toolId(toolId)
, m_viewportController(AZStd::make_shared<MaterialEditorViewportInputController>()) , m_viewportController(AZStd::make_shared<MaterialEditorViewportInputController>())
{ {
m_ui->setupUi(this); m_ui->setupUi(this);
@ -252,7 +253,7 @@ namespace MaterialEditor
OnFieldOfViewChanged(viewportSettings->m_fieldOfView); OnFieldOfViewChanged(viewportSettings->m_fieldOfView);
OnDisplayMapperOperationTypeChanged(viewportSettings->m_displayMapperOperationType); OnDisplayMapperOperationTypeChanged(viewportSettings->m_displayMapperOperationType);
AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect(); AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect(m_toolId);
MaterialViewportNotificationBus::Handler::BusConnect(); MaterialViewportNotificationBus::Handler::BusConnect();
AZ::TickBus::Handler::BusConnect(); AZ::TickBus::Handler::BusConnect();
AZ::TransformNotificationBus::MultiHandler::BusConnect(m_cameraEntity->GetId()); AZ::TransformNotificationBus::MultiHandler::BusConnect(m_cameraEntity->GetId());

@ -57,7 +57,7 @@ namespace MaterialEditor
, public AZ::TransformNotificationBus::MultiHandler , public AZ::TransformNotificationBus::MultiHandler
{ {
public: public:
MaterialViewportWidget(QWidget* parent = nullptr); MaterialViewportWidget(const AZ::Crc32& toolId, QWidget* parent = nullptr);
~MaterialViewportWidget(); ~MaterialViewportWidget();
private: private:
@ -84,6 +84,8 @@ namespace MaterialEditor
// AZ::TransformNotificationBus::MultiHandler overrides... // AZ::TransformNotificationBus::MultiHandler overrides...
void OnTransformChanged(const AZ::Transform&, const AZ::Transform&) override; void OnTransformChanged(const AZ::Transform&, const AZ::Transform&) override;
const AZ::Crc32 m_toolId = {};
using DirectionalLightHandle = AZ::Render::DirectionalLightFeatureProcessorInterface::LightHandle; using DirectionalLightHandle = AZ::Render::DirectionalLightFeatureProcessorInterface::LightHandle;
AZ::Data::Instance<AZ::RPI::SwapChainPass> m_swapChainPass; AZ::Data::Instance<AZ::RPI::SwapChainPass> m_swapChainPass;

@ -6,7 +6,6 @@
* *
*/ */
#include <Atom/RHI/Factory.h>
#include <Atom/RPI.Edit/Material/MaterialSourceData.h> #include <Atom/RPI.Edit/Material/MaterialSourceData.h>
#include <Atom/RPI.Edit/Material/MaterialTypeSourceData.h> #include <Atom/RPI.Edit/Material/MaterialTypeSourceData.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h> #include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
@ -36,11 +35,9 @@ AZ_POP_DISABLE_WARNING
namespace MaterialEditor namespace MaterialEditor
{ {
MaterialEditorWindow::MaterialEditorWindow(QWidget* parent /* = 0 */) MaterialEditorWindow::MaterialEditorWindow(const AZ::Crc32& toolId, QWidget* parent)
: Base(parent) : Base(toolId, parent)
{ {
resize(1280, 1024);
// Among other things, we need the window wrapper to save the main window size, position, and state // Among other things, we need the window wrapper to save the main window size, position, and state
auto mainWindowWrapper = auto mainWindowWrapper =
new AzQtComponents::WindowDecorationWrapper(AzQtComponents::WindowDecorationWrapper::OptionAutoTitleBarButtons); new AzQtComponents::WindowDecorationWrapper(AzQtComponents::WindowDecorationWrapper::OptionAutoTitleBarButtons);
@ -52,36 +49,24 @@ namespace MaterialEditor
QApplication::setWindowIcon(QIcon(":/Icons/materialeditor.svg")); QApplication::setWindowIcon(QIcon(":/Icons/materialeditor.svg"));
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());
}
setObjectName("MaterialEditorWindow"); setObjectName("MaterialEditorWindow");
m_toolBar = new MaterialEditorToolBar(this); m_toolBar = new MaterialEditorToolBar(this);
m_toolBar->setObjectName("ToolBar"); m_toolBar->setObjectName("ToolBar");
addToolBar(m_toolBar); addToolBar(m_toolBar);
m_materialViewport = new MaterialViewportWidget(centralWidget()); m_materialViewport = new MaterialViewportWidget(m_toolId, centralWidget());
m_materialViewport->setObjectName("Viewport"); m_materialViewport->setObjectName("Viewport");
m_materialViewport->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); m_materialViewport->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
centralWidget()->layout()->addWidget(m_materialViewport); centralWidget()->layout()->addWidget(m_materialViewport);
m_assetBrowser->SetFilterState("", AZ::RPI::StreamingImageAsset::Group, true); m_assetBrowser->SetFilterState("", AZ::RPI::StreamingImageAsset::Group, true);
m_assetBrowser->SetFilterState("", AZ::RPI::MaterialAsset::Group, true); m_assetBrowser->SetFilterState("", AZ::RPI::MaterialAsset::Group, true);
m_assetBrowser->SetOpenHandler([](const AZStd::string& absolutePath) { m_assetBrowser->SetOpenHandler([this](const AZStd::string& absolutePath) {
if (AzFramework::StringFunc::Path::IsExtension(absolutePath.c_str(), AZ::RPI::MaterialSourceData::Extension)) if (AzFramework::StringFunc::Path::IsExtension(absolutePath.c_str(), AZ::RPI::MaterialSourceData::Extension))
{ {
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast( AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Event(
&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, absolutePath); m_toolId, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, absolutePath);
return; return;
} }
@ -93,7 +78,7 @@ namespace MaterialEditor
QDesktopServices::openUrl(QUrl::fromLocalFile(absolutePath.c_str())); QDesktopServices::openUrl(QUrl::fromLocalFile(absolutePath.c_str()));
}); });
AddDockWidget("Inspector", new MaterialInspector, Qt::RightDockWidgetArea, Qt::Vertical); AddDockWidget("Inspector", new MaterialInspector(m_toolId), Qt::RightDockWidgetArea, Qt::Vertical);
AddDockWidget("Viewport Settings", new ViewportSettingsInspector, Qt::LeftDockWidgetArea, Qt::Vertical); AddDockWidget("Viewport Settings", new ViewportSettingsInspector, Qt::LeftDockWidgetArea, Qt::Vertical);
SetDockWidgetVisible("Viewport Settings", false); SetDockWidgetVisible("Viewport Settings", false);

@ -32,7 +32,7 @@ namespace MaterialEditor
using Base = AtomToolsFramework::AtomToolsDocumentMainWindow; using Base = AtomToolsFramework::AtomToolsDocumentMainWindow;
MaterialEditorWindow(QWidget* parent = 0); MaterialEditorWindow(const AZ::Crc32& toolId, QWidget* parent = 0);
protected: protected:
void ResizeViewportRenderTarget(uint32_t width, uint32_t height) override; void ResizeViewportRenderTarget(uint32_t width, uint32_t height) override;

@ -15,13 +15,14 @@
namespace MaterialEditor namespace MaterialEditor
{ {
MaterialInspector::MaterialInspector(QWidget* parent) MaterialInspector::MaterialInspector(const AZ::Crc32& toolId, QWidget* parent)
: AtomToolsFramework::InspectorWidget(parent) : AtomToolsFramework::InspectorWidget(parent)
, m_toolId(toolId)
{ {
m_windowSettings = AZ::UserSettings::CreateFind<MaterialEditorWindowSettings>( m_windowSettings = AZ::UserSettings::CreateFind<MaterialEditorWindowSettings>(
AZ::Crc32("MaterialEditorWindowSettings"), AZ::UserSettings::CT_GLOBAL); AZ::Crc32("MaterialEditorWindowSettings"), AZ::UserSettings::CT_GLOBAL);
AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect(); AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect(m_toolId);
} }
MaterialInspector::~MaterialInspector() MaterialInspector::~MaterialInspector()

@ -29,7 +29,7 @@ namespace MaterialEditor
public: public:
AZ_CLASS_ALLOCATOR(MaterialInspector, AZ::SystemAllocator, 0); AZ_CLASS_ALLOCATOR(MaterialInspector, AZ::SystemAllocator, 0);
explicit MaterialInspector(QWidget* parent = nullptr); MaterialInspector(const AZ::Crc32& toolId, QWidget* parent = nullptr);
~MaterialInspector() override; ~MaterialInspector() override;
// AtomToolsFramework::InspectorRequestBus::Handler overrides... // AtomToolsFramework::InspectorRequestBus::Handler overrides...
@ -59,6 +59,8 @@ namespace MaterialEditor
void RequestPropertyContextMenu([[maybe_unused]] AzToolsFramework::InstanceDataNode* pNode, const QPoint&) override {} void RequestPropertyContextMenu([[maybe_unused]] AzToolsFramework::InstanceDataNode* pNode, const QPoint&) override {}
void PropertySelectionChanged([[maybe_unused]] AzToolsFramework::InstanceDataNode* pNode, bool) override {} void PropertySelectionChanged([[maybe_unused]] AzToolsFramework::InstanceDataNode* pNode, bool) override {}
const AZ::Crc32 m_toolId = {};
// Tracking the property that is activiley being edited in the inspector // Tracking the property that is activiley being edited in the inspector
const AtomToolsFramework::DynamicProperty* m_activeProperty = {}; const AtomToolsFramework::DynamicProperty* m_activeProperty = {};

@ -14,8 +14,8 @@
namespace ShaderManagementConsole namespace ShaderManagementConsole
{ {
ShaderManagementConsoleDocument::ShaderManagementConsoleDocument() ShaderManagementConsoleDocument::ShaderManagementConsoleDocument(const AZ::Crc32& toolId)
: AtomToolsFramework::AtomToolsDocument() : AtomToolsFramework::AtomToolsDocument(toolId)
{ {
ShaderManagementConsoleDocumentRequestBus::Handler::BusConnect(m_id); ShaderManagementConsoleDocumentRequestBus::Handler::BusConnect(m_id);
} }
@ -37,8 +37,8 @@ namespace ShaderManagementConsole
AZ_Error("ShaderManagementConsoleDocument", false, "Could not load shader asset: %s.", shaderPath.c_str()); AZ_Error("ShaderManagementConsoleDocument", false, "Could not load shader asset: %s.", shaderPath.c_str());
} }
AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( AtomToolsFramework::AtomToolsDocumentNotificationBus::Event(
&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentModified, m_id); m_toolId, &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentModified, m_id);
} }
const AZ::RPI::ShaderVariantListSourceData& ShaderManagementConsoleDocument::GetShaderVariantListSourceData() const const AZ::RPI::ShaderVariantListSourceData& ShaderManagementConsoleDocument::GetShaderVariantListSourceData() const

@ -24,11 +24,11 @@ namespace ShaderManagementConsole
, public ShaderManagementConsoleDocumentRequestBus::Handler , public ShaderManagementConsoleDocumentRequestBus::Handler
{ {
public: public:
AZ_RTTI(ShaderManagementConsoleDocument, "{DBA269AE-892B-415C-8FA1-166B94B0E045}"); AZ_RTTI(ShaderManagementConsoleDocument, "{504A74BA-F5DD-49E0-BA5E-A381F61DD524}");
AZ_CLASS_ALLOCATOR(ShaderManagementConsoleDocument, AZ::SystemAllocator, 0); AZ_CLASS_ALLOCATOR(ShaderManagementConsoleDocument, AZ::SystemAllocator, 0);
AZ_DISABLE_COPY(ShaderManagementConsoleDocument); AZ_DISABLE_COPY_MOVE(ShaderManagementConsoleDocument);
ShaderManagementConsoleDocument(); ShaderManagementConsoleDocument(const AZ::Crc32& toolId);
~ShaderManagementConsoleDocument(); ~ShaderManagementConsoleDocument();
// AtomToolsFramework::AtomToolsDocument overrides... // AtomToolsFramework::AtomToolsDocument overrides...

@ -47,27 +47,29 @@ void InitShaderManagementConsoleResources()
namespace ShaderManagementConsole namespace ShaderManagementConsole
{ {
static const char* GetBuildTargetName()
{
#if !defined(LY_CMAKE_TARGET)
#error "LY_CMAKE_TARGET must be defined in order to add this source file to a CMake executable target"
#endif
return LY_CMAKE_TARGET;
}
ShaderManagementConsoleApplication::ShaderManagementConsoleApplication(int* argc, char*** argv) ShaderManagementConsoleApplication::ShaderManagementConsoleApplication(int* argc, char*** argv)
: Base(argc, argv) : Base(GetBuildTargetName(), argc, argv)
{ {
InitShaderManagementConsoleResources(); InitShaderManagementConsoleResources();
QApplication::setApplicationName("O3DE Shader Management Console"); QApplication::setApplicationName("O3DE Shader Management Console");
// The settings registry has been created at this point, so add the CMake target
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddBuildSystemTargetSpecialization(
*AZ::SettingsRegistry::Get(), GetBuildTargetName());
ShaderManagementConsoleRequestBus::Handler::BusConnect(); ShaderManagementConsoleRequestBus::Handler::BusConnect();
AzToolsFramework::EditorWindowRequestBus::Handler::BusConnect(); AzToolsFramework::EditorWindowRequestBus::Handler::BusConnect();
AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Handler::BusConnect();
} }
ShaderManagementConsoleApplication::~ShaderManagementConsoleApplication() ShaderManagementConsoleApplication::~ShaderManagementConsoleApplication()
{ {
ShaderManagementConsoleRequestBus::Handler::BusDisconnect(); ShaderManagementConsoleRequestBus::Handler::BusDisconnect();
AzToolsFramework::EditorWindowRequestBus::Handler::BusDisconnect(); AzToolsFramework::EditorWindowRequestBus::Handler::BusDisconnect();
AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Handler::BusDisconnect();
m_window.reset(); m_window.reset();
} }
@ -115,40 +117,20 @@ namespace ShaderManagementConsole
{ {
Base::StartCommon(systemEntity); Base::StartCommon(systemEntity);
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast( AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Event(
&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Handler::RegisterDocumentType, m_toolId, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Handler::RegisterDocumentType,
[]() { return aznew ShaderManagementConsoleDocument(); }); [](const AZ::Crc32& toolId) { return aznew ShaderManagementConsoleDocument(toolId); });
}
AZStd::string ShaderManagementConsoleApplication::GetBuildTargetName() const
{
#if !defined(LY_CMAKE_TARGET)
#error "LY_CMAKE_TARGET must be defined in order to add this source file to a CMake executable target"
#endif
//! Returns the build system target name of "ShaderManagementConsole"
return AZStd::string_view{ LY_CMAKE_TARGET };
}
AZStd::vector<AZStd::string> ShaderManagementConsoleApplication::GetCriticalAssetFilters() const
{
return AZStd::vector<AZStd::string>({ "passes/", "config/" });
}
QWidget* ShaderManagementConsoleApplication::GetAppMainWindow() m_window.reset(aznew ShaderManagementConsoleWindow(m_toolId));
{
return m_window.get();
}
void ShaderManagementConsoleApplication::CreateMainWindow()
{
m_window.reset(aznew ShaderManagementConsoleWindow);
m_assetBrowserInteractions.reset(aznew AtomToolsFramework::AtomToolsAssetBrowserInteractions); m_assetBrowserInteractions.reset(aznew AtomToolsFramework::AtomToolsAssetBrowserInteractions);
m_assetBrowserInteractions->RegisterContextMenuActions( m_assetBrowserInteractions->RegisterContextMenuActions(
[](const AtomToolsFramework::AtomToolsAssetBrowserInteractions::AssetBrowserEntryVector& entries) [](const AtomToolsFramework::AtomToolsAssetBrowserInteractions::AssetBrowserEntryVector& entries)
{ {
return entries.front()->GetEntryType() == AzToolsFramework::AssetBrowser::AssetBrowserEntry::AssetEntryType::Source; return entries.front()->GetEntryType() == AzToolsFramework::AssetBrowser::AssetBrowserEntry::AssetEntryType::Source;
}, },
[]([[maybe_unused]] QWidget* caller, QMenu* menu, const AtomToolsFramework::AtomToolsAssetBrowserInteractions::AssetBrowserEntryVector& entries) [this]([[maybe_unused]] QWidget* caller, QMenu* menu, const AtomToolsFramework::AtomToolsAssetBrowserInteractions::AssetBrowserEntryVector& entries)
{ {
if (AzFramework::StringFunc::Path::IsExtension( if (AzFramework::StringFunc::Path::IsExtension(
entries.front()->GetFullPath().c_str(), AZ::RPI::ShaderSourceData::Extension)) entries.front()->GetFullPath().c_str(), AZ::RPI::ShaderSourceData::Extension))
@ -166,10 +148,10 @@ namespace ShaderManagementConsole
else if (AzFramework::StringFunc::Path::IsExtension( else if (AzFramework::StringFunc::Path::IsExtension(
entries.front()->GetFullPath().c_str(), AZ::RPI::ShaderVariantListSourceData::Extension)) entries.front()->GetFullPath().c_str(), AZ::RPI::ShaderVariantListSourceData::Extension))
{ {
menu->addAction(QObject::tr("Open"), [entries]() menu->addAction(QObject::tr("Open"), [entries, this]()
{ {
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast( AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Event(
&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, m_toolId, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument,
entries.front()->GetFullPath()); entries.front()->GetFullPath());
}); });
} }
@ -183,9 +165,20 @@ namespace ShaderManagementConsole
}); });
} }
void ShaderManagementConsoleApplication::DestroyMainWindow() void ShaderManagementConsoleApplication::Destroy()
{ {
m_window.reset(); m_window.reset();
Base::Destroy();
}
AZStd::vector<AZStd::string> ShaderManagementConsoleApplication::GetCriticalAssetFilters() const
{
return AZStd::vector<AZStd::string>({ "passes/", "config/" });
}
QWidget* ShaderManagementConsoleApplication::GetAppMainWindow()
{
return m_window.get();
} }
AZ::Data::AssetInfo ShaderManagementConsoleApplication::GetSourceAssetInfo(const AZStd::string& sourceAssetFileName) AZ::Data::AssetInfo ShaderManagementConsoleApplication::GetSourceAssetInfo(const AZStd::string& sourceAssetFileName)

@ -11,7 +11,6 @@
#include <Atom/RPI.Reflect/Material/MaterialAsset.h> #include <Atom/RPI.Reflect/Material/MaterialAsset.h>
#include <AtomToolsFramework/AssetBrowser/AtomToolsAssetBrowserInteractions.h> #include <AtomToolsFramework/AssetBrowser/AtomToolsAssetBrowserInteractions.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentApplication.h> #include <AtomToolsFramework/Document/AtomToolsDocumentApplication.h>
#include <AtomToolsFramework/Window/AtomToolsMainWindowFactoryRequestBus.h>
#include <AzToolsFramework/API/EditorWindowRequestBus.h> #include <AzToolsFramework/API/EditorWindowRequestBus.h>
#include <ShaderManagementConsoleRequestBus.h> #include <ShaderManagementConsoleRequestBus.h>
#include <Window/ShaderManagementConsoleWindow.h> #include <Window/ShaderManagementConsoleWindow.h>
@ -21,7 +20,6 @@ namespace ShaderManagementConsole
class ShaderManagementConsoleApplication class ShaderManagementConsoleApplication
: public AtomToolsFramework::AtomToolsDocumentApplication : public AtomToolsFramework::AtomToolsDocumentApplication
, private ShaderManagementConsoleRequestBus::Handler , private ShaderManagementConsoleRequestBus::Handler
, private AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Handler
, private AzToolsFramework::EditorWindowRequestBus::Handler , private AzToolsFramework::EditorWindowRequestBus::Handler
{ {
public: public:
@ -36,18 +34,14 @@ namespace ShaderManagementConsole
void Reflect(AZ::ReflectContext* context) override; void Reflect(AZ::ReflectContext* context) override;
const char* GetCurrentConfigurationName() const override; const char* GetCurrentConfigurationName() const override;
void StartCommon(AZ::Entity* systemEntity) override; void StartCommon(AZ::Entity* systemEntity) override;
void Destroy() override;
// AtomToolsFramework::AtomToolsApplication overrides... // AtomToolsFramework::AtomToolsApplication overrides...
AZStd::string GetBuildTargetName() const override;
AZStd::vector<AZStd::string> GetCriticalAssetFilters() const override; AZStd::vector<AZStd::string> GetCriticalAssetFilters() const override;
// AzToolsFramework::EditorWindowRequests::Bus::Handler // AzToolsFramework::EditorWindowRequests::Bus::Handler
QWidget* GetAppMainWindow() override; QWidget* GetAppMainWindow() override;
// AtomToolsMainWindowFactoryRequestBus::Handler overrides...
void CreateMainWindow() override;
void DestroyMainWindow() override;
// ShaderManagementConsoleRequestBus::Handler overrides... // ShaderManagementConsoleRequestBus::Handler overrides...
AZ::Data::AssetInfo GetSourceAssetInfo(const AZStd::string& sourceAssetFileName) override; AZ::Data::AssetInfo GetSourceAssetInfo(const AZStd::string& sourceAssetFileName) override;
AZStd::vector<AZ::Data::AssetId> FindMaterialAssetsUsingShader(const AZStd::string& shaderFilePath) override; AZStd::vector<AZ::Data::AssetId> FindMaterialAssetsUsingShader(const AZStd::string& shaderFilePath) override;

@ -26,11 +26,9 @@ AZ_POP_DISABLE_WARNING
namespace ShaderManagementConsole namespace ShaderManagementConsole
{ {
ShaderManagementConsoleWindow::ShaderManagementConsoleWindow(QWidget* parent /* = 0 */) ShaderManagementConsoleWindow::ShaderManagementConsoleWindow(const AZ::Crc32& toolId, QWidget* parent)
: Base(parent) : Base(toolId, parent)
{ {
resize(1280, 1024);
// Among other things, we need the window wrapper to save the main window size, position, and state // Among other things, we need the window wrapper to save the main window size, position, and state
auto mainWindowWrapper = auto mainWindowWrapper =
new AzQtComponents::WindowDecorationWrapper(AzQtComponents::WindowDecorationWrapper::OptionAutoTitleBarButtons); new AzQtComponents::WindowDecorationWrapper(AzQtComponents::WindowDecorationWrapper::OptionAutoTitleBarButtons);
@ -42,11 +40,11 @@ namespace ShaderManagementConsole
setObjectName("ShaderManagementConsoleWindow"); setObjectName("ShaderManagementConsoleWindow");
m_assetBrowser->SetFilterState("", AZ::RPI::ShaderAsset::Group, true); m_assetBrowser->SetFilterState("", AZ::RPI::ShaderAsset::Group, true);
m_assetBrowser->SetOpenHandler([](const AZStd::string& absolutePath) { m_assetBrowser->SetOpenHandler([this](const AZStd::string& absolutePath) {
if (AzFramework::StringFunc::Path::IsExtension(absolutePath.c_str(), AZ::RPI::ShaderVariantListSourceData::Extension)) if (AzFramework::StringFunc::Path::IsExtension(absolutePath.c_str(), AZ::RPI::ShaderVariantListSourceData::Extension))
{ {
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast( AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Event(
&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, absolutePath); m_toolId, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, absolutePath);
return; return;
} }

@ -31,7 +31,7 @@ namespace ShaderManagementConsole
using Base = AtomToolsFramework::AtomToolsDocumentMainWindow; using Base = AtomToolsFramework::AtomToolsDocumentMainWindow;
ShaderManagementConsoleWindow(QWidget* parent = 0); ShaderManagementConsoleWindow(const AZ::Crc32& toolId, QWidget* parent = 0);
~ShaderManagementConsoleWindow() = default; ~ShaderManagementConsoleWindow() = default;
protected: protected:

Loading…
Cancel
Save