ソースを参照

ScriptCanvas breakpoint support : Make scriptcanvas a standalone application (#18722)

* Standalone script canvas

Signed-off-by: guillaume-haerinck <[email protected]>

* Basic working logger

Signed-off-by: guillaume-haerinck <[email protected]>

* Open from asset browser double click

Signed-off-by: guillaume-haerinck <[email protected]>

* Fix linux and other platform build

Signed-off-by: guillaume-haerinck <[email protected]>

* Second linux fix

Signed-off-by: guillaume-haerinck <[email protected]>

* Node palette draw lint background before text

Signed-off-by: guillaume-haerinck <[email protected]>

* Populate node model when asset browser is ready to catch scriptevents

Signed-off-by: guillaume-haerinck <[email protected]>

* Only init window when asset browser is ready

Signed-off-by: guillaume-haerinck <[email protected]>

* Hide unsuported button for now

Signed-off-by: guillaume-haerinck <[email protected]>

* Fix linux nounity build

Signed-off-by: guillaume-haerinck <[email protected]>

---------

Signed-off-by: guillaume-haerinck <[email protected]>
Guillaume Haerinck 3 週間 前
コミット
0c90356787
49 ファイル変更853 行追加533 行削除
  1. 0 1
      Code/Editor/LyViewPaneNames.h
  2. 5 0
      Code/Framework/AzCore/AzCore/Component/ComponentApplicationBus.h
  3. 11 4
      Code/Framework/AzFramework/AzFramework/Application/Application.cpp
  4. 5 0
      Code/Framework/AzFramework/AzFramework/Script/ScriptRemoteDebuggingConstants.h
  5. 4 0
      Code/Tools/AssetProcessor/AssetBuilder/AssetBuilderApplication.h
  6. 5 0
      Code/Tools/AssetProcessor/AssetBuilder/Platform/Linux/AssetBuilderApplication_linux.cpp
  7. 5 0
      Code/Tools/AssetProcessor/AssetBuilder/Platform/Mac/AssetBuilderApplication_mac.cpp
  8. 5 0
      Code/Tools/AssetProcessor/AssetBuilder/Platform/Windows/AssetBuilderApplication_windows.cpp
  9. 21 21
      Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/NodePalette/NodePaletteWidget.cpp
  10. 50 0
      Gems/ScriptCanvas/Code/Application/Document/ScriptCanvasDocument.cpp
  11. 36 0
      Gems/ScriptCanvas/Code/Application/Document/ScriptCanvasDocument.h
  12. 20 0
      Gems/ScriptCanvas/Code/Application/Document/ScriptCanvasDocumentRequestBus.h
  13. 10 0
      Gems/ScriptCanvas/Code/Application/Platform/Android/platform_android_files.cmake
  14. 10 0
      Gems/ScriptCanvas/Code/Application/Platform/Linux/platform_linux_files.cmake
  15. 10 0
      Gems/ScriptCanvas/Code/Application/Platform/Mac/platform_mac_files.cmake
  16. 3 0
      Gems/ScriptCanvas/Code/Application/Platform/Windows/ScriptCanvasApplication.ico
  17. 1 0
      Gems/ScriptCanvas/Code/Application/Platform/Windows/ScriptCanvasApplication.rc
  18. 11 0
      Gems/ScriptCanvas/Code/Application/Platform/Windows/platform_windows_files.cmake
  19. 10 0
      Gems/ScriptCanvas/Code/Application/Platform/iOS/platform_ios_files.cmake
  20. 18 0
      Gems/ScriptCanvas/Code/Application/Resources/application.svg
  21. 103 0
      Gems/ScriptCanvas/Code/Application/ScriptCanvasApplication.cpp
  22. 48 0
      Gems/ScriptCanvas/Code/Application/ScriptCanvasApplication.h
  23. 5 0
      Gems/ScriptCanvas/Code/Application/ScriptCanvasApplicationResources.qrc
  24. 28 0
      Gems/ScriptCanvas/Code/Application/main.cpp
  25. 1 2
      Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderDataSystem.cpp
  26. 57 0
      Gems/ScriptCanvas/Code/CMakeLists.txt
  27. 4 12
      Gems/ScriptCanvas/Code/Editor/Framework/Configuration.cpp
  28. 3 0
      Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Bus/ScriptCanvasBus.h
  29. 94 62
      Gems/ScriptCanvas/Code/Editor/SystemComponent.cpp
  30. 3 6
      Gems/ScriptCanvas/Code/Editor/SystemComponent.h
  31. 11 60
      Gems/ScriptCanvas/Code/Editor/View/Widgets/LoggingPanel/LiveWindowSession/LiveLoggingDataAggregator.cpp
  32. 0 7
      Gems/ScriptCanvas/Code/Editor/View/Widgets/LoggingPanel/LiveWindowSession/LiveLoggingDataAggregator.h
  33. 6 71
      Gems/ScriptCanvas/Code/Editor/View/Widgets/LoggingPanel/LiveWindowSession/LiveLoggingWindowSession.cpp
  34. 3 11
      Gems/ScriptCanvas/Code/Editor/View/Widgets/LoggingPanel/LiveWindowSession/LiveLoggingWindowSession.h
  35. 3 2
      Gems/ScriptCanvas/Code/Editor/View/Widgets/ScriptCanvasNodePaletteDockWidget.cpp
  36. 1 1
      Gems/ScriptCanvas/Code/Editor/View/Widgets/ScriptCanvasNodePaletteDockWidget.h
  37. 0 3
      Gems/ScriptCanvas/Code/Editor/View/Widgets/UnitTestPanel/UnitTestDockWidget.cpp
  38. 43 4
      Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp
  39. 19 1
      Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h
  40. 0 9
      Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/API.cpp
  41. 0 1
      Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/API.h
  42. 3 10
      Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/Bus.h
  43. 139 186
      Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/ClientTransceiver.cpp
  44. 13 33
      Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/ClientTransceiver.h
  45. 7 6
      Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/Debugger.cpp
  46. 2 1
      Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/Debugger.h
  47. 0 18
      Gems/ScriptCanvas/Code/Include/ScriptCanvas/Utils/ScriptCanvasConstants.h
  48. 17 0
      Gems/ScriptCanvas/Code/scriptcanvasgem_application_files.cmake
  49. 0 1
      Gems/ScriptCanvas/Code/scriptcanvasgem_headers.cmake

+ 0 - 1
Code/Editor/LyViewPaneNames.h

@@ -32,7 +32,6 @@ namespace LyViewPane
     static const char* const ConsoleMenuName = "&Console";
     static const char* const ConsoleVariables = "Console Variables";
     static const char* const TrackView = "Track View";
-    static const char* const ScriptCanvas = "Script Canvas";
     static const char* const UiEditor = "UI Editor";
 
     static const char* const EditorSettingsManager = "Editor Settings Manager";

+ 5 - 0
Code/Framework/AzCore/AzCore/Component/ComponentApplicationBus.h

@@ -57,6 +57,9 @@ namespace AZ
         //! Signals if the application is running in console mode where the native client window is not created but still (optionally) supports graphics rendering.
         bool IsConsoleMode() const;
 
+        //! Signals if the application is the AssetProcessor tool application.
+        bool IsAssetProcessor() const;
+
         enum class Masks
         {
             Invalid = 0,
@@ -65,6 +68,7 @@ namespace AZ
             Game = 1 << 2,
             Headless = 1 << 3,
             ConsoleMode = 1 << 4,
+            AssetProcessor = 1 << 5
         };
         Masks m_maskValue = Masks::Invalid;
     };
@@ -76,6 +80,7 @@ namespace AZ
     inline bool ApplicationTypeQuery::IsGame() const { return (m_maskValue & Masks::Game) == Masks::Game; }
     inline bool ApplicationTypeQuery::IsHeadless() const { return (m_maskValue & Masks::Headless) == Masks::Headless; }
     inline bool ApplicationTypeQuery::IsConsoleMode() const { return (m_maskValue & Masks::ConsoleMode) == Masks::ConsoleMode; }
+    inline bool ApplicationTypeQuery::IsAssetProcessor() const { return (m_maskValue & Masks::AssetProcessor) == Masks::AssetProcessor; }
     inline bool ApplicationTypeQuery::IsValid() const { return m_maskValue != Masks::Invalid; }
 
     using EntityAddedEvent = AZ::Event<AZ::Entity*>;

+ 11 - 4
Code/Framework/AzFramework/AzFramework/Application/Application.cpp

@@ -247,12 +247,19 @@ namespace AzFramework
                 using AssetCatalogBus = AZ::Data::AssetCatalogRequestBus;
                 AssetCatalogBus::Broadcast(AZStd::move(StartMonitoringAssetsAndLoadCatalog));
             }
+
 #if defined(ENABLE_REMOTE_TOOLS)
-            IRemoteTools* remoteTools = RemoteToolsInterface::Get();
-            if (remoteTools)
+            AZ::ApplicationTypeQuery appType;
+            AZ::ComponentApplicationBus::Broadcast(&AZ::ComponentApplicationBus::Events::QueryApplicationType, appType);
+            if (appType.IsEditor() || appType.IsGame())
             {
-                remoteTools->RegisterToolingServiceClient(
-                    AzFramework::LuaToolsKey, AzFramework::LuaToolsName, AzFramework::LuaToolsPort);
+                if (IRemoteTools* remoteTools = RemoteToolsInterface::Get())
+                {
+                    remoteTools->RegisterToolingServiceClient(
+                        AzFramework::LuaToolsKey, AzFramework::LuaToolsName, AzFramework::LuaToolsPort);
+                    remoteTools->RegisterToolingServiceClient(
+                        AzFramework::ScriptCanvasToolsKey, AzFramework::ScriptCanvasToolsName, AzFramework::ScriptCanvasToolsPort);
+                }
             }
 #endif
         }

+ 5 - 0
Code/Framework/AzFramework/AzFramework/Script/ScriptRemoteDebuggingConstants.h

@@ -7,6 +7,7 @@
  */
 #pragma once
 
+#include <AzCore/Math/Crc.h>
 #include <AzCore/Name/Name.h>
 #include <AzCore/Name/NameDictionary.h>
 
@@ -15,4 +16,8 @@ namespace AzFramework
     static const AZ::Name LuaToolsName = AZ::Name::FromStringLiteral("LuaRemoteTools", nullptr);
     static constexpr AZ::Crc32 LuaToolsKey("LuaRemoteTools");
     static constexpr uint16_t LuaToolsPort = 6777;
+
+    static const AZ::Name ScriptCanvasToolsName = AZ::Name::FromStringLiteral("ScriptCanvasRemoteTools", nullptr);
+    static constexpr AZ::Crc32 ScriptCanvasToolsKey("ScriptCanvasRemoteTools");
+    static constexpr uint16_t ScriptCanvasToolsPort = 45641;
 }

+ 4 - 0
Code/Tools/AssetProcessor/AssetBuilder/AssetBuilderApplication.h

@@ -45,6 +45,10 @@ public:
 
     void InitializeBuilderComponents() override;
 
+protected:
+    // AzFramework::ApplicationRequests::Bus overrides ...
+    void QueryApplicationType(AZ::ApplicationTypeQuery& appType) const override;
+
 private:
     void InstallCtrlHandler();
 

+ 5 - 0
Code/Tools/AssetProcessor/AssetBuilder/Platform/Linux/AssetBuilderApplication_linux.cpp

@@ -8,6 +8,11 @@
 
 #include <AssetBuilderApplication.h>
 
+void AssetBuilderApplication::QueryApplicationType(AZ::ApplicationTypeQuery& appType) const
+{
+    appType.m_maskValue = AZ::ApplicationTypeQuery::Masks::Tool | AZ::ApplicationTypeQuery::Masks::AssetProcessor;
+}
+
 void AssetBuilderApplication::InstallCtrlHandler()
 {
 }

+ 5 - 0
Code/Tools/AssetProcessor/AssetBuilder/Platform/Mac/AssetBuilderApplication_mac.cpp

@@ -8,6 +8,11 @@
 
 #include <AssetBuilderApplication.h>
 
+void AssetBuilderApplication::QueryApplicationType(AZ::ApplicationTypeQuery& appType) const
+{
+    appType.m_maskValue = AZ::ApplicationTypeQuery::Masks::Tool | AZ::ApplicationTypeQuery::Masks::AssetProcessor;
+}
+
 void AssetBuilderApplication::InstallCtrlHandler()
 {
 }

+ 5 - 0
Code/Tools/AssetProcessor/AssetBuilder/Platform/Windows/AssetBuilderApplication_windows.cpp

@@ -25,6 +25,11 @@ namespace AssetBuilderApplicationPrivate
     }
 }
 
+void AssetBuilderApplication::QueryApplicationType(AZ::ApplicationTypeQuery& appType) const
+{
+    appType.m_maskValue = AZ::ApplicationTypeQuery::Masks::Tool | AZ::ApplicationTypeQuery::Masks::AssetProcessor;
+}
+
 void AssetBuilderApplication::InstallCtrlHandler()
 {
     ::SetConsoleCtrlHandler(AssetBuilderApplicationPrivate::CtrlHandlerRoutine, TRUE);

+ 21 - 21
Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/NodePalette/NodePaletteWidget.cpp

@@ -64,27 +64,6 @@ namespace GraphCanvas
             QModelIndex sourceIndex = static_cast<const NodePaletteSortFilterProxyModel*>(index.model())->mapToSource(index);
             NodePaletteTreeItem* treeItem = static_cast<NodePaletteTreeItem*>(sourceIndex.internalPointer());
 
-            if (treeItem)
-            {
-                // Make the text slightly transparent if the item is disabled
-                if (!treeItem->IsEnabled())
-                {
-                    QVariant roleColor = index.data(Qt::ForegroundRole);
-                    QColor textColor = (roleColor.type() == QVariant::Type::Color)
-                        ? roleColor.value<QColor>() : options.palette.color(QPalette::Text);
-
-                    int fontAlpha = aznumeric_cast<int>(textColor.alpha() * 0.5f);
-                    fontAlpha = AZStd::min(AZStd::min(fontAlpha, 127), textColor.alpha());
-
-                    textColor.setAlpha(fontAlpha);
-
-                    options.palette.setColor(QPalette::Text, textColor);
-                }
-            }
-
-            // paint the original node item
-            IconDecoratedNameDelegate::paint(painter, options, index);
-
             const int textMargin = options.widget->style()->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, options.widget) + 1;
             QRect textRect = options.widget->style()->subElementRect(QStyle::SE_ItemViewItemText, &options);
             textRect = textRect.adjusted(textMargin, 0, -textMargin, 0);
@@ -111,6 +90,27 @@ namespace GraphCanvas
                 }
             }
 
+            if (treeItem)
+            {
+                // Make the text slightly transparent if the item is disabled
+                if (!treeItem->IsEnabled())
+                {
+                    QVariant roleColor = index.data(Qt::ForegroundRole);
+                    QColor textColor =
+                        (roleColor.type() == QVariant::Type::Color) ? roleColor.value<QColor>() : options.palette.color(QPalette::Text);
+
+                    int fontAlpha = aznumeric_cast<int>(textColor.alpha() * 0.5f);
+                    fontAlpha = AZStd::min(AZStd::min(fontAlpha, 127), textColor.alpha());
+
+                    textColor.setAlpha(fontAlpha);
+
+                    options.palette.setColor(QPalette::Text, textColor);
+                }
+            }
+
+            // paint the original node item
+            IconDecoratedNameDelegate::paint(painter, options, index);
+
             painter->restore();
         }
         else

+ 50 - 0
Gems/ScriptCanvas/Code/Application/Document/ScriptCanvasDocument.cpp

@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include "ScriptCanvasDocument.h"
+
+#include <AtomToolsFramework/Document/AtomToolsDocumentTypeInfo.h>
+#include <AzCore/RTTI/BehaviorContext.h>
+#include <AzCore/Serialization/EditContext.h>
+#include <AzCore/Serialization/SerializeContext.h>
+
+namespace ScriptCanvas
+{
+    void ScriptCanvasDocument::Reflect(AZ::ReflectContext* context)
+    {
+        if (auto serialize = azrtti_cast<AZ::SerializeContext*>(context))
+        {
+            serialize->Class<ScriptCanvasDocument, AtomToolsFramework::AtomToolsDocument>()->Version(0);
+        }
+    }
+
+    ScriptCanvasDocument::ScriptCanvasDocument(const AZ::Crc32& toolId, const AtomToolsFramework::DocumentTypeInfo& documentTypeInfo)
+        : AtomToolsFramework::AtomToolsDocument(toolId, documentTypeInfo)
+    {
+        ScriptCanvasDocumentRequestBus::Handler::BusConnect(m_id);
+    }
+
+    ScriptCanvasDocument::~ScriptCanvasDocument()
+    {
+        ScriptCanvasDocumentRequestBus::Handler::BusDisconnect();
+    }
+
+    AtomToolsFramework::DocumentTypeInfo ScriptCanvasDocument::BuildDocumentTypeInfo()
+    {
+        AtomToolsFramework::DocumentTypeInfo documentType;
+        documentType.m_documentTypeName = "ScriptCanvas";
+        documentType.m_documentFactoryCallback = [](const AZ::Crc32& toolId, const AtomToolsFramework::DocumentTypeInfo& documentTypeInfo)
+        {
+            return aznew ScriptCanvasDocument(toolId, documentTypeInfo);
+        };
+        documentType.m_supportedExtensionsToCreate.push_back({ "Script Canvas", "scriptcanvas" });
+        documentType.m_supportedExtensionsToOpen.push_back({ "Script Canvas", "scriptcanvas" });
+        return documentType;
+    }
+
+} // namespace ScriptCanvas

+ 36 - 0
Gems/ScriptCanvas/Code/Application/Document/ScriptCanvasDocument.h

@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include <AtomToolsFramework/Document/AtomToolsDocument.h>
+#include <AzCore/RTTI/RTTI.h>
+
+#include "ScriptCanvasDocumentRequestBus.h"
+
+namespace ScriptCanvas
+{
+    class ScriptCanvasDocument
+        : public AtomToolsFramework::AtomToolsDocument
+        , public ScriptCanvasDocumentRequestBus::Handler
+    {
+    public:
+        AZ_RTTI(ScriptCanvasDocument, "{1030D380-F43F-4C84-9041-8B85B0EF75A3}", AtomToolsFramework::AtomToolsDocument);
+        AZ_CLASS_ALLOCATOR(ScriptCanvasDocument, AZ::SystemAllocator);
+        AZ_DISABLE_COPY_MOVE(ScriptCanvasDocument);
+
+        static void Reflect(AZ::ReflectContext* context);
+
+        ScriptCanvasDocument() = default;
+        ScriptCanvasDocument(const AZ::Crc32& toolId, const AtomToolsFramework::DocumentTypeInfo& documentTypeInfo);
+        virtual ~ScriptCanvasDocument();
+
+        // AtomToolsFramework::AtomToolsDocument overrides...
+        static AtomToolsFramework::DocumentTypeInfo BuildDocumentTypeInfo();
+        // ~AtomToolsFramework::AtomToolsDocument
+    };
+
+} // namespace ScriptCanvas

+ 20 - 0
Gems/ScriptCanvas/Code/Application/Document/ScriptCanvasDocumentRequestBus.h

@@ -0,0 +1,20 @@
+/*
+ * 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
+ *
+ */
+
+namespace ScriptCanvas
+{
+    class ScriptCanvasDocumentRequests : public AZ::EBusTraits
+    {
+    public:
+        static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
+        static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
+        typedef AZ::Uuid BusIdType;
+    };
+
+    using ScriptCanvasDocumentRequestBus = AZ::EBus<ScriptCanvasDocumentRequests>;
+} // namespace ScriptCanvas

+ 10 - 0
Gems/ScriptCanvas/Code/Application/Platform/Android/platform_android_files.cmake

@@ -0,0 +1,10 @@
+#
+# 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
+#
+#
+
+set(FILES
+)

+ 10 - 0
Gems/ScriptCanvas/Code/Application/Platform/Linux/platform_linux_files.cmake

@@ -0,0 +1,10 @@
+#
+# 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
+#
+#
+
+set(FILES
+)

+ 10 - 0
Gems/ScriptCanvas/Code/Application/Platform/Mac/platform_mac_files.cmake

@@ -0,0 +1,10 @@
+#
+# 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
+#
+#
+
+set(FILES
+)

+ 3 - 0
Gems/ScriptCanvas/Code/Application/Platform/Windows/ScriptCanvasApplication.ico

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b552edbdfee09d7588e0b8deb305d2d29de31c4c9ce5eab26b24cfd426dfa99d
+size 5214

+ 1 - 0
Gems/ScriptCanvas/Code/Application/Platform/Windows/ScriptCanvasApplication.rc

@@ -0,0 +1 @@
+IDI_ICON1 ICON DISCARDABLE "ScriptCanvasApplication.ico"

+ 11 - 0
Gems/ScriptCanvas/Code/Application/Platform/Windows/platform_windows_files.cmake

@@ -0,0 +1,11 @@
+#
+# 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
+#
+#
+
+set(FILES
+    ScriptCanvasApplication.rc
+)

+ 10 - 0
Gems/ScriptCanvas/Code/Application/Platform/iOS/platform_ios_files.cmake

@@ -0,0 +1,10 @@
+#
+# 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
+#
+#
+
+set(FILES
+)

+ 18 - 0
Gems/ScriptCanvas/Code/Application/Resources/application.svg

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="100%" height="100%" viewBox="0 0 256 256" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
+    <g id="Icons---Application-Icons---Material-Editor" serif:id="Icons-/-Application-Icons-/-Material-Editor">
+        <g id="Group">
+            <g id="Fill-1-Clipped">
+                <path id="Fill-1" d="M184.641,-0L71.359,-0C32.112,-0 0,32.111 0,71.359L0,184.641C0,223.889 32.112,256 71.359,256L184.641,256C223.889,256 256,223.889 256,184.641L256,71.359C256,32.111 223.889,-0 184.641,-0" style="fill:rgb(30,112,235);fill-rule:nonzero;"/>
+            </g>
+            <g id="script_canvas_editor.svg" transform="matrix(8.72164,0,0,8.72164,128,128)">
+                <g transform="matrix(1,0,0,1,-12,-12)">
+                    <g id="SC-icon">
+                        <path d="M10.693,4.518L2.961,4.518L2.961,7.967C2.961,8.287 3.209,8.548 3.513,8.548L10.141,8.548C10.449,8.548 10.693,8.29 10.693,7.967L10.693,4.518ZM14.233,16.435L14.233,20.173C14.233,20.492 14.481,20.753 14.785,20.753L21.413,20.753C21.721,20.753 21.965,20.496 21.965,20.173L21.965,16.435L14.233,16.435ZM13.284,19.173C10.225,19.173 8.774,18.054 8.774,16.155C8.774,13.038 10.373,12.156 12.105,10.771C13.112,9.965 15.712,8.728 15.419,7.156C15.074,5.312 13.789,5.542 12.961,5.542L11.74,5.542L11.74,8.559C11.74,9.197 11.252,9.715 10.639,9.715L3.1,9.715C2.493,9.715 2,9.196 2,8.559L2,3.156C2,2.518 2.487,2 3.1,2L10.639,2C11.247,2 11.74,2.519 11.74,3.156L11.74,4.287C11.808,4.304 12.821,4.287 13.291,4.287C14.527,4.287 16.431,4.716 16.774,7.156C17.105,9.514 13.864,11.102 12.961,11.765C12.057,12.428 9.985,13.94 10.373,16.155C10.592,17.401 11.14,17.494 13.284,17.616L13.284,15.096C13.284,14.458 13.771,13.94 14.384,13.94L21.9,13.94C22.507,13.94 23,14.459 23,15.096L23,20.844C23,21.482 22.513,22 21.9,22L14.384,22C13.776,22 13.284,21.481 13.284,20.844L13.284,19.173Z" style="fill:white;fill-rule:nonzero;"/>
+                    </g>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>

+ 103 - 0
Gems/ScriptCanvas/Code/Application/ScriptCanvasApplication.cpp

@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include "ScriptCanvasApplication.h"
+
+#include "Document/ScriptCanvasDocument.h"
+
+#include <AzFramework/Network/IRemoteTools.h>
+#include <AzFramework/Script/ScriptRemoteDebuggingConstants.h>
+#include <QApplication>
+#include <QIcon>
+
+#if defined(EXTERNAL_CRASH_REPORTING)
+#include <ToolsCrashHandler.h>
+#endif
+
+// This has to live outside of any namespaces due to issues on Linux with calls to Q_INIT_RESOURCE if they are inside a namespace
+void InitScriptCanvasApplicationResources()
+{
+    Q_INIT_RESOURCE(ScriptCanvasApplicationResources);
+}
+
+namespace ScriptCanvas
+{
+    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;
+    }
+
+    ScriptCanvasApplication::ScriptCanvasApplication(int* argc, char*** argv)
+        : Base(GetBuildTargetName(), argc, argv)
+    {
+#if defined(EXTERNAL_CRASH_REPORTING)
+        CrashHandler::ToolsCrashHandler::InitCrashHandler(GetBuildTargetName(), {});
+#endif
+
+        InitScriptCanvasApplicationResources();
+
+        QApplication::setOrganizationName("O3DE");
+        QApplication::setApplicationName("O3DE Script Canvas");
+        QApplication::setWindowIcon(QIcon(":/Resources/application.svg"));
+
+        AzToolsFramework::EditorWindowRequestBus::Handler::BusConnect();
+        AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect(m_toolId);
+    }
+
+    ScriptCanvasApplication::~ScriptCanvasApplication()
+    {
+        AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusDisconnect();
+        AzToolsFramework::EditorWindowRequestBus::Handler::BusDisconnect();
+    }
+
+    void ScriptCanvasApplication::Reflect(AZ::ReflectContext* context)
+    {
+        Base::Reflect(context);
+        ScriptCanvasDocument::Reflect(context);
+    }
+
+    void ScriptCanvasApplication::StartCommon(AZ::Entity* systemEntity)
+    {
+        Base::StartCommon(systemEntity);
+
+        auto documentTypeInfo = ScriptCanvasDocument::BuildDocumentTypeInfo();
+        AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Event(
+            m_toolId, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Handler::RegisterDocumentType, documentTypeInfo);
+
+#if defined(ENABLE_REMOTE_TOOLS)
+        if (auto* remoteToolsInterface = AzFramework::RemoteToolsInterface::Get())
+        {
+            remoteToolsInterface->RegisterToolingServiceHost(
+                AzFramework::ScriptCanvasToolsKey, AzFramework::ScriptCanvasToolsName, AzFramework::ScriptCanvasToolsPort);
+        }
+#endif
+
+        InitMainWindow();
+    }
+
+    void ScriptCanvasApplication::Destroy()
+    {
+        m_window.reset();
+        Base::Destroy();
+    }
+
+    QWidget* ScriptCanvasApplication::GetAppMainWindow()
+    {
+        return m_window.get();
+    }
+
+    void ScriptCanvasApplication::InitMainWindow()
+    {
+        m_window.reset(aznew ScriptCanvasEditor::MainWindow(m_toolId));
+        m_window->show();
+    }
+
+} // namespace ScriptCanvas

+ 48 - 0
Gems/ScriptCanvas/Code/Application/ScriptCanvasApplication.h

@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include <AtomToolsFramework/Document/AtomToolsDocumentApplication.h>
+#include <AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h>
+#include <AzCore/Memory/Memory.h>
+#include <AzCore/Settings/CommandLine.h>
+#include <AzToolsFramework/API/EditorWindowRequestBus.h>
+#include <View/Windows/MainWindow.h>
+
+namespace ScriptCanvas
+{
+    class ScriptCanvasApplication
+        : public AtomToolsFramework::AtomToolsDocumentApplication
+        , private AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler
+        , private AzToolsFramework::EditorWindowRequestBus::Handler
+    {
+    public:
+        AZ_CLASS_ALLOCATOR(ScriptCanvasApplication, AZ::SystemAllocator)
+        AZ_TYPE_INFO(ScriptCanvasApplication, "{484D42F9-30C5-4221-BF23-EDCA71726C05}");
+        using Base = AtomToolsFramework::AtomToolsDocumentApplication;
+
+        ScriptCanvasApplication(int* argc, char*** argv);
+        virtual ~ScriptCanvasApplication() override;
+
+        // AzFramework::Application overrides
+        void Reflect(AZ::ReflectContext* context) override;
+        void StartCommon(AZ::Entity* systemEntity) override;
+        void Destroy() override;
+        // ~AzToolsFramework::ToolsApplication
+
+        // AzToolsFramework::EditorWindowRequests::Bus::Handler
+        QWidget* GetAppMainWindow() override;
+
+    private:
+        void InitMainWindow();
+
+    private:
+        AZStd::unique_ptr<ScriptCanvasEditor::MainWindow> m_window;
+    };
+} // namespace ScriptCanvas

+ 5 - 0
Gems/ScriptCanvas/Code/Application/ScriptCanvasApplicationResources.qrc

@@ -0,0 +1,5 @@
+<RCC>
+    <qresource prefix="/">
+      <file>Resources/application.svg</file>
+    </qresource>
+</RCC>

+ 28 - 0
Gems/ScriptCanvas/Code/Application/main.cpp

@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include "ScriptCanvasApplication.h"
+
+#include <AzCore/Debug/Trace.h>
+#include <AzQtComponents/Application/AzQtApplication.h>
+
+int main(int argc, char* argv[])
+{
+    const AZ::Debug::Trace tracer;
+    AzQtComponents::AzQtApplication::InitializeDpiScaling();
+
+    ScriptCanvas::ScriptCanvasApplication app(&argc, &argv);
+    if (app.LaunchLocalServer())
+    {
+        app.Start({}, {});
+        app.RunMainLoop();
+        app.Stop();
+    }
+
+    return 0;
+}

+ 1 - 2
Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderDataSystem.cpp

@@ -104,8 +104,7 @@ namespace ScriptCanvasBuilder
         AZ::ApplicationTypeQuery appType;
         AZ::ComponentApplicationBus::Broadcast(&AZ::ComponentApplicationBus::Events::QueryApplicationType, appType);
         ScriptCanvas::MakeInternalGraphEntitiesUnique makeUnique = ScriptCanvas::MakeInternalGraphEntitiesUnique::Yes;
-        const bool isAssetProcessor = appType.IsValid() && (appType.IsTool() && !appType.IsEditor());
-        if (isAssetProcessor)
+        if (appType.IsAssetProcessor())
         {
             // Allow to keep the same entity UIDs between the editable scriptCanvas and the compiled scriptCanvas files,
             // This is needed to support debug features such as breakpoints.

+ 57 - 0
Gems/ScriptCanvas/Code/CMakeLists.txt

@@ -157,6 +157,7 @@ ly_create_alias(NAME ${gem_name}.Servers  NAMESPACE Gem TARGETS Gem::${gem_name}
 ly_create_alias(NAME ${gem_name}.Unified  NAMESPACE Gem TARGETS Gem::${gem_name})
 
 if(PAL_TRAIT_BUILD_HOST_TOOLS)
+
     ly_add_target(
         NAME ${gem_name}.Editor.Static STATIC
         NAMESPACE Gem
@@ -194,6 +195,7 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS)
                 Gem::ExpressionEvaluation.Static
             PRIVATE
                 Legacy::EditorCore
+                Gem::AtomToolsFramework.Static
         RUNTIME_DEPENDENCIES
             Gem::${gem_name}
     )
@@ -231,6 +233,50 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS)
             Gem::ExpressionEvaluation
     )
 
+    o3de_pal_dir(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Application/Platform/${PAL_PLATFORM_NAME} "${gem_restricted_path}" "${gem_path}" "${gem_parent_relative_path}")
+
+    ly_add_target(
+        NAME ${gem_name}Application APPLICATION
+        NAMESPACE Gem
+        AUTORCC
+        FILES_CMAKE
+            scriptcanvasgem_application_files.cmake
+            ${pal_source_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
+        COMPILE_DEFINITIONS
+            PUBLIC
+                SCRIPTCANVAS_ERRORS_ENABLED
+            PRIVATE
+                SCRIPTCANVAS_EDITOR
+                ${SCRIPT_CANVAS_COMMON_DEFINES}
+        INCLUDE_DIRECTORIES
+            PRIVATE
+                Application
+                Editor
+        BUILD_DEPENDENCIES
+            PRIVATE
+                AZ::AzCore
+                AZ::AzToolsFramework
+                AZ::AzQtComponents
+                Legacy::EditorCore
+                Gem::${gem_name}.Editor
+                Gem::${gem_name}.Editor.Static
+                Gem::AtomToolsFramework.Static
+        RUNTIME_DEPENDENCIES
+            Gem::${gem_name}.Editor
+    )
+
+    # Inject target name for dependency resolution
+    ly_add_source_properties(
+        SOURCES
+            Application/ScriptCanvasApplication.cpp
+        PROPERTY COMPILE_DEFINITIONS
+            VALUES
+                LY_CMAKE_TARGET="${gem_name}Application")
+
+    if(PAL_TRAIT_BUILD_EXTERNAL_CRASH_HANDLER_SUPPORTED)
+        ly_target_link_libraries(${gem_name}Application PRIVATE AZ::ToolsCrashHandler)
+    endif()
+
     # Inject the gem name into the Module source file
     ly_add_source_properties(
         SOURCES
@@ -244,6 +290,17 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS)
     ly_create_alias(NAME ${gem_name}.Builders NAMESPACE Gem TARGETS Gem::${gem_name}.Editor)
     ly_create_alias(NAME ${gem_name}.Tools    NAMESPACE Gem TARGETS Gem::${gem_name}.Editor)
 
+    ly_set_gem_variant_to_load(TARGETS ${gem_name}Application VARIANTS Tools)
+    
+    # Add build dependency to Editor for the ScriptCanvas application since
+    # Editor opens up the ScriptCanvas
+    ly_add_dependencies(Editor Gem::${gem_name}Application)
+
+    # Inject the project path into the ScriptCanvas VS debugger command arguments if the build system being invoked
+    # in a project centric view
+    if(NOT PROJECT_NAME STREQUAL "O3DE")
+        set_property(TARGET ${gem_name}Application APPEND PROPERTY VS_DEBUGGER_COMMAND_ARGUMENTS "--project-path=\"${CMAKE_SOURCE_DIR}\"")
+    endif()
 
 endif()
 

+ 4 - 12
Gems/ScriptCanvas/Code/Editor/Framework/Configuration.cpp

@@ -15,11 +15,11 @@
 #include <AzFramework/Asset/AssetSystemBus.h>
 #include <AzToolsFramework/API/EditorAssetSystemAPI.h>
 #include <AzToolsFramework/API/ToolsApplicationAPI.h>
-#include <LyViewPaneNames.h>
-#include <ScriptCanvas/Assets/ScriptCanvasFileHandling.h>
 #include <Editor/Framework/Configuration.h>
-#include <ScriptCanvas/Components/EditorUtils.h>
+#include <ScriptCanvas/Assets/ScriptCanvasFileHandling.h>
 #include <ScriptCanvas/Bus/RequestBus.h>
+#include <ScriptCanvas/Bus/ScriptCanvasBus.h>
+#include <ScriptCanvas/Components/EditorUtils.h>
 
 namespace ScriptCanvasEditor
 {
@@ -155,17 +155,9 @@ namespace ScriptCanvasEditor
 
     void Configuration::OpenEditor([[maybe_unused]] const AZ::Data::AssetId& assetId, const AZ::Data::AssetType&)
     {
-        AzToolsFramework::OpenViewPane(LyViewPane::ScriptCanvas);
-
         if (m_sourceHandle.IsDescriptionValid())
         {
-            AZ::Outcome<int, AZStd::string> openOutcome = AZ::Failure(AZStd::string());
-            GeneralRequestBus::BroadcastResult(openOutcome, &GeneralRequests::OpenScriptCanvasAsset, m_sourceHandle, Tracker::ScriptCanvasFileState::UNMODIFIED, -1);
-
-            if (!openOutcome)
-            {
-                AZ_Warning("Script Canvas", openOutcome, "%s", openOutcome.GetError().data());
-            }
+            SystemRequestBus::Broadcast(&SystemRequestBus::Events::OpenScriptCanvasEditor, m_sourceHandle.AbsolutePath().c_str());
         }
     }
 

+ 3 - 0
Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Bus/ScriptCanvasBus.h

@@ -28,6 +28,9 @@ namespace ScriptCanvasEditor
         virtual void CreateEditorComponentsOnEntity(AZ::Entity* entity, const AZ::Data::AssetType& assetType) = 0;
 
         virtual void RequestGarbageCollect() = 0;
+
+        //! Open document in script canvas editor
+        virtual void OpenScriptCanvasEditor(const AZStd::string& sourcePath) = 0;
     };
 
     using SystemRequestBus = AZ::EBus<SystemRequests>;

+ 94 - 62
Gems/ScriptCanvas/Code/Editor/SystemComponent.cpp

@@ -7,18 +7,22 @@
  */
 
 #include <AzCore/EBus/Results.h>
+#include <AzCore/IO/Path/Path.h>
 #include <AzCore/Jobs/JobFunction.h>
 #include <AzCore/Serialization/EditContext.h>
 #include <AzCore/Serialization/SerializeContext.h>
 #include <AzCore/Serialization/Utils.h>
-#include <AzCore/StringFunc/StringFunc.h>
 #include <AzCore/std/string/wildcard.h>
+#include <AzCore/StringFunc/StringFunc.h>
+#include <AzCore/Utils/Utils.h>
 #include <AzFramework/Entity/EntityContextBus.h>
-#include <AzFramework/Network/IRemoteTools.h>
 #include <AzFramework/IO/FileOperations.h>
 #include <AzToolsFramework/ActionManager/Action/ActionManagerInterface.h>
+#include <AzToolsFramework/ActionManager/Menu/MenuManagerInterface.h>
 #include <AzToolsFramework/API/ViewPaneOptions.h>
 #include <AzToolsFramework/AssetBrowser/Entries/SourceAssetBrowserEntry.h>
+#include <AzToolsFramework/Editor/ActionManagerIdentifiers/EditorContextIdentifiers.h>
+#include <AzToolsFramework/Editor/ActionManagerIdentifiers/EditorMenuIdentifiers.h>
 #include <AzToolsFramework/UI/PropertyEditor/GenericComboBoxCtrl.h>
 #include <Editor/Assets/ScriptCanvasAssetHelpers.h>
 #include <Editor/Framework/ScriptCanvasGraphUtilities.h>
@@ -29,10 +33,11 @@
 #include <Editor/View/Windows/MainWindow.h>
 #include <GraphCanvas/GraphCanvasBus.h>
 #include <LyViewPaneNames.h>
-#include <QFileInfo>
 #include <QDir>
+#include <QFileInfo>
 #include <QMenu>
-#include <ScriptCanvasContextIdentifiers.h>
+#include <QProcess>
+#include <QString>
 #include <ScriptCanvas/Bus/EditorScriptCanvasBus.h>
 #include <ScriptCanvas/Components/EditorGraph.h>
 #include <ScriptCanvas/Components/EditorGraphVariableManagerComponent.h>
@@ -40,11 +45,13 @@
 #include <ScriptCanvas/Data/DataRegistry.h>
 #include <ScriptCanvas/Libraries/Libraries.h>
 #include <ScriptCanvas/PerformanceStatisticsBus.h>
-#include <ScriptCanvas/Utils/ScriptCanvasConstants.h>
 #include <ScriptCanvas/Variable/VariableCore.h>
+#include <ScriptCanvasContextIdentifiers.h>
 
 namespace ScriptCanvasEditor
 {
+    constexpr AZStd::string_view ScriptCanvasApplicationActionIdentifier = "o3de.action.tools.script_canvas";
+
     static const size_t cs_jobThreads = 1;
 
     SystemComponent::SystemComponent()
@@ -56,8 +63,6 @@ namespace ScriptCanvasEditor
 
     SystemComponent::~SystemComponent()
     {
-        AzToolsFramework::UnregisterViewPane(LyViewPane::ScriptCanvas);
-        AzToolsFramework::EditorEvents::Bus::Handler::BusDisconnect();
         AzToolsFramework::AssetSeedManagerRequests::Bus::Handler::BusDisconnect();
         AZ::SystemTickBus::Handler::BusDisconnect();
     }
@@ -107,21 +112,11 @@ namespace ScriptCanvasEditor
 
     void SystemComponent::Init()
     {
-        AzToolsFramework::EditorEvents::Bus::Handler::BusConnect();
-
         m_viewportDragDropHandler = AZStd::make_unique<ScriptCanvasAssetDragDropHandler>();
     }
 
     void SystemComponent::Activate()
     {
-#if defined(ENABLE_REMOTE_TOOLS)
-        if (auto* remoteToolsInterface = AzFramework::RemoteToolsInterface::Get())
-        {
-            remoteToolsInterface->RegisterToolingServiceHost(
-                ScriptCanvas::RemoteToolsKey, ScriptCanvas::RemoteToolsName, ScriptCanvas::RemoteToolsPort);
-        }
-#endif
-
         AZ::JobManagerDesc jobDesc;
         for (size_t i = 0; i < cs_jobThreads; ++i)
         {
@@ -140,7 +135,6 @@ namespace ScriptCanvasEditor
 
         SystemRequestBus::Handler::BusConnect();
         ScriptCanvasExecutionBus::Handler::BusConnect();
-        AzToolsFramework::EditorEvents::Bus::Handler::BusConnect();
         AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusConnect();
         AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusConnect();
         AzToolsFramework::ActionManagerRegistrationNotificationBus::Handler::BusConnect();
@@ -160,24 +154,11 @@ namespace ScriptCanvasEditor
         m_nodeReplacementSystem.LoadReplacementMetadata();
     }
 
-    void SystemComponent::NotifyRegisterViews()
-    {
-        QtViewOptions options;
-        options.canHaveMultipleInstances = false;
-        options.isPreview = true;
-        options.showInMenu = true;
-        options.showOnToolsToolbar = true;
-        options.toolbarIcon = ":/Menu/script_canvas_editor.svg";
-
-        AzToolsFramework::RegisterViewPane<ScriptCanvasEditor::MainWindow>(LyViewPane::ScriptCanvas, LyViewPane::CategoryTools, options);
-    }
-
     void SystemComponent::Deactivate()
     {
         AzToolsFramework::ActionManagerRegistrationNotificationBus::Handler::BusDisconnect();
         m_nodeReplacementSystem.UnloadReplacementMetadata();
         AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusDisconnect();
-        AzToolsFramework::EditorEvents::Bus::Handler::BusDisconnect();
         ScriptCanvasExecutionBus::Handler::BusDisconnect();
         SystemRequestBus::Handler::BusDisconnect();
         AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusDisconnect();
@@ -195,6 +176,27 @@ namespace ScriptCanvasEditor
         }
     }
 
+    void SystemComponent::OpenScriptCanvasEditor(const AZStd::string& sourcePath)
+    {
+        QStringList arguments;
+        arguments.append(sourcePath.c_str());
+
+        AZ::IO::FixedMaxPathString projectPath(AZ::Utils::GetProjectPath());
+        if (!projectPath.empty())
+        {
+            arguments.append(QString("--project-path=%1").arg(projectPath.c_str()));
+        }
+
+        AZ_TracePrintf("ScriptCanvasApplication", "Launching Script Canvas Editor");
+        AZ::IO::FixedMaxPath engineRoot = AZ::Utils::GetEnginePath();
+        AZ_Assert(!engineRoot.empty(), "Cannot query Engine Path");
+
+        AZ::IO::FixedMaxPath launchPath =
+            AZ::IO::FixedMaxPath(AZ::Utils::GetExecutableDirectory()) / (QString("ScriptCanvasApplication") + AZ_TRAIT_OS_EXECUTABLE_EXTENSION).toUtf8().constData();
+
+        QProcess::startDetached(launchPath.c_str(), arguments, engineRoot.c_str());
+    }
+
     void SystemComponent::GetEditorCreatableTypes(AZStd::unordered_set<ScriptCanvas::Data::Type>& outCreatableTypes)
     {
         outCreatableTypes.insert(m_creatableTypes.begin(), m_creatableTypes.end());
@@ -288,32 +290,10 @@ namespace ScriptCanvasEditor
 
         if (AZ::IO::Path(fullSourceFileName).Extension() == ScriptCanvasEditor::SourceDescription::GetFileExtension())
         {
-            auto scriptCanvasOpenInEditorCallback = []([[maybe_unused]] const char* fullSourceFileNameInCall, const AZ::Uuid& sourceUUIDInCall)
+            auto scriptCanvasOpenInEditorCallback =
+                [this](const char* fullSourceFileNameInCall, [[maybe_unused]] const AZ::Uuid& sourceUUIDInCall)
             {
-                AZ::Outcome<int, AZStd::string> openOutcome = AZ::Failure(AZStd::string());
-
-                auto sourceHandle = CompleteDescription(SourceHandle(nullptr, sourceUUIDInCall));
-
-                if (sourceHandle)
-                {
-                    AzToolsFramework::EditorRequests::Bus::Broadcast(&AzToolsFramework::EditorRequests::OpenViewPane, "Script Canvas");
-
-                    GeneralRequestBus::BroadcastResult(openOutcome
-                        , &GeneralRequests::OpenScriptCanvasAsset
-                        , *sourceHandle
-                        , Tracker::ScriptCanvasFileState::UNMODIFIED
-                        , -1);
-
-                    if (!openOutcome.IsSuccess())
-                    {
-                        AZ_Error("ScriptCanvas", false, openOutcome.GetError().data());
-                    }
-                }
-                else
-                {
-                    AZ_Warning("ScriptCanvas", false
-                        , "Unabled to find full path for Source UUid %s", sourceUUIDInCall.ToString<AZStd::string>().c_str());
-                }
+                OpenScriptCanvasEditor(fullSourceFileNameInCall);
             };
 
             openers.push_back({ "O3DE_ScriptCanvasEditor"
@@ -400,14 +380,66 @@ namespace ScriptCanvasEditor
 
     void SystemComponent::OnActionContextRegistrationHook()
     {
-        if (auto actionManagerInterface = AZ::Interface<AzToolsFramework::ActionManagerInterface>::Get())
+        auto* actionManagerInterface = AZ::Interface<AzToolsFramework::ActionManagerInterface>::Get();
+        AZ_Assert(actionManagerInterface, "ScriptCanvas System Component - could not get ActionManagerInterface");
+        if (!actionManagerInterface)
+            return;
+        
+        AzToolsFramework::ActionContextProperties contextProperties;
+        contextProperties.m_name = "O3DE Script Canvas";
+
+        // Register custom action contexts to allow duplicated shortcut hotkeys to work
+        actionManagerInterface->RegisterActionContext(ScriptCanvasIdentifiers::ScriptCanvasActionContextIdentifier, contextProperties);
+        actionManagerInterface->RegisterActionContext(ScriptCanvasIdentifiers::ScriptCanvasVariablesActionContextIdentifier, contextProperties);
+        
+    }
+
+    void SystemComponent::OnActionRegistrationHook()
+    {
+        auto* actionManagerInterface = AZ::Interface<AzToolsFramework::ActionManagerInterface>::Get();
+        AZ_Assert(actionManagerInterface, "ScriptCanvas System Component - could not get ActionManagerInterface");
+        if (!actionManagerInterface)
+            return;
+
         {
-            AzToolsFramework::ActionContextProperties contextProperties;
-            contextProperties.m_name = "O3DE Script Canvas";
+            AzToolsFramework::ActionProperties actionProperties;
+            actionProperties.m_name = "Script Canvas";
+            actionProperties.m_iconPath = ":/Menu/script_canvas_editor.svg";
+
+            auto outcome = actionManagerInterface->RegisterAction(
+                EditorIdentifiers::MainWindowActionContextIdentifier,
+                ScriptCanvasApplicationActionIdentifier,
+                actionProperties,
+                [this]()
+                {
+                    OpenScriptCanvasEditor("");
+                });
+            AZ_Assert(outcome.IsSuccess(), "Failed to RegisterAction %s", ScriptCanvasApplicationActionIdentifier.data());
+        }
+    }
 
-            // Register custom action contexts to allow duplicated shortcut hotkeys to work
-            actionManagerInterface->RegisterActionContext(ScriptCanvasIdentifiers::ScriptCanvasActionContextIdentifier, contextProperties);
-            actionManagerInterface->RegisterActionContext(ScriptCanvasIdentifiers::ScriptCanvasVariablesActionContextIdentifier, contextProperties);
+    void SystemComponent::OnMenuBindingHook()
+    {
+        auto* actionManagerInterface = AZ::Interface<AzToolsFramework::ActionManagerInterface>::Get();
+        AZ_Assert(actionManagerInterface, "ScriptCanvas System Component - could not get ActionManagerInterface");
+
+        auto menuManagerInterface = AZ::Interface<AzToolsFramework::MenuManagerInterface>::Get();
+        AZ_Assert(menuManagerInterface, "ScriptCanvas System Component - could not get MenuManagerInterface");
+
+        if (!actionManagerInterface || !menuManagerInterface)
+            return;
+
+        {
+            auto outcome = menuManagerInterface->AddActionToMenu(
+                EditorIdentifiers::ToolsMenuIdentifier,
+                ScriptCanvasApplicationActionIdentifier,
+                actionManagerInterface->GenerateActionAlphabeticalSortKey(ScriptCanvasApplicationActionIdentifier));
+
+            AZ_Assert(
+                outcome.IsSuccess(),
+                "Failed to AddAction %s to Menu %s",
+                ScriptCanvasApplicationActionIdentifier.data(),
+                EditorIdentifiers::ToolsMenuIdentifier.data());
         }
     }
 

+ 3 - 6
Gems/ScriptCanvas/Code/Editor/SystemComponent.h

@@ -35,7 +35,6 @@ namespace ScriptCanvasEditor
     class SystemComponent
         : public AZ::Component
         , private SystemRequestBus::Handler
-        , private AzToolsFramework::EditorEvents::Bus::Handler
         , private AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler
         , private ScriptCanvasExecutionBus::Handler
         , private AZ::UserSettingsNotificationBus::Handler
@@ -70,11 +69,7 @@ namespace ScriptCanvasEditor
         // SystemRequestBus::Handler...
         void GetEditorCreatableTypes(AZStd::unordered_set<ScriptCanvas::Data::Type>& outCreatableTypes) override;
         void CreateEditorComponentsOnEntity(AZ::Entity* entity, const AZ::Data::AssetType& assetType) override;
-        ////////////////////////////////////////////////////////////////////////
-
-        ////////////////////////////////////////////////////////////////////////
-        // AztoolsFramework::EditorEvents::Bus::Handler...
-        void NotifyRegisterViews() override;
+        void OpenScriptCanvasEditor(const AZStd::string& sourcePath) override;
         ////////////////////////////////////////////////////////////////////////
 
         ////////////////////////////////////////////////////////////////////////
@@ -103,6 +98,8 @@ namespace ScriptCanvasEditor
         ////////////////////////////////////////////////////////////////////////
         // ActionManagerRegistrationNotificationBus::Handler...
         void OnActionContextRegistrationHook() override;
+        void OnActionRegistrationHook() override;
+        void OnMenuBindingHook() override;
         ////////////////////////////////////////////////////////////////////////
 
         ////////////////////////////////////////////////////////////////////////

+ 11 - 60
Gems/ScriptCanvas/Code/Editor/View/Widgets/LoggingPanel/LiveWindowSession/LiveLoggingDataAggregator.cpp

@@ -10,6 +10,7 @@
 #include <AzCore/std/containers/vector.h>
 
 #include <AzFramework/Network/IRemoteTools.h>
+#include <AzFramework/Script/ScriptRemoteDebuggingConstants.h>
 #include <AzToolsFramework/Entity/EditorEntityContextBus.h>
 
 #include <Editor/View/Widgets/LoggingPanel/LiveWindowSession/LiveLoggingDataAggregator.h>
@@ -17,7 +18,6 @@
 #include <ScriptCanvas/Asset/ExecutionLogAssetBus.h>
 #include <ScriptCanvas/Core/ExecutionNotificationsBus.h>
 #include <ScriptCanvas/Execution/RuntimeComponent.h>
-#include <ScriptCanvas/Utils/ScriptCanvasConstants.h>
 
 namespace ScriptCanvasEditor
 {
@@ -26,8 +26,7 @@ namespace ScriptCanvasEditor
     //////////////////////////////
     
     LiveLoggingDataAggregator::LiveLoggingDataAggregator()
-        : m_captureType(CaptureType::Editor)
-        , m_isCapturingData(false)
+        : m_isCapturingData(false)
         , m_ignoreRegistrations(false)
     {
         ScriptCanvas::Debugger::ClientUINotificationBus::Handler::BusConnect();
@@ -43,10 +42,10 @@ namespace ScriptCanvasEditor
     {
         ResetData();
 
-        bool isConnected = false;
-        ScriptCanvas::Debugger::ClientRequestsBus::BroadcastResult(isConnected, &ScriptCanvas::Debugger::ClientRequests::HasValidConnection);
+        AzFramework::RemoteToolsEndpointInfo target;
+        ScriptCanvas::Debugger::ClientRequestsBus::BroadcastResult(target, &ScriptCanvas::Debugger::ClientRequests::GetNetworkTarget);
         
-        if (isConnected)
+        if (target.IsValid())
         {
             EditorLoggingComponentNotificationBus::Handler::BusDisconnect();
 
@@ -54,15 +53,7 @@ namespace ScriptCanvasEditor
             {
                 ScriptCanvas::Debugger::ServiceNotificationsBus::Handler::BusConnect();
             }
-
-            bool isSelf = false;
-            ScriptCanvas::Debugger::ClientRequestsBus::BroadcastResult(isSelf, &ScriptCanvas::Debugger::ClientRequests::IsConnectedToSelf);
-
-            if (!isSelf)
-            {
-                m_captureType = CaptureType::External;
-                m_staticRegistrations.clear();
-            }
+            m_staticRegistrations.clear();
         }
         else
         {
@@ -72,8 +63,6 @@ namespace ScriptCanvasEditor
             }
 
             ScriptCanvas::Debugger::ServiceNotificationsBus::Handler::BusDisconnect();
-
-            m_captureType = CaptureType::Editor;
             SetupEditorEntities();
         }
     }
@@ -201,7 +190,7 @@ namespace ScriptCanvasEditor
             return;
         }
 
-        if (IsCapturingData() || m_captureType == External)
+        if (IsCapturingData())
         {
             if (graphIdentifier.m_componentId == k_dynamicallySpawnedControllerId)
             {
@@ -237,7 +226,7 @@ namespace ScriptCanvasEditor
             return;
         }
 
-        if (IsCapturingData() || m_captureType == External)
+        if (IsCapturingData())
         {
             if (graphIdentifier.m_componentId == k_dynamicallySpawnedControllerId)
             {
@@ -246,20 +235,6 @@ namespace ScriptCanvasEditor
             else
             {
                 ScriptCanvas::Debugger::ClientUIRequestBus::Broadcast(&ScriptCanvas::Debugger::ClientUIRequests::RemoveEntityLoggingTarget, namedEntityId, graphIdentifier);
-
-                if (m_captureType == Editor)
-                {
-                    bool gotResult = false;
-                    AZ::EntityId editorId;
-
-                    AzToolsFramework::EditorEntityContextRequestBus::BroadcastResult(gotResult, &AzToolsFramework::EditorEntityContextRequests::MapRuntimeIdToEditorId, namedEntityId, editorId);
-
-                    if (gotResult)
-                    {
-                        AZ::NamedEntityId namedEditorId(editorId, namedEntityId.GetName());
-                        RemoveStaticRegistration(namedEditorId, graphIdentifier);
-                    }
-                }
             }
 
             return;
@@ -270,8 +245,7 @@ namespace ScriptCanvasEditor
 
     void LiveLoggingDataAggregator::AddStaticRegistration(const AZ::NamedEntityId& namedEntityId, const ScriptCanvas::GraphIdentifier& graphIdentifier)
     {
-        if (graphIdentifier.m_componentId == k_dynamicallySpawnedControllerId
-            || m_captureType != Editor)
+        if (graphIdentifier.m_componentId == k_dynamicallySpawnedControllerId)
         {
             return;
         }
@@ -297,8 +271,7 @@ namespace ScriptCanvasEditor
 
     void LiveLoggingDataAggregator::RemoveStaticRegistration(const AZ::NamedEntityId& namedEntityId, const ScriptCanvas::GraphIdentifier& graphIdentifier)
     {
-        if (graphIdentifier.m_componentId == k_dynamicallySpawnedControllerId
-            || m_captureType != Editor)
+        if (graphIdentifier.m_componentId == k_dynamicallySpawnedControllerId)
         {
             return;
         }
@@ -364,29 +337,7 @@ namespace ScriptCanvasEditor
         const AZStd::string name = AZStd::string::format("ScriptCanvasLog_%s", AZStd::to_string(AZStd::GetTimeUTCMilliSecond()).data());
         ScriptCanvas::ExecutionLogAssetEBus::Broadcast(&ScriptCanvas::ExecutionLogAssetBus::SaveToRelativePath, name);
 
-        if (m_captureType == CaptureType::Editor)
-        {
-            bool isDesiredTargetConnected = false;
-            AzFramework::IRemoteTools* remoteTools = AzFramework::RemoteToolsInterface::Get();
-            if (remoteTools)
-            {
-                const AzFramework::RemoteToolsEndpointInfo& desiredTarget = remoteTools->GetDesiredEndpoint(ScriptCanvas::RemoteToolsKey);
-                isDesiredTargetConnected = desiredTarget.IsOnline();
-            }
-
-            if (isDesiredTargetConnected)
-            {
-                SetupExternalEntities();
-            }
-            else
-            {
-                SetupEditorEntities();
-            }
-        }
-        else
-        {
-            SetupExternalEntities();
-        }
+        SetupExternalEntities();
 
         ScriptCanvas::ExecutionLogAssetEBus::Broadcast(&ScriptCanvas::ExecutionLogAssetBus::ClearLog);
 

+ 0 - 7
Gems/ScriptCanvas/Code/Editor/View/Widgets/LoggingPanel/LiveWindowSession/LiveLoggingDataAggregator.h

@@ -21,12 +21,6 @@ namespace ScriptCanvasEditor
         , public ScriptCanvas::Debugger::ServiceNotificationsBus::Handler
         , public ScriptCanvas::Debugger::ClientUINotificationBus::Handler
     {
-        enum CaptureType
-        {
-            Editor,
-            External
-        };
-
     public:
         AZ_CLASS_ALLOCATOR(LiveLoggingDataAggregator, AZ::SystemAllocator);
         LiveLoggingDataAggregator();
@@ -80,7 +74,6 @@ namespace ScriptCanvasEditor
         void SetupEditorEntities();
         void SetupExternalEntities();
 
-        CaptureType m_captureType;
         bool m_isCapturingData;
         bool m_ignoreRegistrations;
 

+ 6 - 71
Gems/ScriptCanvas/Code/Editor/View/Widgets/LoggingPanel/LiveWindowSession/LiveLoggingWindowSession.cpp

@@ -7,6 +7,7 @@
  */
 
 #include <AzCore/Interface/Interface.h>
+#include <AzFramework/Script/ScriptRemoteDebuggingConstants.h>
 #include <AzToolsFramework/Entity/EditorEntityContextBus.h>
 #include <EditorCoreAPI.h>
 #include <IEditor.h>
@@ -15,8 +16,6 @@
 
 #include <Editor/View/Widgets/LoggingPanel/LiveWindowSession/LiveLoggingWindowSession.h>
 
-#include <ScriptCanvas/Utils/ScriptCanvasConstants.h>
-
 namespace ScriptCanvasEditor
 {
     ///////////////////////
@@ -127,7 +126,7 @@ namespace ScriptCanvasEditor
         AzFramework::RemoteToolsEndpointContainer targets;
         if (remoteTools)
         {
-            remoteTools->EnumTargetInfos(ScriptCanvas::RemoteToolsKey, targets);
+            remoteTools->EnumTargetInfos(AzFramework::ScriptCanvasToolsKey, targets);
         }
 
         for (const auto& targetPair : targets)
@@ -188,7 +187,6 @@ namespace ScriptCanvasEditor
 
     LiveLoggingWindowSession::LiveLoggingWindowSession(QWidget* parent)
         : LoggingWindowSession(parent)
-        , m_startedSession(false)
         , m_encodeStaticEntities(false)
         , m_isCapturing(false)
     {
@@ -199,7 +197,6 @@ namespace ScriptCanvasEditor
             m_ui->targetSelector->setModel(m_targetManagerModel);
         }
 
-        AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusConnect();
         ScriptCanvas::Debugger::ServiceNotificationsBus::Handler::BusConnect();
 
         SetDataId(m_liveDataAggregator.GetDataId());
@@ -237,7 +234,6 @@ namespace ScriptCanvasEditor
 
     LiveLoggingWindowSession::~LiveLoggingWindowSession()
     {
-        AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusDisconnect();
         ScriptCanvas::Debugger::ServiceNotificationsBus::Handler::BusDisconnect();
     }
 
@@ -268,10 +264,8 @@ namespace ScriptCanvasEditor
 
             if (connected)
             {
-                AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusDisconnect();
-
                 const AzFramework::RemoteToolsEndpointInfo& desiredInfo =
-                    AzFramework::RemoteToolsInterface::Get()->GetDesiredEndpoint(ScriptCanvas::RemoteToolsKey);
+                    AzFramework::RemoteToolsInterface::Get()->GetDesiredEndpoint(AzFramework::ScriptCanvasToolsKey);
 
                 if (desiredInfo.IsValid() && !desiredInfo.IsSelf())
                 {
@@ -294,10 +288,6 @@ namespace ScriptCanvasEditor
             
             if (useFallback)
             {
-                if (!AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusIsConnected())
-                {
-                    AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusConnect();
-                }
 
                 m_ui->targetSelector->setCurrentIndex(0);
             }
@@ -322,32 +312,6 @@ namespace ScriptCanvasEditor
         }
     }
 
-    void LiveLoggingWindowSession::OnStartPlayInEditorBegin()
-    {
-        if (isVisible())
-        {
-            m_encodeStaticEntities = true;
-            ScriptCanvas::Debugger::ClientUIRequestBus::Broadcast(&ScriptCanvas::Debugger::ClientUIRequests::StartEditorSession);
-
-            if ((m_userSettings->IsAutoCaptureEnabled()) || m_startedSession)
-            {
-                SetIsCapturing(true);
-            }
-        }
-    }
-
-    void LiveLoggingWindowSession::OnStopPlayInEditor()
-    {
-        if (isVisible())
-        {
-            SetIsCapturing(false);
-            m_startedSession = false;
-
-            ScriptCanvas::Debugger::ClientUIRequestBus::Broadcast(&ScriptCanvas::Debugger::ClientUIRequests::StopEditorSession);
-            m_encodeStaticEntities = false;
-        }
-    }
-
     void LiveLoggingWindowSession::Connected([[maybe_unused]] ScriptCanvas::Debugger::Target& target)
     {
         if (m_userSettings->IsAutoCaptureEnabled() && isVisible())
@@ -358,35 +322,6 @@ namespace ScriptCanvasEditor
 
     void LiveLoggingWindowSession::OnCaptureButtonPressed()
     {
-        bool isSelfTarget = false;
-        ScriptCanvas::Debugger::ClientRequestsBus::BroadcastResult(isSelfTarget, &ScriptCanvas::Debugger::ClientRequests::IsConnectedToSelf);
-
-        if (isSelfTarget)
-        {
-            if (!m_startedSession)
-            {
-                bool isRunningGame = false;
-                AzToolsFramework::EditorEntityContextRequestBus::BroadcastResult(isRunningGame, &AzToolsFramework::EditorEntityContextRequests::IsEditorRunningGame);
-
-                if (!isRunningGame)
-                {
-                    if (GetIEditor()->IsLevelLoaded())
-                    {
-                        m_startedSession = true;
-
-                        GetIEditor()->SetInGameMode(true);
-                    }
-
-                    return;
-                }
-            }
-            else
-            {
-                GetIEditor()->SetInGameMode(false);
-                return;
-            }
-        }
-
         SetIsCapturing(!m_isCapturing);
     }
 
@@ -417,13 +352,13 @@ namespace ScriptCanvasEditor
 
         optionsMenu.exec(point);
     }
-    
+
     void LiveLoggingWindowSession::OnTargetChanged(int index)
     {
         // Special case out the editor
         if (index == 0)
         {
-            AzFramework::RemoteToolsInterface::Get()->SetDesiredEndpoint(ScriptCanvas::RemoteToolsKey, 0);
+            AzFramework::RemoteToolsInterface::Get()->SetDesiredEndpoint(AzFramework::ScriptCanvasToolsKey, 0);
         }
         else
         {
@@ -431,7 +366,7 @@ namespace ScriptCanvasEditor
 
             if (info.IsValid())
             {
-                AzFramework::RemoteToolsInterface::Get()->SetDesiredEndpoint(ScriptCanvas::RemoteToolsKey, info.GetPersistentId());
+                AzFramework::RemoteToolsInterface::Get()->SetDesiredEndpoint(AzFramework::ScriptCanvasToolsKey, info.GetPersistentId());
             }
         }
     }

+ 3 - 11
Gems/ScriptCanvas/Code/Editor/View/Widgets/LoggingPanel/LiveWindowSession/LiveLoggingWindowSession.h

@@ -31,7 +31,7 @@ namespace ScriptCanvasEditor
 
         TargetManagerModel();
 
-        // QAbstarctItemModel
+        // QAbstractItemModel
         int rowCount(const QModelIndex& parent = QModelIndex()) const override;
         QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
         ////
@@ -43,7 +43,6 @@ namespace ScriptCanvasEditor
         int GetRowForTarget(AZ::u32 targetId);
 
     private:
-
         void ScrapeTargetInfo();
 
         AZStd::vector<AzFramework::RemoteToolsEndpointInfo> m_targetInfo;
@@ -76,7 +75,6 @@ namespace ScriptCanvasEditor
     
     class LiveLoggingWindowSession
         : public LoggingWindowSession
-        , public AzToolsFramework::EditorEntityContextNotificationBus::Handler
         , public ScriptCanvas::Debugger::ServiceNotificationsBus::Handler
     {
         Q_OBJECT
@@ -94,11 +92,6 @@ namespace ScriptCanvasEditor
         void TargetLeftNetwork(AzFramework::RemoteToolsEndpointInfo info);
         ////
 
-        // AzToolsFramework::EditorEntityContextNotificationBus::Handler
-        void OnStartPlayInEditorBegin() override;
-        void OnStopPlayInEditor() override;
-        ////
-
         // ScriptCavnas::Debugger::ServiceNotificationsBus
         void Connected(ScriptCanvas::Debugger::Target& target) override;
         ////
@@ -108,9 +101,9 @@ namespace ScriptCanvasEditor
         void OnCaptureButtonPressed() override;
         void OnPlaybackButtonPressed() override;
         void OnOptionsButtonPressed() override;
-    
+
         void OnTargetChanged(int currentIndex) override;
-        
+
     private:
 
         void OnAutoCaptureToggled(bool checked);
@@ -125,7 +118,6 @@ namespace ScriptCanvasEditor
 
         TargetManagerModel* m_targetManagerModel;
 
-        bool m_startedSession;
         bool m_encodeStaticEntities;
         
         bool m_isCapturing;

+ 3 - 2
Gems/ScriptCanvas/Code/Editor/View/Widgets/ScriptCanvasNodePaletteDockWidget.cpp

@@ -668,6 +668,8 @@ namespace ScriptCanvasEditor
 
             if (!paletteConfig.m_isInContextMenu)
             {
+                // Now that scriptcanvas is a separate application, cannot use AssetEditorRequestsBus 
+                /*
                 QMenu* creationMenu = new QMenu();
 
                 auto scriptEventAction = creationMenu->addAction("New Script Event");
@@ -682,8 +684,7 @@ namespace ScriptCanvasEditor
                 //
 
                 AddSearchCustomizationWidget(m_newCustomEvent);
-
-                
+                */
 
                 {
                     m_nextCycleAction = new QAction(treeView);

+ 1 - 1
Gems/ScriptCanvas/Code/Editor/View/Widgets/ScriptCanvasNodePaletteDockWidget.h

@@ -216,7 +216,7 @@ namespace ScriptCanvasEditor
             AzToolsFramework::AssetBrowser::AssetBrowserFilterModel* m_assetModel;
             const NodePaletteModel& m_nodePaletteModel;
 
-            QToolButton* m_newCustomEvent;
+            // QToolButton* m_newCustomEvent; // See comment in code
 
             AZStd::unordered_set< ScriptCanvas::NodeTypeIdentifier > m_cyclingIdentifiers;
             GraphCanvas::NodeFocusCyclingHelper m_cyclingHelper;

+ 0 - 3
Gems/ScriptCanvas/Code/Editor/View/Widgets/UnitTestPanel/UnitTestDockWidget.cpp

@@ -427,9 +427,6 @@ namespace ScriptCanvasEditor
 
     void UnitTestDockWidget::OpenScriptInEditor(AZ::Uuid sourceUuid)
     {
-        AzToolsFramework::OpenViewPane(LyViewPane::ScriptCanvas);
-        AZ::Data::AssetId sourceAssetId(sourceUuid, 0);
-
         AZ::Outcome<int, AZStd::string> openOutcome = AZ::Failure(AZStd::string());
         GeneralRequestBus::BroadcastResult(openOutcome, &GeneralRequests::OpenScriptCanvasAssetId
             , SourceHandle(nullptr, sourceUuid)

+ 43 - 4
Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp

@@ -33,6 +33,8 @@
 #include <QProgressDialog>
 #include <QToolButton>
 
+#include <AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h>
+
 #include <ScriptEvents/ScriptEventsAsset.h>
 
 #include <Editor/GraphCanvas/Components/MappingComponent.h>
@@ -83,7 +85,6 @@
 #include <AzFramework/StringFunc/StringFunc.h>
 
 #include <AzToolsFramework/ActionManager/HotKey/HotKeyManagerInterface.h>
-#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
 #include <AzToolsFramework/AssetBrowser/AssetBrowserModel.h>
 #include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h>
 #include <AzToolsFramework/AssetBrowser/Entries/SourceAssetBrowserEntry.h>
@@ -359,7 +360,7 @@ namespace ScriptCanvasEditor
     // MainWindow
     ////////////////
 
-    MainWindow::MainWindow(QWidget* parent)
+    MainWindow::MainWindow(const AZ::Crc32& toolId, QWidget* parent)
         : QMainWindow(parent, Qt::Widget | Qt::WindowMinMaxButtonsHint)
         , ui(new Ui::MainWindow)
         , m_loadingNewlySavedFile(false)
@@ -375,11 +376,34 @@ namespace ScriptCanvasEditor
         , m_systemTickActions(0)
         , m_closeCurrentGraphAfterSave(false)
         , m_styleManager(ScriptCanvasEditor::AssetEditorId, "ScriptCanvas/StyleSheet/graphcanvas_style.json")
+        , m_toolId(toolId)
     {
-        AZ_PROFILE_FUNCTION(ScriptCanvas);
-
+        AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect(m_toolId);
         VariablePaletteRequestBus::Handler::BusConnect();
         GraphCanvas::AssetEditorAutomationRequestBus::Handler::BusConnect(ScriptCanvasEditor::AssetEditorId);
+        AssetBrowserComponentNotificationBus::Handler::BusConnect();
+
+        bool isReady = false;
+        AzToolsFramework::AssetBrowser::AssetBrowserComponentRequestBus::BroadcastResult(
+            isReady, &AzToolsFramework::AssetBrowser::AssetBrowserComponentRequests::AreEntriesReady);
+        if (isReady)
+        {
+            InitMainWindow(); // Will be init during OnAssetBrowserComponentReady() otherwise
+        }
+    }
+
+    void MainWindow::InitMainWindow()
+    {
+        AZ_PROFILE_FUNCTION(ScriptCanvas);
+
+        static bool alreadyInit = false;
+        if (alreadyInit)
+        {
+            assert(false && "ScriptCanvas InitMainWindow() called twice, this shouldn't happen");
+            return;
+        }
+
+        alreadyInit = true;
 
         AZStd::array<char, AZ::IO::MaxPathLength> unresolvedPath;
         AZ::IO::FileIOBase::GetInstance()->ResolvePath("@products@/translation/scriptcanvas_en_us.qm", unresolvedPath.data(), unresolvedPath.size());
@@ -675,6 +699,7 @@ namespace ScriptCanvasEditor
     {
         m_workspace->Save();
 
+        AssetBrowserComponentNotificationBus::Handler::BusDisconnect();
         ScriptCanvas::BatchOperationNotificationBus::Handler::BusDisconnect();
         GraphCanvas::AssetEditorRequestBus::Handler::BusDisconnect();
         UndoNotificationBus::Handler::BusDisconnect();
@@ -683,6 +708,7 @@ namespace ScriptCanvasEditor
         GraphCanvas::AssetEditorAutomationRequestBus::Handler::BusDisconnect();
         ScriptCanvas::ScriptCanvasSettingsRequestBus::Handler::BusDisconnect();
         AzToolsFramework::AssetSystemBus::Handler::BusDisconnect();
+        AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusDisconnect();
 
         if (auto hotKeyManagerInterface = AZ::Interface<AzToolsFramework::HotKeyManagerInterface>::Get())
         {
@@ -1033,6 +1059,14 @@ namespace ScriptCanvasEditor
         return output;
     }
 
+    void MainWindow::OnDocumentOpened(const AZ::Uuid& documentId)
+    {
+        AZStd::string result;
+        AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(
+            result, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
+        OpenFile(result.c_str());
+    }
+
     void MainWindow::OpenValidationPanel()
     {
         if (!m_validationDockWidget->isVisible())
@@ -3983,6 +4017,11 @@ namespace ScriptCanvasEditor
         PopPreventUndoStateUpdate();
     }
 
+    void MainWindow::OnAssetBrowserComponentReady()
+    {
+        InitMainWindow();
+    }
+
     void MainWindow::PrepareActiveAssetForSave()
     {
         PrepareAssetForSave(m_activeGraph);

+ 19 - 1
Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h

@@ -17,13 +17,17 @@
 #include <QToolButton>
 #include <QWidget>
 
+#include <AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h>
+
 #include <AzCore/Component/ComponentApplicationBus.h>
 #include <AzCore/Component/EntityId.h>
 #include <AzCore/Asset/AssetCommon.h>
 #include <AzCore/Asset/AssetManagerBus.h>
+#include <AzCore/Math/Crc.h>
 
 #include <AzFramework/Asset/AssetCatalogBus.h>
 
+#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
 #include <AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h>
 
 #include <AzQtComponents/Components/WindowDecorationWrapper.h>
@@ -228,6 +232,8 @@ namespace ScriptCanvasEditor
         , private VariablePaletteRequestBus::Handler
         , private ScriptCanvas::BatchOperationNotificationBus::Handler
         , private AssetGraphSceneBus::Handler
+        , private AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler
+        , private AzToolsFramework::AssetBrowser::AssetBrowserComponentNotificationBus::Handler
 #if SCRIPTCANVAS_EDITOR
         //, public IEditorNotifyListener
 #endif
@@ -256,10 +262,12 @@ namespace ScriptCanvasEditor
 
     public:
 
-        explicit MainWindow(QWidget* parent = nullptr);
+        MainWindow(const AZ::Crc32& toolId, QWidget* parent = nullptr);
         ~MainWindow() override;
 
     private:
+        void InitMainWindow();
+
         // UIRequestBus
         QMainWindow* GetMainWindow() override { return qobject_cast<QMainWindow*>(this); }
         void OpenValidationPanel() override;
@@ -283,6 +291,10 @@ namespace ScriptCanvasEditor
             const VariablePaletteRequests::VariableConfigurationInput& input, const QPoint& scenePosition) override;
         ////
 
+        // AtomToolsDocumentNotificationBus
+        void OnDocumentOpened(const AZ::Uuid& documentId) override;
+        // ~AtomToolsDocumentNotificationBus
+
         // GraphCanvas::AssetEditorRequestBus
         void OnSelectionManipulationBegin() override;
         void OnSelectionManipulationEnd() override;
@@ -322,6 +334,10 @@ namespace ScriptCanvasEditor
         void OnCommandStarted(AZ::Crc32 commandTag) override;
         void OnCommandFinished(AZ::Crc32 commandTag) override;
 
+        //! AssetBrowserComponentNotificationBus
+        void OnAssetBrowserComponentReady() override;
+        ////
+
         // File menu
         void OnFileNew();
 
@@ -769,5 +785,7 @@ namespace ScriptCanvasEditor
         void MarkRecentSave(const SourceHandle& handle);
         AZStd::recursive_mutex m_mutex;
         AZStd::unordered_map <AZStd::string, AZStd::chrono::steady_clock::time_point> m_saves;
+
+        const AZ::Crc32 m_toolId = {};
     };
 }

+ 0 - 9
Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/API.cpp

@@ -14,14 +14,5 @@ namespace ScriptCanvas
     {
         const AZ::u64 k_serviceNotificationsMsgSlotId = AZ_CRC_CE("ScriptCanvasDebugServiceNotifications");
         const AZ::u64 k_clientRequestsMsgSlotId = AZ_CRC_CE("ScriptCanvasDebugClientRequests");
-
-        AZ::Outcome<void, AZStd::string> IsTargetConnectable(const AzFramework::RemoteToolsEndpointInfo& target)
-        {
-            if (!target.IsValid())
-            {
-                return AZ::Failure(AZStd::string("The target is invalid, it has never been seen"));
-            }
-            return AZ::Success();
-        }
     }
 }

+ 0 - 1
Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/API.h

@@ -43,7 +43,6 @@ namespace ScriptCanvas
         extern const AZ::u64 k_serviceNotificationsMsgSlotId;
         extern const AZ::u64 k_clientRequestsMsgSlotId;
 
-        AZ::Outcome<void, AZStd::string> IsTargetConnectable(const AzFramework::RemoteToolsEndpointInfo& target);
         void ReflectArguments(AZ::ReflectContext* context);
         void ReflectNotifications(AZ::ReflectContext* context);
         void ReflectRequests(AZ::ReflectContext* context);

+ 3 - 10
Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/Bus.h

@@ -69,12 +69,9 @@ namespace ScriptCanvas
             virtual ~ClientRequests() = default;
 
             // Target Management Methods
-            virtual AzFramework::RemoteToolsEndpointContainer EnumerateAvailableNetworkTargets() { return AzFramework::RemoteToolsEndpointContainer(); }
-
-            virtual bool HasValidConnection() const { return false; }
-            virtual bool IsConnected(const AzFramework::RemoteToolsEndpointInfo&) const { return false; }
-            virtual bool IsConnectedToSelf() const { return false; }
-            virtual AzFramework::RemoteToolsEndpointInfo GetNetworkTarget() { return AzFramework::RemoteToolsEndpointInfo(); }
+            virtual AzFramework::RemoteToolsEndpointContainer EnumerateAvailableNetworkTargets() const { return AzFramework::RemoteToolsEndpointContainer(); }
+            virtual void SetNetworkTarget([[maybe_unused]] AzFramework::RemoteToolsEndpointInfo target) {}
+            virtual AzFramework::RemoteToolsEndpointInfo GetNetworkTarget() const { return AzFramework::RemoteToolsEndpointInfo(); }
 
             // Control Methods
             virtual void AddBreakpoint(const Breakpoint&) {}
@@ -101,10 +98,6 @@ namespace ScriptCanvas
         class ClientUIRequests : public AZ::EBusTraits
         {
         public:
-
-            virtual void StartEditorSession() = 0;
-            virtual void StopEditorSession() = 0;
-
             virtual void StartLogging(ScriptTarget& initialTargets) = 0;
             virtual void StopLogging() = 0;
 

+ 139 - 186
Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/ClientTransceiver.cpp

@@ -11,7 +11,7 @@
 #include "Messages/Request.h"
 #include "Messages/Notify.h"
 
-#include <ScriptCanvas/Utils/ScriptCanvasConstants.h>
+#include <AzFramework/Script/ScriptRemoteDebuggingConstants.h>
 
 using namespace AzFramework;
 
@@ -25,28 +25,27 @@ namespace ScriptCanvas
             ClientUIRequestBus::Handler::BusConnect();
             AZ::SystemTickBus::Handler::BusConnect();
 
-            DiscoverNetworkTargets();
+            m_remoteToolsEndpointJoinedHandler = AzFramework::RemoteToolsEndpointStatusEvent::Handler(
+                [this]([[maybe_unused]] AzFramework::RemoteToolsEndpointInfo info)
+                {
+                    OnRemoteToolsEndpointListChanged();
+                });
 
-            for (auto& idAndInfo : m_networkTargets)
-            {
-                if (idAndInfo.second.IsSelf())
+            m_remoteToolsEndpointLeftHandler = AzFramework::RemoteToolsEndpointStatusEvent::Handler(
+                [this]([[maybe_unused]] AzFramework::RemoteToolsEndpointInfo info)
                 {
-                    m_selfTarget = idAndInfo.second;
-                    SCRIPT_CANVAS_DEBUGGER_TRACE_CLIENT("Self found!");
-                    break;
-                }
-            }
+                    OnRemoteToolsEndpointListChanged();
+                });
 
-            if (m_selfTarget.IsValid())
-            { 
-                m_currentTarget = m_selfTarget;
-                DesiredTargetConnected(true);
-            }
-            else
+            if (auto* remoteToolsInterface = AzFramework::RemoteToolsInterface::Get())
             {
-                SCRIPT_CANVAS_DEBUGGER_TRACE_CLIENT("Self NOT found!");
+                remoteToolsInterface->RegisterRemoteToolsEndpointJoinedHandler(
+                    AzFramework::ScriptCanvasToolsKey, m_remoteToolsEndpointJoinedHandler);
+                remoteToolsInterface->RegisterRemoteToolsEndpointLeftHandler(AzFramework::ScriptCanvasToolsKey, m_remoteToolsEndpointLeftHandler);
             }
 
+            OnRemoteToolsEndpointListChanged();
+
             m_addCache.m_logExecution = true;
             m_removeCache.m_logExecution = false;
         }
@@ -60,10 +59,11 @@ namespace ScriptCanvas
 
         void ClientTransceiver::AddBreakpoint(const Breakpoint& breakpoint)
         {
-            SCRIPT_CANVAS_DEBUGGER_TRACE_CLIENT("TRX sending AddBreakpoint Request %s", breakpoint.ToString().data());
-            if (AzFramework::IRemoteTools* remoteTools = RemoteToolsInterface::Get())
+            AzFramework::RemoteToolsEndpointInfo target = GetNetworkTarget();
+            if (target.IsValid())
             {
-                remoteTools->SendRemoteToolsMessage(m_currentTarget, Message::AddBreakpointRequest(breakpoint));
+                SCRIPT_CANVAS_DEBUGGER_TRACE_CLIENT("TRX sending AddBreakpoint Request %s", breakpoint.ToString().data());
+                RemoteToolsInterface::Get()->SendRemoteToolsMessage(target, Message::AddBreakpointRequest(breakpoint));
             }
         }
 
@@ -74,10 +74,47 @@ namespace ScriptCanvas
 
         void ClientTransceiver::Break()
         {
-            SCRIPT_CANVAS_DEBUGGER_TRACE_CLIENT("TRX Sending Break Request %s", m_currentTarget.GetDisplayName());
-            RemoteToolsInterface::Get()->SendRemoteToolsMessage(m_currentTarget, Message::BreakRequest());
+            AzFramework::RemoteToolsEndpointInfo target = GetNetworkTarget();
+            if (target.IsValid())
+            {
+                SCRIPT_CANVAS_DEBUGGER_TRACE_CLIENT("TRX Sending Break Request %s", target.GetDisplayName());
+                RemoteToolsInterface::Get()->SendRemoteToolsMessage(target, Message::BreakRequest());
+            }
         }
-        
+
+        void ClientTransceiver::OnRemoteToolsEndpointListChanged()
+        {
+            AzFramework::RemoteToolsEndpointInfo target = GetNetworkTarget();
+            if (!target.IsValid())
+            {
+                ConnectToFirstTargetIfNotConnected();
+            }
+        }
+
+        void ClientTransceiver::ConnectToFirstTargetIfNotConnected()
+        {
+            auto* remoteToolsInterface = AzFramework::RemoteToolsInterface::Get();
+            if (!remoteToolsInterface)
+                return;
+
+            if (remoteToolsInterface->GetDesiredEndpoint(AzFramework::ScriptCanvasToolsKey).IsValid())
+                return; // If we are already connected to a target, we don't do anything
+
+            AzFramework::RemoteToolsEndpointContainer targets;
+            remoteToolsInterface->EnumTargetInfos(AzFramework::ScriptCanvasToolsKey, targets);
+            for (const auto& [_, info] : targets)
+            {
+                if (!info.IsSelf() && info.IsOnline())
+                {
+                    SetNetworkTarget(info);
+                    return;
+                }
+            }
+
+            // No valid target found
+            SetNetworkTarget(AzFramework::RemoteToolsEndpointInfo());
+        }
+
         void ClientTransceiver::BreakpointAdded(const Breakpoint& breakpoint)
         {
             Lock lock(m_mutex);
@@ -94,6 +131,7 @@ namespace ScriptCanvas
                 ServiceNotificationsBus::Broadcast(&ServiceNotifications::BreakPointAdded, breakpoint);
             }
         }
+
         void ClientTransceiver::ClearMessages()
         {
             Lock guard(m_msgMutex);
@@ -102,80 +140,66 @@ namespace ScriptCanvas
 
         void ClientTransceiver::Continue()
         {
-            SCRIPT_CANVAS_DEBUGGER_TRACE_CLIENT("TRX Sending Continue Request %s", m_currentTarget.GetDisplayName());
-            RemoteToolsInterface::Get()->SendRemoteToolsMessage(m_currentTarget, Message::ContinueRequest());
-        }
-
-        void ClientTransceiver::DesiredTargetConnected(bool connected)
-        {
-            if (connected)
-            {
-                SCRIPT_CANVAS_DEBUGGER_TRACE_CLIENT("DesiredTarget connected!, sending connect request to %s", m_currentTarget.GetDisplayName());
-            }
-            else
-            {
-                SCRIPT_CANVAS_DEBUGGER_TRACE_CLIENT("DesiredTarget NOT connected!");
-                m_currentTarget = AzFramework::RemoteToolsEndpointInfo();
-            }
-
-            ClientUINotificationBus::Broadcast(&ClientUINotifications::OnCurrentTargetChanged);
-            
-            if (m_currentTarget.IsValid())
-            {
-                RemoteToolsInterface::Get()->SendRemoteToolsMessage(m_currentTarget, Message::ConnectRequest(m_connectionState));
-            }
-        }
-
-        void ClientTransceiver::DesiredTargetChanged([[maybe_unused]] AZ::u32 newId, [[maybe_unused]] AZ::u32 oldId)
-        {
-            if (HasValidConnection())
+            AzFramework::RemoteToolsEndpointInfo target = GetNetworkTarget();
+            if (target.IsValid())
             {
-                DisconnectFromTarget();
+                SCRIPT_CANVAS_DEBUGGER_TRACE_CLIENT("TRX Sending Continue Request %s", target.GetDisplayName());
+                RemoteToolsInterface::Get()->SendRemoteToolsMessage(target, Message::ContinueRequest());
             }
         }
         
-        AzFramework::RemoteToolsEndpointContainer ClientTransceiver::EnumerateAvailableNetworkTargets()
-        {
-            return m_networkTargets;
-        }
-
-        void ClientTransceiver::DiscoverNetworkTargets()
+        AzFramework::RemoteToolsEndpointContainer ClientTransceiver::EnumerateAvailableNetworkTargets() const
         {
             AzFramework::RemoteToolsEndpointContainer targets;
             if (AzFramework::IRemoteTools* remoteTools = RemoteToolsInterface::Get())
             {
-                remoteTools->EnumTargetInfos(ScriptCanvas::RemoteToolsKey, targets);
+                remoteTools->EnumTargetInfos(AzFramework::ScriptCanvasToolsKey, targets);
             }
 
             AzFramework::RemoteToolsEndpointContainer connectableTargets;
-            
+
             for (auto& idAndInfo : targets)
             {
                 const auto& targetInfo = idAndInfo.second;
-                auto isConnectable = IsTargetConnectable(targetInfo);
-                if (isConnectable.IsSuccess())
+                if (targetInfo.IsValid() && targetInfo.IsOnline())
                 {
                     connectableTargets[idAndInfo.first] = idAndInfo.second;
                     SCRIPT_CANVAS_DEBUGGER_TRACE_CLIENT("Debugger TRX can connect to %s", targetInfo.GetDisplayName());
                 }
                 else
                 {
-                    SCRIPT_CANVAS_DEBUGGER_TRACE_CLIENT("Debugger TRX can't connect to %s because: %s", targetInfo.GetDisplayName(), isConnectable.GetError().c_str());
+                    SCRIPT_CANVAS_DEBUGGER_TRACE_CLIENT(
+                        "Debugger TRX can't connect to %s because: %s", targetInfo.GetDisplayName(), isConnectable.GetError().c_str());
                 }
             }
 
+            return connectableTargets;
+        }
+
+        void ClientTransceiver::SetNetworkTarget(AzFramework::RemoteToolsEndpointInfo target)
+        {
+            AzFramework::RemoteToolsEndpointInfo previousTarget = GetNetworkTarget();
+            if (previousTarget.IsValid())
             {
-                Lock lock(m_mutex);
-                m_networkTargets = connectableTargets;
+                RemoteToolsInterface::Get()->SendRemoteToolsMessage(previousTarget, Message::DisconnectRequest());
             }
+
+            ClearMessages();
+            if (target.IsValid())
+            {
+                RemoteToolsInterface::Get()->SetDesiredEndpoint(AzFramework::ScriptCanvasToolsKey, target.GetPersistentId());
+                RemoteToolsInterface::Get()->SendRemoteToolsMessage(target, Message::ConnectRequest(m_connectionState));
+            }
+
+            ClientUINotificationBus::Broadcast(&ClientUINotifications::OnCurrentTargetChanged);
         }
 
-        AzFramework::RemoteToolsEndpointInfo ClientTransceiver::GetNetworkTarget()
+        AzFramework::RemoteToolsEndpointInfo ClientTransceiver::GetNetworkTarget() const
         {
             AzFramework::RemoteToolsEndpointInfo targetInfo;
             if (AzFramework::IRemoteTools* remoteTools = RemoteToolsInterface::Get())
             {
-                targetInfo = remoteTools->GetDesiredEndpoint(ScriptCanvas::RemoteToolsKey);
+                targetInfo = remoteTools->GetDesiredEndpoint(AzFramework::ScriptCanvasToolsKey);
             }
 
             if (!targetInfo.GetPersistentId())
@@ -184,10 +208,9 @@ namespace ScriptCanvas
                 return AzFramework::RemoteToolsEndpointInfo();
             }
 
-            auto isConnectable = IsTargetConnectable(targetInfo);
-            if (!isConnectable.IsSuccess())
+            if (!targetInfo.IsValid() || !targetInfo.IsOnline())
             {
-                SCRIPT_CANVAS_DEBUGGER_TRACE_CLIENT("Debugger TRX has no target because: %s", isConnectable.GetError().c_str());
+                SCRIPT_CANVAS_DEBUGGER_TRACE_CLIENT("The target is currently not in a state that would allow debugging code (offline or not debuggable)");
                 return AzFramework::RemoteToolsEndpointInfo();
             }
 
@@ -196,20 +219,32 @@ namespace ScriptCanvas
         
         void ClientTransceiver::GetAvailableScriptTargets()
         {
-            SCRIPT_CANVAS_DEBUGGER_TRACE_CLIENT("TRX sending GetAvailableScriptTargets Request %s", m_currentTarget.GetDisplayName());
-            RemoteToolsInterface::Get()->SendRemoteToolsMessage(m_currentTarget, Message::GetAvailableScriptTargets());
+            AzFramework::RemoteToolsEndpointInfo target = GetNetworkTarget();
+            if (target.IsValid())
+            {
+                SCRIPT_CANVAS_DEBUGGER_TRACE_CLIENT("TRX sending GetAvailableScriptTargets Request %s", target.GetDisplayName());
+                RemoteToolsInterface::Get()->SendRemoteToolsMessage(target, Message::GetAvailableScriptTargets());
+            }
         }
         
         void ClientTransceiver::GetActiveEntities()
         {
-            SCRIPT_CANVAS_DEBUGGER_TRACE_CLIENT("TRX sending GetActiveEntities Request %s", m_currentTarget.GetDisplayName());
-            RemoteToolsInterface::Get()->SendRemoteToolsMessage(m_currentTarget, Message::GetActiveEntitiesRequest());
+            AzFramework::RemoteToolsEndpointInfo target = GetNetworkTarget();
+            if (target.IsValid())
+            {
+                SCRIPT_CANVAS_DEBUGGER_TRACE_CLIENT("TRX sending GetActiveEntities Request %s", target.GetDisplayName());
+                RemoteToolsInterface::Get()->SendRemoteToolsMessage(target, Message::GetActiveEntitiesRequest());
+            }
         }
 
         void ClientTransceiver::GetActiveGraphs()
         {
-            SCRIPT_CANVAS_DEBUGGER_TRACE_CLIENT("TRX sending GetActiveGraphs Request %s", m_currentTarget.GetDisplayName());
-            RemoteToolsInterface::Get()->SendRemoteToolsMessage(m_currentTarget, Message::GetActiveGraphsRequest());
+            AzFramework::RemoteToolsEndpointInfo target = GetNetworkTarget();
+            if (target.IsValid())
+            {
+                SCRIPT_CANVAS_DEBUGGER_TRACE_CLIENT("TRX sending GetActiveGraphs Request %s", target.GetDisplayName());
+                RemoteToolsInterface::Get()->SendRemoteToolsMessage(target, Message::GetActiveGraphsRequest());
+            }
         }
         
         void ClientTransceiver::GetVariableValue()
@@ -217,21 +252,6 @@ namespace ScriptCanvas
 
         }
 
-        bool ClientTransceiver::HasValidConnection() const
-        {
-            return m_currentTarget.IsValid();
-        }
-
-        bool ClientTransceiver::IsConnected(const AzFramework::RemoteToolsEndpointInfo& targetInfo) const
-        {
-            return m_currentTarget.IsIdentityEqualTo(targetInfo);
-        }
-
-        bool ClientTransceiver::IsConnectedToSelf() const
-        {
-            return IsConnected(m_selfTarget) || !m_currentTarget.IsValid();
-        }
-
         void ClientTransceiver::OnReceivedMsg(AzFramework::RemoteToolsMessagePointer msg)
         {
             {
@@ -279,19 +299,6 @@ namespace ScriptCanvas
             }
         }
 
-        void ClientTransceiver::DisconnectFromTarget()
-        {
-            if (AzFramework::IRemoteTools* remoteTools = RemoteToolsInterface::Get())
-            {
-                remoteTools->SendRemoteToolsMessage(m_currentTarget, Message::DisconnectRequest());
-            }
-        }
-
-        void ClientTransceiver::CleanupConnection()
-        {
-            ClearMessages();
-        }
-
         void ClientTransceiver::RemoveBreakpoint(const Breakpoint&)
         {
 
@@ -309,42 +316,11 @@ namespace ScriptCanvas
 
         void ClientTransceiver::StepOver()
         {
-            SCRIPT_CANVAS_DEBUGGER_TRACE_CLIENT("TRX Sending StepOver Request %s", m_currentTarget.GetDisplayName());
-            RemoteToolsInterface::Get()->SendRemoteToolsMessage(m_currentTarget, Message::StepOverRequest());
-        }
-
-        void ClientTransceiver::TargetJoinedNetwork(AzFramework::RemoteToolsEndpointInfo info)
-        {
-            auto isConnectable = IsTargetConnectable(info);
-            if (isConnectable.IsSuccess())
+            AzFramework::RemoteToolsEndpointInfo target = GetNetworkTarget();
+            if (target.IsValid())
             {
-                m_networkTargets.emplace(info.GetPersistentId(), info);
-                ServiceNotificationsBus::Broadcast(&ServiceNotifications::BecameUnavailable, Target(info));
-            }
-        }
-
-        void ClientTransceiver::TargetLeftNetwork(AzFramework::RemoteToolsEndpointInfo info)
-        {
-            bool eventNeeded = false;
-
-            if (info.IsIdentityEqualTo(m_currentTarget))
-            {
-                CleanupConnection();
-                eventNeeded = true;
-            }
-            else
-            {
-                auto iter = m_networkTargets.find(info.GetPersistentId());
-                if (iter != m_networkTargets.end())
-                {
-                    m_networkTargets.erase(iter);
-                    eventNeeded = true;
-                }
-            }
-
-            if (eventNeeded)
-            {
-                ServiceNotificationsBus::Broadcast(&ServiceNotifications::BecameUnavailable, Target(info));
+                SCRIPT_CANVAS_DEBUGGER_TRACE_CLIENT("TRX Sending StepOver Request %s", target.GetDisplayName());
+                RemoteToolsInterface::Get()->SendRemoteToolsMessage(target, Message::StepOverRequest());
             }
         }
 
@@ -384,7 +360,7 @@ namespace ScriptCanvas
 
         void ClientTransceiver::Visit(Message::Connected& notification)
         {
-            if (notification.m_target.m_info.IsIdentityEqualTo(m_currentTarget))
+            if (notification.m_target.m_info.IsIdentityEqualTo(GetNetworkTarget()))
             {
                 SCRIPT_CANVAS_DEBUGGER_TRACE_CLIENT("Neat. we're connected");
                 ServiceNotificationsBus::Broadcast(&ServiceNotifications::Connected, notification.m_target);
@@ -399,22 +375,14 @@ namespace ScriptCanvas
         {
             SCRIPT_CANVAS_DEBUGGER_TRACE_CLIENT("Disconnect Notification Received");
             ServiceNotificationsBus::Broadcast(&ServiceNotifications::Disconnected);
-
-            CleanupConnection();
-
-            if (m_resetDesiredTarget)
-            {
-                m_resetDesiredTarget = false;
-                RemoteToolsInterface::Get()->SetDesiredEndpointInfo(ScriptCanvas::RemoteToolsKey, m_previousDesiredInfo);
-                m_currentTarget = AzFramework::RemoteToolsEndpointInfo();
-            }
+            ClearMessages();
         }
 
         void ClientTransceiver::Visit([[maybe_unused]] Message::Continued& notification)
         {
             SCRIPT_CANVAS_DEBUGGER_TRACE_CLIENT("received continue notification!");
             Target connectedTarget;
-            connectedTarget.m_info = m_currentTarget;
+            connectedTarget.m_info = GetNetworkTarget();
 
             ServiceNotificationsBus::Broadcast(&ServiceNotifications::Continued, connectedTarget);
         }
@@ -455,49 +423,32 @@ namespace ScriptCanvas
             if (!remoteTools)
                 return;
 
-            if (!m_addCache.m_entities.empty())
+            AzFramework::RemoteToolsEndpointInfo target = GetNetworkTarget();
+            if (target.IsValid())
             {
-                remoteTools->SendRemoteToolsMessage(m_currentTarget, Message::AddTargetsRequest(m_addCache));
-                m_connectionState.Merge(m_addCache);
-                m_addCache.Clear();
-            }
+                if (!m_addCache.m_entities.empty())
+                {
+                    remoteTools->SendRemoteToolsMessage(target, Message::AddTargetsRequest(m_addCache));
+                    m_connectionState.Merge(m_addCache);
+                    m_addCache.Clear();
+                }
 
-            if (!m_removeCache.m_entities.empty())
-            {
-                remoteTools->SendRemoteToolsMessage(m_currentTarget, Message::RemoveTargetsRequest(m_removeCache));
-                m_connectionState.Remove(m_removeCache);
-                m_removeCache.Clear();
+                if (!m_removeCache.m_entities.empty())
+                {
+                    remoteTools->SendRemoteToolsMessage(target, Message::RemoveTargetsRequest(m_removeCache));
+                    m_connectionState.Remove(m_removeCache);
+                    m_removeCache.Clear();
+                }
             }
 
-            const AzFramework::ReceivedRemoteToolsMessages* messages = remoteTools->GetReceivedMessages(ScriptCanvas::RemoteToolsKey);
+            const AzFramework::ReceivedRemoteToolsMessages* messages = remoteTools->GetReceivedMessages(AzFramework::ScriptCanvasToolsKey);
             if (messages)
             {
                 for (const AzFramework::RemoteToolsMessagePointer& msg : *messages)
                 {
                     OnReceivedMsg(msg);
                 }
-                remoteTools->ClearReceivedMessagesForNextTick(ScriptCanvas::RemoteToolsKey);
-            }
-        }
-
-        void ClientTransceiver::StartEditorSession()
-        {
-            if (!m_currentTarget.IsValid())
-            {
-                m_resetDesiredTarget = true;
-                if (AzFramework::IRemoteTools* remoteTools = RemoteToolsInterface::Get())
-                {
-                    m_previousDesiredInfo = remoteTools->GetDesiredEndpoint(ScriptCanvas::RemoteToolsKey);
-                    remoteTools->SetDesiredEndpointInfo(ScriptCanvas::RemoteToolsKey, m_selfTarget);
-                }
-            }
-        }
-
-        void ClientTransceiver::StopEditorSession()
-        {
-            if (m_resetDesiredTarget)
-            {
-                DisconnectFromTarget();
+                remoteTools->ClearReceivedMessagesForNextTick(AzFramework::ScriptCanvasToolsKey);
             }
         }
 
@@ -507,17 +458,19 @@ namespace ScriptCanvas
             m_connectionState.Clear();
             m_connectionState.Merge(initialTargets);
 
-            if (m_currentTarget.IsValid())
+            AzFramework::RemoteToolsEndpointInfo target = GetNetworkTarget();
+            if (target.IsValid())
             {
-                RemoteToolsInterface::Get()->SendRemoteToolsMessage(m_currentTarget, Message::StartLoggingRequest(initialTargets));
+                RemoteToolsInterface::Get()->SendRemoteToolsMessage(target, Message::StartLoggingRequest(initialTargets));
             }
         }
 
         void ClientTransceiver::StopLogging()
         {
-            if (AzFramework::IRemoteTools* remoteTools = RemoteToolsInterface::Get())
+            AzFramework::RemoteToolsEndpointInfo target = GetNetworkTarget();
+            if (target.IsValid())
             {
-                remoteTools->SendRemoteToolsMessage(m_currentTarget, Message::StopLoggingRequest());
+                RemoteToolsInterface::Get()->SendRemoteToolsMessage(target, Message::StopLoggingRequest());
             }
 
             m_connectionState.m_logExecution = false;

+ 13 - 33
Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/ClientTransceiver.h

@@ -25,7 +25,7 @@ namespace ScriptCanvas
     namespace Debugger
     {
         /**
-         * ClientTransceiver 
+         * ClientTransceiver - Editor/Tooling side only
          * listens to debugger service messages on the target manager bus, and translates them
          * to ServiceNotifications
          *
@@ -51,12 +51,9 @@ namespace ScriptCanvas
             
             //////////////////////////////////////////////////////////////////////////
             // ClientRequests
-            AzFramework::RemoteToolsEndpointContainer EnumerateAvailableNetworkTargets() override;
-
-            bool HasValidConnection() const override;
-            bool IsConnected(const AzFramework::RemoteToolsEndpointInfo&) const override;
-            bool IsConnectedToSelf() const override;
-            AzFramework::RemoteToolsEndpointInfo GetNetworkTarget() override;
+            AzFramework::RemoteToolsEndpointContainer EnumerateAvailableNetworkTargets() const override;
+            void SetNetworkTarget(AzFramework::RemoteToolsEndpointInfo target) override;
+            AzFramework::RemoteToolsEndpointInfo GetNetworkTarget() const override;
 
             void AddBreakpoint(const Breakpoint&) override;
             void AddVariableChangeBreakpoint(const VariableChangeBreakpoint&) override;
@@ -74,12 +71,6 @@ namespace ScriptCanvas
             void GetVariableValue() override;
             //////////////////////////////////////////////////////////////////////////
 
-            //////////////////////////////////////////////////////////////////////////
-            // TODO : Must be implemented via IRemoteTools handlers
-            void TargetJoinedNetwork(AzFramework::RemoteToolsEndpointInfo info);
-            void TargetLeftNetwork(AzFramework::RemoteToolsEndpointInfo info);
-            //////////////////////////////////////////////////////////////////////////
-
             void OnReceivedMsg(AzFramework::RemoteToolsMessagePointer msg);
 
             //////////////////////////////////////////////////////////////////////////
@@ -107,9 +98,6 @@ namespace ScriptCanvas
 
             //////////////////////////////////////////////////////////////////////////
             // ClientUIRequestBus
-            void StartEditorSession() override;
-            void StopEditorSession() override;
-
             void StartLogging(ScriptTarget& initialTargets) override;
             void StopLogging() override;
 
@@ -120,35 +108,27 @@ namespace ScriptCanvas
             void RemoveGraphLoggingTarget(const AZ::Data::AssetId& assetId) override;
             //////////////////////////////////////////////////////////////////////////
 
-        protected:
-            void DiscoverNetworkTargets();
+        private:
+            void OnRemoteToolsEndpointListChanged();
+            void ConnectToFirstTargetIfNotConnected();
+
             void BreakpointAdded(const Breakpoint& breakpoint);
             void ClearMessages();
             void ProcessMessages();
-            
-        private:
-            void DesiredTargetConnected(bool connected);
-            void DesiredTargetChanged(AZ::u32 newId, AZ::u32 oldId);
-            void DisconnectFromTarget();
-            void CleanupConnection();
 
+        private:
             Mutex m_mutex;
 
-            AzFramework::RemoteToolsEndpointInfo m_selfTarget;
+            AzFramework::RemoteToolsEndpointStatusEvent::Handler m_remoteToolsEndpointJoinedHandler;
+            AzFramework::RemoteToolsEndpointStatusEvent::Handler m_remoteToolsEndpointLeftHandler;
 
-            bool m_resetDesiredTarget = false;
-            AzFramework::RemoteToolsEndpointInfo m_previousDesiredInfo;
-
-            AzFramework::RemoteToolsEndpointInfo m_currentTarget;
             ScriptTarget m_connectionState;
+            ScriptTarget m_addCache;
+            ScriptTarget m_removeCache;
 
-            AzFramework::RemoteToolsEndpointContainer m_networkTargets;
             AZStd::unordered_set<Breakpoint> m_breakpointsActive;
             AZStd::unordered_set<Breakpoint> m_breakpointsInactive;
 
-            ScriptTarget m_addCache;
-            ScriptTarget m_removeCache;
-            
             Mutex m_msgMutex;
             AzFramework::RemoteToolsMessageQueue m_msgQueue;
         };

+ 7 - 6
Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/Debugger.cpp

@@ -7,6 +7,7 @@
  */
 
 #include <AzFramework/Entity/GameEntityContextBus.h>
+#include <AzFramework/Script/ScriptRemoteDebuggingConstants.h>
 
 #include "Debugger.h"
 #include "Messages/Notify.h"
@@ -14,7 +15,6 @@
 
 #include <ScriptCanvas/Core/GraphBus.h>
 #include <ScriptCanvas/Execution/RuntimeComponent.h>
-#include <ScriptCanvas/Utils/ScriptCanvasConstants.h>
 
 namespace ScriptCanvas
 {
@@ -57,7 +57,7 @@ namespace ScriptCanvas
         Message::Request* ServiceComponent::FilterMessage(AzFramework::RemoteToolsMessagePointer& msg)
         {
             AzFramework::RemoteToolsEndpointInfo client =
-                AzFramework::RemoteToolsInterface::Get()->GetEndpointInfo(ScriptCanvas::RemoteToolsKey, msg->GetSenderTargetId());
+                AzFramework::RemoteToolsInterface::Get()->GetEndpointInfo(AzFramework::ScriptCanvasToolsKey, msg->GetSenderTargetId());
 
             // cull messages without a target match
             if (!m_client.m_info.IsIdentityEqualTo(client))
@@ -150,14 +150,15 @@ namespace ScriptCanvas
             AzFramework::IRemoteTools* remoteTools = AzFramework::RemoteToolsInterface::Get();
             if (remoteTools)
             {
-                const AzFramework::ReceivedRemoteToolsMessages* messages = remoteTools->GetReceivedMessages(ScriptCanvas::RemoteToolsKey);
+                const AzFramework::ReceivedRemoteToolsMessages* messages =
+                    remoteTools->GetReceivedMessages(AzFramework::ScriptCanvasToolsKey);
                 if (messages)
                 {
                     for (const AzFramework::RemoteToolsMessagePointer& msg : *messages)
                     {
                         OnReceivedMsg(msg);
                     }
-                    remoteTools->ClearReceivedMessagesForNextTick(ScriptCanvas::RemoteToolsKey);
+                    remoteTools->ClearReceivedMessagesForNextTick(AzFramework::ScriptCanvasToolsKey);
                 }
             }
         }
@@ -221,10 +222,10 @@ namespace ScriptCanvas
                 {
                     this->RemoteToolsEndpointLeft(info);
                 });
-            m_remoteTools->RegisterRemoteToolsEndpointLeftHandler(ScriptCanvas::RemoteToolsKey, m_endpointLeftEventHandler);
+            m_remoteTools->RegisterRemoteToolsEndpointLeftHandler(AzFramework::ScriptCanvasToolsKey, m_endpointLeftEventHandler);
 
             AzFramework::RemoteToolsEndpointContainer targets;
-            m_remoteTools->EnumTargetInfos(ScriptCanvas::RemoteToolsKey, targets);
+            m_remoteTools->EnumTargetInfos(AzFramework::ScriptCanvasToolsKey, targets);
             for (auto& idAndInfo : targets)
             {
                 if (idAndInfo.second.IsSelf())

+ 2 - 1
Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/Debugger.h

@@ -26,7 +26,8 @@ namespace ScriptCanvas
 {
     namespace Debugger
     {
-        //! The ScriptCanvas debugger component, this is the runtime debugger code that directly controls the execution
+        //! The ScriptCanvas debugger component - Game side only
+        //! this is the runtime debugger code that directly controls the execution
         //! and provides insight into a running ScriptCanvas graph.
         class ServiceComponent
             : public AZ::Component

+ 0 - 18
Gems/ScriptCanvas/Code/Include/ScriptCanvas/Utils/ScriptCanvasConstants.h

@@ -1,18 +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/Name/Name.h>
-#include <AzCore/Name/NameDictionary.h>
-
-namespace ScriptCanvas
-{
-    static const AZ::Name RemoteToolsName = AZ::Name::FromStringLiteral("ScriptCanvasRemoteTools", nullptr);
-    static constexpr AZ::Crc32 RemoteToolsKey("ScriptCanvasRemoteTools");
-    static constexpr uint16_t RemoteToolsPort = 45641;
-}

+ 17 - 0
Gems/ScriptCanvas/Code/scriptcanvasgem_application_files.cmake

@@ -0,0 +1,17 @@
+#
+# 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
+#
+#
+
+set(FILES
+    Application/main.cpp
+    Application/ScriptCanvasApplication.cpp
+    Application/ScriptCanvasApplication.h
+    Application/ScriptCanvasApplicationResources.qrc
+    Application/Document/ScriptCanvasDocument.cpp
+    Application/Document/ScriptCanvasDocument.h
+    Application/Document/ScriptCanvasDocumentRequestBus.h
+)

+ 0 - 1
Gems/ScriptCanvas/Code/scriptcanvasgem_headers.cmake

@@ -337,7 +337,6 @@ set(FILES
     Include/ScriptCanvas/Utils/VersionConverters.h
     Include/ScriptCanvas/Utils/VersioningUtils.h
     Include/ScriptCanvas/Utils/BehaviorContextUtils.h
-    Include/ScriptCanvas/Utils/ScriptCanvasConstants.h
 )
 
 set(SKIP_UNITY_BUILD_INCLUSION_FILES