Ver Fonte

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 <[email protected]>

Guthrie Adams há 3 anos atrás
pai
commit
c6ba1ef064
39 ficheiros alterados com 554 adições e 602 exclusões
  1. 3 3
      AutomatedTesting/Gem/PythonTests/Atom/atom_utils/material_editor_utils.py
  2. 1 1
      AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomMaterialEditor_BasicTests.py
  3. 7 22
      Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h
  4. 5 3
      Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocument.h
  5. 10 2
      Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentApplication.h
  6. 1 1
      Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentMainWindow.h
  7. 2 1
      Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h
  8. 25 43
      Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentSystem.h
  9. 7 4
      Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h
  10. 4 1
      Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h
  11. 0 30
      Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowFactoryRequestBus.h
  12. 2 1
      Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowNotificationBus.h
  13. 6 3
      Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h
  14. 63 72
      Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp
  15. 23 18
      Gems/Atom/Tools/AtomToolsFramework/Code/Source/AssetBrowser/AtomToolsAssetBrowser.cpp
  16. 0 3
      Gems/Atom/Tools/AtomToolsFramework/Code/Source/AtomToolsFrameworkModule.cpp
  17. 25 24
      Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp
  18. 22 4
      Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentApplication.cpp
  19. 31 23
      Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentMainWindow.cpp
  20. 175 173
      Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystem.cpp
  21. 33 14
      Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp
  22. 0 9
      Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindowSystemComponent.cpp
  23. 2 3
      Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake
  24. 8 8
      Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp
  25. 2 2
      Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h
  26. 32 39
      Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp
  27. 1 7
      Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h
  28. 3 2
      Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportWidget.cpp
  29. 3 1
      Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportWidget.h
  30. 7 22
      Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp
  31. 1 1
      Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h
  32. 3 2
      Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.cpp
  33. 3 1
      Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.h
  34. 4 4
      Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.cpp
  35. 3 3
      Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.h
  36. 30 37
      Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp
  37. 1 7
      Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h
  38. 5 7
      Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp
  39. 1 1
      Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h

+ 3 - 3
AutomatedTesting/Gem/PythonTests/Atom/atom_utils/material_editor_utils.py

@@ -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):

+ 1 - 1
AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomMaterialEditor_BasicTests.py

@@ -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__":

+ 7 - 22
Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h

@@ -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
+        // AzFramework::Application overrides...
         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

+ 5 - 3
Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocument.h

@@ -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;

+ 10 - 2
Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentApplication.h

@@ -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

+ 1 - 1
Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentMainWindow.h

@@ -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:

+ 2 - 1
Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h

@@ -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

+ 25 - 43
Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.h → Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentSystem.h

@@ -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>
-
-AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
-#include <QFileInfo>
-#include <QString>
-AZ_POP_DISABLE_WARNING
+#include <AzCore/Asset/AssetCommon.h>
+#include <AzCore/Memory/Memory.h>
+#include <AzCore/RTTI/RTTI.h>
+#include <AzCore/std/smart_ptr/shared_ptr.h>
 
 
 namespace AtomToolsFramework
 namespace AtomToolsFramework
 {
 {
-    //! AtomToolsDocumentSystemComponent is the central component for managing documents
-    class AtomToolsDocumentSystemComponent
-        : public AZ::Component
-        , private AtomToolsDocumentNotificationBus::Handler
-        , private AtomToolsDocumentSystemRequestBus::Handler
+    //! AtomToolsDocumentSystem Is responsible for creation, management, and requests related to documents
+    class AtomToolsDocumentSystem
+        : public AtomToolsDocumentNotificationBus::Handler
+        , public AtomToolsDocumentSystemRequestBus::Handler
     {
     {
     public:
     public:
-        AZ_COMPONENT(AtomToolsDocumentSystemComponent, "{343A3383-6A59-4343-851B-BF84FC6CB18E}");
-
-        AtomToolsDocumentSystemComponent();
-        ~AtomToolsDocumentSystemComponent() = default;
-        AtomToolsDocumentSystemComponent(const AtomToolsDocumentSystemComponent&) = delete;
-        AtomToolsDocumentSystemComponent& operator=(const AtomToolsDocumentSystemComponent&) = delete;
+        AZ_CLASS_ALLOCATOR(AtomToolsFramework::AtomToolsDocumentSystem, AZ::SystemAllocator, 0);
+        AZ_RTTI(AtomToolsFramework::AtomToolsDocumentSystem, "{9D31F309-6B20-40C5-813C-F1226180E1F8}");
+        AZ_DISABLE_COPY_MOVE(AtomToolsDocumentSystem);
 
 
         static void Reflect(AZ::ReflectContext* context);
         static void Reflect(AZ::ReflectContext* context);
 
 
-        static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
-        static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
-
-    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();
+        AtomToolsDocumentSystem() = default;
+        AtomToolsDocumentSystem(const AZ::Crc32& toolId);
+        ~AtomToolsDocumentSystem();
 
 
-        ////////////////////////////////////////////////////////////////////////
         // 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;

+ 7 - 4
Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h

@@ -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::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
+        static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
+        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

+ 4 - 1
Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h

@@ -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 = {};
 
 

+ 0 - 30
Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowFactoryRequestBus.h

@@ -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

+ 2 - 1
Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowNotificationBus.h

@@ -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(){};
     };
     };

+ 6 - 3
Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h

@@ -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::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
+        static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
+        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

+ 63 - 72
Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp

@@ -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
-    {
-        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)
+    AtomToolsApplication::AtomToolsApplication(const AZStd::string& targetName, 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_loggingCallback = [targetName]([[maybe_unused]] AZStd::string_view logData)
+        connectionSettings.m_connectionIdentifier = m_targetName;
+        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(
-                &AtomToolsFramework::AtomToolsMainWindowRequestBus::Handler::ActivateWindow);
+            AtomToolsMainWindowRequestBus::Event(m_toolId, &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);
-            QTimer::singleShot(
-                timeoutInMs,
-                [this]
-                {
-                    AZ_Printf(GetBuildTargetName().c_str(), "Timeout reached, shutting down");
-                    ExitMainLoop();
-                });
+            AZ_Printf(m_targetName.c_str(), "Timeout scheduled, shutting down in %u ms", timeoutInMs);
+            QTimer::singleShot(timeoutInMs, [this] {
+                AZ_Printf(m_targetName.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

+ 23 - 18
Gems/Atom/Tools/AtomToolsFramework/Code/Source/AssetBrowser/AtomToolsAssetBrowser.cpp

@@ -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
-            AzToolsFramework::AssetBrowser::AssetBrowserViewRequestBus::Broadcast(
-                &AzToolsFramework::AssetBrowser::AssetBrowserViewRequestBus::Events::SelectFileAtPath, m_pathToSelect);
+            AZ::TickBus::Handler::BusDisconnect();
+            m_pathToSelect.clear();
+            return;
+        }
 
 
-            // Iterate over the selected entries to verify if the selection was made
-            for (const AssetBrowserEntry* entry : m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets())
+        // Attempt to select the new path
+        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();
-                    AzFramework::StringFunc::Path::Normalize(sourcePath);
-                    if (m_pathToSelect == sourcePath)
-                    {
-                        // Once the selection is confirmed, cancel the operation and disconnect
-                        AZ::TickBus::Handler::BusDisconnect();
-                        m_pathToSelect.clear();
-                    }
+                    // Once the selection is confirmed, cancel the operation and disconnect
+                    AZ::TickBus::Handler::BusDisconnect();
+                    m_pathToSelect.clear();
                 }
                 }
             }
             }
         }
         }

+ 0 - 3
Gems/Atom/Tools/AtomToolsFramework/Code/Source/AtomToolsFrameworkModule.cpp

@@ -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>(),

+ 25 - 24
Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp

@@ -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::Broadcast(&AtomToolsDocumentNotificationBus::Events::OnDocumentDestroyed, m_id);
+        AtomToolsDocumentNotificationBus::Event(m_toolId, &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::Events::OnDocumentModified, m_id);
-        AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(
-            &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id);
+        AtomToolsFramework::AtomToolsDocumentNotificationBus::Event(
+            m_toolId, &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentModified, m_id);
+        AtomToolsFramework::AtomToolsDocumentNotificationBus::Event(
+            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::Events::OnDocumentClosed, m_id);
+        AtomToolsFramework::AtomToolsDocumentNotificationBus::Event(
+            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::Events::OnDocumentUndoStateChanged, m_id);
+            AtomToolsFramework::AtomToolsDocumentNotificationBus::Event(
+                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::Events::OnDocumentUndoStateChanged, m_id);
+            AtomToolsFramework::AtomToolsDocumentNotificationBus::Event(
+                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::Events::OnDocumentOpened, m_id);
+        AtomToolsFramework::AtomToolsDocumentNotificationBus::Event(
+            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::Events::OnDocumentSaved, m_id);
+        AtomToolsFramework::AtomToolsDocumentNotificationBus::Event(
+            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::Events::OnDocumentUndoStateChanged, m_id);
+        AtomToolsFramework::AtomToolsDocumentNotificationBus::Event(
+            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::Events::OnDocumentExternallyModified, m_id);
+                AtomToolsFramework::AtomToolsDocumentNotificationBus::Event(
+                    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::Events::OnDocumentDependencyModified, m_id);
+            AtomToolsFramework::AtomToolsDocumentNotificationBus::Event(
+                m_toolId, &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentDependencyModified, m_id);
         }
         }
     }
     }
 
 

+ 22 - 4
Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentApplication.cpp

@@ -11,11 +11,29 @@
 
 
 namespace AtomToolsFramework
 namespace AtomToolsFramework
 {
 {
-    AtomToolsDocumentApplication::AtomToolsDocumentApplication(int* argc, char*** argv)
-        : Base(argc, argv)
+    AtomToolsDocumentApplication::AtomToolsDocumentApplication(const AZStd::string& targetName, int* argc, char*** 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());
-            AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath);
+            AZ_Printf(m_targetName.c_str(), "Opening document: %s", openDocumentPath.c_str());
+            AtomToolsDocumentSystemRequestBus::Event(m_toolId, &AtomToolsDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath);
         }
         }
 
 
         Base::ProcessCommandLine(commandLine);
         Base::ProcessCommandLine(commandLine);

+ 31 - 23
Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentMainWindow.cpp

@@ -25,13 +25,13 @@ AZ_POP_DISABLE_WARNING
 
 
 namespace AtomToolsFramework
 namespace AtomToolsFramework
 {
 {
-    AtomToolsDocumentMainWindow::AtomToolsDocumentMainWindow(QWidget* parent /* = 0 */)
-        : AtomToolsMainWindow(parent)
+    AtomToolsDocumentMainWindow::AtomToolsDocumentMainWindow(const AZ::Crc32& toolId, QWidget* parent /* = 0 */)
+        : 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::Events::CreateDocumentFromFile, openPath, savePath);
+                AtomToolsDocumentSystemRequestBus::Event(
+                    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,
-                documentId, GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData());
+            AtomToolsDocumentSystemRequestBus::EventResult(
+                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,
-                documentId, GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData());
+            AtomToolsDocumentSystemRequestBus::EventResult(
+                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", []() {
-            AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::CloseAllDocuments);
+        m_actionCloseAll = CreateAction("Close All", [this]() {
+            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>

+ 175 - 173
Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp → Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystem.cpp

@@ -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)
     {
     {
-    }
-
-    void AtomToolsDocumentSystemComponent::Reflect(AZ::ReflectContext* context)
-    {
-        if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
+        if (auto 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)
-    {
-        provided.push_back(AZ_CRC_CE("AtomToolsDocumentSystemService"));
-    }
-
-    void AtomToolsDocumentSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
+    AtomToolsDocumentSystem::AtomToolsDocumentSystem(const AZ::Crc32& toolId)
+        : m_toolId(toolId)
     {
     {
-        incompatible.push_back(AZ_CRC_CE("AtomToolsDocumentSystemService"));
+        AtomToolsDocumentSystemRequestBus::Handler::BusConnect(m_toolId);
+        AtomToolsDocumentNotificationBus::Handler::BusConnect(m_toolId);
     }
     }
 
 
-    void AtomToolsDocumentSystemComponent::Init()
-    {
-    }
-
-    void AtomToolsDocumentSystemComponent::Activate()
+    AtomToolsDocumentSystem::~AtomToolsDocumentSystem()
     {
     {
         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)
-    {
-        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)
+    AZ::Uuid AtomToolsDocumentSystem::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"),
-                QString("Do you want to save changes to\n%1?").arg(documentPath.c_str()),
+                QObject::tr("Document has unsaved changes"),
+                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"),
-                QString("Failed to close: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str()));
+                QApplication::activeWindow(),
+                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"),
-                QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str()));
+                QApplication::activeWindow(),
+                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"),
-                QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str()));
+                QApplication::activeWindow(),
+                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"),
-                QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str()));
+                QApplication::activeWindow(),
+                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();
-        AtomToolsDocumentSystemRequestBus::BroadcastResult(documentId, &AtomToolsDocumentSystemRequestBus::Events::CreateDocument);
+        AZ::Uuid documentId = CreateDocument();
         if (documentId.IsNull())
         if (documentId.IsNull())
         {
         {
             QMessageBox::critical(
             QMessageBox::critical(
-                QApplication::activeWindow(), QString("Document could not be created"),
-                QString("Failed to create: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str()));
+                QApplication::activeWindow(),
+                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"),
-                QString("Failed to open: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str()));
-            AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::DestroyDocument, documentId);
+                QApplication::activeWindow(),
+                QObject::tr("Document could not be opened"),
+                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"),
-                QString("Warnings encountered: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str()));
+                QApplication::activeWindow(),
+                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

+ 33 - 14
Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp

@@ -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(
-            &AtomToolsFramework::PerformanceMonitorRequestBus::Handler::SetProfilerEnabled, false);
+        PerformanceMonitorRequestBus::Broadcast(&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(
-            &AtomToolsFramework::PerformanceMonitorRequestBus::Handler::SetProfilerEnabled, true);
+        PerformanceMonitorRequestBus::Broadcast(&PerformanceMonitorRequestBus::Handler::SetProfilerEnabled, true);
 
 
         UpdateMetrics();
         UpdateMetrics();
     }
     }
 
 
     void AtomToolsMainWindow::UpdateMetrics()
     void AtomToolsMainWindow::UpdateMetrics()
     {
     {
-        AtomToolsFramework::PerformanceMetrics metrics = {};
-        AtomToolsFramework::PerformanceMonitorRequestBus::BroadcastResult(
-            metrics, &AtomToolsFramework::PerformanceMonitorRequestBus::Handler::GetMetrics);
+        PerformanceMetrics metrics = {};
+        PerformanceMonitorRequestBus::BroadcastResult(metrics, &PerformanceMonitorRequestBus::Handler::GetMetrics);
 
 
         m_statusBarCpuTime->setText(tr("CPU Time %1 ms").arg(QString::number(metrics.m_cpuFrameTimeMs, 'f', 2)));
         m_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

+ 0 - 9
Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindowSystemComponent.cpp

@@ -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")

+ 2 - 3
Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake

@@ -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/AtomToolsDocumentSystemComponent.h
+    Source/Document/AtomToolsDocumentSystem.cpp
     Source/DynamicProperty/DynamicProperty.cpp
     Source/DynamicProperty/DynamicProperty.cpp
     Source/DynamicProperty/DynamicPropertyGroup.cpp
     Source/DynamicProperty/DynamicPropertyGroup.cpp
     Source/Inspector/InspectorWidget.cpp
     Source/Inspector/InspectorWidget.cpp

+ 8 - 8
Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp

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

+ 2 - 2
Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h

@@ -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...

+ 32 - 39
Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp

@@ -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::Handler::RegisterDocumentType,
-            []() { return aznew MaterialDocument(); });
-    }
-
-    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 };
-    }
+        AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Event(
+            m_toolId, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Handler::RegisterDocumentType,
+            [](const AZ::Crc32& toolId) { return aznew MaterialDocument(toolId); });
 
 
-    AZStd::vector<AZStd::string> MaterialEditorApplication::GetCriticalAssetFilters() const
-    {
-        return AZStd::vector<AZStd::string>({ "passes/", "config/", "MaterialEditor/" });
-    }
+        m_window.reset(aznew MaterialEditorWindow(m_toolId));
 
 
-    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::Events::OpenDocument,
+                            AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Event(
+                                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::Events::CreateDocumentFromFile,
+                            AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Event(
+                                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::Events::CreateDocumentFromFile,
+                            AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Event(
+                                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()

+ 1 - 7
Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h

@@ -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;
 
 

+ 3 - 2
Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportWidget.cpp

@@ -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());

+ 3 - 1
Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportWidget.h

@@ -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;

+ 7 - 22
Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp

@@ -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 */)
-        : Base(parent)
+    MaterialEditorWindow::MaterialEditorWindow(const AZ::Crc32& toolId, QWidget* 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::Events::OpenDocument, absolutePath);
+                AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Event(
+                    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);
 
 

+ 1 - 1
Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h

@@ -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;

+ 3 - 2
Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.cpp

@@ -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()

+ 3 - 1
Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.h

@@ -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 = {};
 
 

+ 4 - 4
Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.cpp

@@ -14,8 +14,8 @@
 
 
 namespace ShaderManagementConsole
 namespace ShaderManagementConsole
 {
 {
-    ShaderManagementConsoleDocument::ShaderManagementConsoleDocument()
-        : AtomToolsFramework::AtomToolsDocument()
+    ShaderManagementConsoleDocument::ShaderManagementConsoleDocument(const AZ::Crc32& toolId)
+        : 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::Events::OnDocumentModified, m_id);
+        AtomToolsFramework::AtomToolsDocumentNotificationBus::Event(
+            m_toolId, &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentModified, m_id);
     }
     }
 
 
     const AZ::RPI::ShaderVariantListSourceData& ShaderManagementConsoleDocument::GetShaderVariantListSourceData() const
     const AZ::RPI::ShaderVariantListSourceData& ShaderManagementConsoleDocument::GetShaderVariantListSourceData() const

+ 3 - 3
Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.h

@@ -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...

+ 30 - 37
Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp

@@ -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::Handler::RegisterDocumentType,
-            []() { return aznew ShaderManagementConsoleDocument(); });
-    }
-
-    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/" });
-    }
+        AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Event(
+            m_toolId, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Handler::RegisterDocumentType,
+            [](const AZ::Crc32& toolId) { return aznew ShaderManagementConsoleDocument(toolId); });
 
 
-    QWidget* ShaderManagementConsoleApplication::GetAppMainWindow()
-    {
-        return m_window.get();
-    }
+        m_window.reset(aznew ShaderManagementConsoleWindow(m_toolId));
 
 
-    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::Events::OpenDocument,
+                            AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Event(
+                                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)

+ 1 - 7
Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h

@@ -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;

+ 5 - 7
Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp

@@ -26,11 +26,9 @@ AZ_POP_DISABLE_WARNING
 
 
 namespace ShaderManagementConsole
 namespace ShaderManagementConsole
 {
 {
-    ShaderManagementConsoleWindow::ShaderManagementConsoleWindow(QWidget* parent /* = 0 */)
-        : Base(parent)
+    ShaderManagementConsoleWindow::ShaderManagementConsoleWindow(const AZ::Crc32& toolId, QWidget* 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::Events::OpenDocument, absolutePath);
+                AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Event(
+                    m_toolId, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, absolutePath);
                 return;
                 return;
             }
             }
 
 

+ 1 - 1
Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h

@@ -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: