123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497 |
- /*
- * 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 <AzCore/Interface/Interface.h>
- #include <AzFramework/Script/ScriptRemoteDebuggingConstants.h>
- #include <AzToolsFramework/Entity/EditorEntityContextBus.h>
- #include <EditorCoreAPI.h>
- #include <IEditor.h>
- #include <QtWidgets/QLabel>
- #include <ScriptCanvas/Asset/RuntimeAsset.h>
- #include <Editor/View/Widgets/LoggingPanel/LiveWindowSession/LiveLoggingWindowSession.h>
- namespace ScriptCanvasEditor
- {
- ///////////////////////
- // TargetManagerModel
- ///////////////////////
- TargetManagerModel::TargetManagerModel()
- {
- AzFramework::RemoteToolsEndpointInfo editorTargetInfo("Editor");
- m_targetInfo.push_back(editorTargetInfo);
- ScrapeTargetInfo();
- }
- int TargetManagerModel::rowCount([[maybe_unused]] const QModelIndex& parent) const
- {
- return static_cast<int>(m_targetInfo.size());
- }
- QVariant TargetManagerModel::data(const QModelIndex& index, int role) const
- {
- if (!index.isValid())
- {
- return QVariant();
- }
- switch (role)
- {
- case Qt::DisplayRole:
- {
- const AzFramework::RemoteToolsEndpointInfo& targetInfo = m_targetInfo[index.row()];
- if (index.row() > 0)
- {
- return QString("%1 (%2)").arg(targetInfo.GetDisplayName(), QString::number(targetInfo.GetPersistentId(), 16));
- }
- else
- {
- return QString(targetInfo.GetDisplayName());
- }
- }
- break;
- default:
- break;
- }
- return QVariant();
- }
- void TargetManagerModel::TargetJoinedNetwork(AzFramework::RemoteToolsEndpointInfo info)
- {
- if (!info.IsSelf())
- {
- int element = GetRowForTarget(info.GetPersistentId());
- if (element < 0)
- {
- beginInsertRows(QModelIndex(), rowCount(), rowCount());
- m_targetInfo.push_back(info);
- endInsertRows();
- }
- }
- else
- {
- ScrapeTargetInfo();
- }
- }
- void TargetManagerModel::TargetLeftNetwork(AzFramework::RemoteToolsEndpointInfo info)
- {
- int element = GetRowForTarget(info.GetPersistentId());
- // 0 is reserved for our fake Editor one.
- // And we don't want to remove it.
- if (element > 0)
- {
- beginRemoveRows(QModelIndex(), element, element);
- m_targetInfo.erase(m_targetInfo.begin() + element);
- endRemoveRows();
- }
- }
- AzFramework::RemoteToolsEndpointInfo TargetManagerModel::FindTargetInfoForRow(int row)
- {
- if (row < 0 && row >= m_targetInfo.size())
- {
- return AzFramework::RemoteToolsEndpointInfo();
- }
- return m_targetInfo[row];
- }
- int TargetManagerModel::GetRowForTarget(AZ::u32 targetId)
- {
- for (size_t i = 0; i < m_targetInfo.size(); ++i)
- {
- if (m_targetInfo[i].GetPersistentId() == targetId)
- {
- return static_cast<int>(i);
- }
- }
- return -1;
- }
- void TargetManagerModel::ScrapeTargetInfo()
- {
- AzFramework::IRemoteTools* remoteTools = AzFramework::RemoteToolsInterface::Get();
- AzFramework::RemoteToolsEndpointContainer targets;
- if (remoteTools)
- {
- remoteTools->EnumTargetInfos(AzFramework::ScriptCanvasToolsKey, targets);
- }
- for (const auto& targetPair : targets)
- {
- if (!targetPair.second.IsSelf())
- {
- m_targetInfo.push_back(targetPair.second);
- }
- }
- }
- ////////////////////////////
- // LiveLoggingUserSettings
- ////////////////////////////
- AZStd::intrusive_ptr<LiveLoggingUserSettings> LiveLoggingUserSettings::FindSettingsInstance()
- {
- return AZ::UserSettings::CreateFind<LiveLoggingUserSettings>(AZ_CRC_CE("ScriptCanvas::LiveLoggingUserSettings"), AZ::UserSettings::CT_LOCAL);
- }
- void LiveLoggingUserSettings::Reflect(AZ::ReflectContext* reflectContext)
- {
- AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflectContext);
- if (serializeContext)
- {
- serializeContext->Class<LiveLoggingUserSettings>()
- ->Version(1)
- ->Field("AutoCapturing", &LiveLoggingUserSettings::m_isAutoCaptureEnabled)
- ->Field("LiveUpdating", &LiveLoggingUserSettings::m_enableLiveUpdates)
- ;
- }
- }
- void LiveLoggingUserSettings::SetAutoCaptureEnabled(bool enabled)
- {
- m_isAutoCaptureEnabled = enabled;
- }
- bool LiveLoggingUserSettings::IsAutoCaptureEnabled() const
- {
- return m_isAutoCaptureEnabled;
- }
- void LiveLoggingUserSettings::SetLiveUpdates(bool enabled)
- {
- m_enableLiveUpdates = enabled;
- }
- bool LiveLoggingUserSettings::IsLiveUpdating() const
- {
- return m_enableLiveUpdates;
- }
- /////////////////////////////
- // LiveLoggingWindowSession
- /////////////////////////////
- LiveLoggingWindowSession::LiveLoggingWindowSession(QWidget* parent)
- : LoggingWindowSession(parent)
- , m_encodeStaticEntities(false)
- , m_isCapturing(false)
- {
- m_targetManagerModel = aznew TargetManagerModel();
- {
- QSignalBlocker signalBlocker(m_ui->targetSelector);
- m_ui->targetSelector->setModel(m_targetManagerModel);
- }
- ScriptCanvas::Debugger::ServiceNotificationsBus::Handler::BusConnect();
- SetDataId(m_liveDataAggregator.GetDataId());
- RegisterTreeRoot(m_liveDataAggregator.GetTreeRoot());
- m_userSettings = LiveLoggingUserSettings::FindSettingsInstance();
- if (!m_userSettings->IsLiveUpdating())
- {
- m_liveDataAggregator.GetTreeRoot()->SetUpdatePolicy(DebugLogRootItem::UpdatePolicy::SingleTime);
- }
- else
- {
- m_liveDataAggregator.GetTreeRoot()->SetUpdatePolicy(DebugLogRootItem::UpdatePolicy::RealTime);
- }
-
- // Despite being apart of the base menu for now, the LiveLoggingWindow is the only one that needs to utilize these buttons.
- // Going to control them from here.
- m_ui->liveUpdatesToggle->setChecked(m_userSettings->IsLiveUpdating());
- QObject::connect(m_ui->liveUpdatesToggle, &QToolButton::toggled, this, &LiveLoggingWindowSession::OnLiveUpdateToggled);
- m_ui->autoCaptureToggle->setChecked(m_userSettings->IsAutoCaptureEnabled());
- QObject::connect(m_ui->autoCaptureToggle, &QToolButton::toggled, this, &LiveLoggingWindowSession::OnAutoCaptureToggled);
- if (!AzFramework::RemoteToolsInterface::Get())
- {
- m_ui->logTree->setHidden(true);
- m_ui->verticalLayout->setAlignment(Qt::AlignTop);
- QLabel* warnMessage = new QLabel("Please enable the **Remote Tools Connection** gem to use graph debugging features");
- warnMessage->setTextFormat(Qt::MarkdownText);
- m_ui->verticalLayout->addWidget(warnMessage);
- }
- }
- LiveLoggingWindowSession::~LiveLoggingWindowSession()
- {
- ScriptCanvas::Debugger::ServiceNotificationsBus::Handler::BusDisconnect();
- }
- void LiveLoggingWindowSession::DesiredTargetChanged(AZ::u32 newId, [[maybe_unused]] AZ::u32 oldId)
- {
- {
- QSignalBlocker signalBlocker(m_ui->targetSelector);
- int row = m_targetManagerModel->GetRowForTarget(newId);
- if (row < 0)
- {
- m_ui->targetSelector->setCurrentIndex(0);
- }
- else
- {
- m_ui->targetSelector->setCurrentIndex(row);
- }
- }
- }
- void LiveLoggingWindowSession::DesiredTargetConnected(bool connected)
- {
- {
- QSignalBlocker signalBlocker(m_ui->targetSelector);
- bool useFallback = !connected;
- if (connected)
- {
- const AzFramework::RemoteToolsEndpointInfo& desiredInfo =
- AzFramework::RemoteToolsInterface::Get()->GetDesiredEndpoint(AzFramework::ScriptCanvasToolsKey);
- if (desiredInfo.IsValid() && !desiredInfo.IsSelf())
- {
- int index = m_targetManagerModel->GetRowForTarget(desiredInfo.GetPersistentId());
- if (index > 0)
- {
- m_ui->targetSelector->setCurrentIndex(index);
- }
- }
- else
- {
- useFallback = true;
- }
- }
- else if (m_isCapturing)
- {
- SetIsCapturing(false);
- }
-
- if (useFallback)
- {
- m_ui->targetSelector->setCurrentIndex(0);
- }
- }
- }
- void LiveLoggingWindowSession::TargetJoinedNetwork(AzFramework::RemoteToolsEndpointInfo info)
- {
- {
- QSignalBlocker signalBlocker(m_ui->targetSelector);
- m_targetManagerModel->TargetJoinedNetwork(info);
- }
- }
- void LiveLoggingWindowSession::TargetLeftNetwork(AzFramework::RemoteToolsEndpointInfo info)
- {
- {
- QSignalBlocker signalBlocker(m_ui->targetSelector);
- m_targetManagerModel->TargetLeftNetwork(info);
- }
- }
- void LiveLoggingWindowSession::Connected([[maybe_unused]] ScriptCanvas::Debugger::Target& target)
- {
- if (m_userSettings->IsAutoCaptureEnabled() && isVisible())
- {
- SetIsCapturing(true);
- }
- }
- void LiveLoggingWindowSession::OnCaptureButtonPressed()
- {
- SetIsCapturing(!m_isCapturing);
- }
- void LiveLoggingWindowSession::OnPlaybackButtonPressed()
- {
- // Nothing to do in the LiveLoggingWindowSession
- }
- void LiveLoggingWindowSession::OnOptionsButtonPressed()
- {
- QPoint point = QCursor::pos();
- QMenu optionsMenu;
- QAction* autoCaptureAction = optionsMenu.addAction("Auto Capture");
- autoCaptureAction->setCheckable(true);
- autoCaptureAction->setChecked(m_userSettings->IsAutoCaptureEnabled());
- QObject::connect(autoCaptureAction, &QAction::toggled, this, &LiveLoggingWindowSession::OnAutoCaptureToggled);
- QAction* liveUpdateAction = optionsMenu.addAction("Live Updates");
- liveUpdateAction->setCheckable(true);
- liveUpdateAction->setChecked(m_userSettings->IsLiveUpdating());
- QObject::connect(liveUpdateAction, &QAction::toggled, this, &LiveLoggingWindowSession::OnLiveUpdateToggled);
- optionsMenu.exec(point);
- }
- void LiveLoggingWindowSession::OnTargetChanged(int index)
- {
- // Special case out the editor
- if (index == 0)
- {
- AzFramework::RemoteToolsInterface::Get()->SetDesiredEndpoint(AzFramework::ScriptCanvasToolsKey, 0);
- }
- else
- {
- AzFramework::RemoteToolsEndpointInfo info = m_targetManagerModel->FindTargetInfoForRow(index);
- if (info.IsValid())
- {
- AzFramework::RemoteToolsInterface::Get()->SetDesiredEndpoint(AzFramework::ScriptCanvasToolsKey, info.GetPersistentId());
- }
- }
- }
- void LiveLoggingWindowSession::OnAutoCaptureToggled(bool checked)
- {
- m_userSettings->SetAutoCaptureEnabled(checked);
- }
- void LiveLoggingWindowSession::OnLiveUpdateToggled(bool checked)
- {
- m_userSettings->SetLiveUpdates(checked);
- if (!m_userSettings->IsLiveUpdating())
- {
- m_liveDataAggregator.GetTreeRoot()->SetUpdatePolicy(DebugLogRootItem::UpdatePolicy::SingleTime);
- }
- else
- {
- // If we enable this we want to update the current display.
- m_liveDataAggregator.GetTreeRoot()->RedoLayout();
- m_liveDataAggregator.GetTreeRoot()->SetUpdatePolicy(DebugLogRootItem::UpdatePolicy::RealTime);
- }
- }
- void LiveLoggingWindowSession::StartDataCapture()
- {
- ScriptCanvas::Debugger::ScriptTarget captureInfo;
- ConfigureScriptTarget(captureInfo);
- m_liveDataAggregator.StartCaptureData();
- m_ui->captureButton->setIcon(QIcon(":/ScriptCanvasEditorResources/Resources/capture_live.png"));
- ScriptCanvas::Debugger::ClientUIRequestBus::Broadcast(&ScriptCanvas::Debugger::ClientUIRequests::StartLogging, captureInfo);
- }
- void LiveLoggingWindowSession::StopDataCapture()
- {
- m_liveDataAggregator.StopCaptureData();
- m_ui->captureButton->setIcon(QIcon(":/ScriptCanvasEditorResources/Resources/capture_offline.png"));
- ScriptCanvas::Debugger::ClientUIRequestBus::Broadcast(&ScriptCanvas::Debugger::ClientUIRequests::StopLogging);
- if (!m_userSettings->IsLiveUpdating())
- {
- m_liveDataAggregator.GetTreeRoot()->RedoLayout();
- }
- }
- void LiveLoggingWindowSession::ConfigureScriptTarget(ScriptCanvas::Debugger::ScriptTarget& captureInfo)
- {
- if (m_encodeStaticEntities)
- {
- const auto& staticRegistrations = m_liveDataAggregator.GetStaticRegistrations();
- for (const auto& registrationPair : staticRegistrations)
- {
- bool gotResult = false;
- AZ::EntityId runtimeId;
-
- AzToolsFramework::EditorEntityContextRequestBus::BroadcastResult(gotResult, &AzToolsFramework::EditorEntityContextRequests::MapEditorIdToRuntimeId, registrationPair.first, runtimeId);
- if (runtimeId.IsValid())
- {
- auto entityIter = captureInfo.m_entities.find(runtimeId);
- if (entityIter == captureInfo.m_entities.end())
- {
- auto insertResult = captureInfo.m_entities.insert(AZStd::make_pair(runtimeId, AZStd::unordered_set< ScriptCanvas::GraphIdentifier >()));
- entityIter = insertResult.first;
- }
- entityIter->second.insert(registrationPair.second);
- m_liveDataAggregator.RegisterEntityName(runtimeId, registrationPair.first.GetName());
- }
- else
- {
- auto insertResult = captureInfo.m_staticEntities.insert(registrationPair.first);
- insertResult.first->second.insert(registrationPair.second);
- }
- }
- }
-
- const LoggingEntityMap& registrationMap = m_liveDataAggregator.GetLoggingEntityMap();
- for (const auto& registrationPair : registrationMap)
- {
- auto entityIter = captureInfo.m_entities.find(registrationPair.first);
- if (entityIter == captureInfo.m_entities.end())
- {
- auto insertResult = captureInfo.m_entities.insert(AZStd::make_pair(registrationPair.first, AZStd::unordered_set< ScriptCanvas::GraphIdentifier >()));
- entityIter = insertResult.first;
- }
- entityIter->second.insert(registrationPair.second);
- }
- const LoggingAssetSet& registrationSet = m_liveDataAggregator.GetLoggingAssetSet();
- for (const auto& graphIdentifier : registrationSet)
- {
- // Graphs capture is using runtime asset subID, need this conversion else comparison won't match
- captureInfo.m_graphs.insert(AZ::Data::AssetId(graphIdentifier.m_assetId.m_guid, ScriptCanvas::RuntimeDataSubId));
- }
- }
- void LiveLoggingWindowSession::SetIsCapturing(bool isCapturing)
- {
- if (isCapturing != m_isCapturing)
- {
- m_isCapturing = isCapturing;
- if (m_isCapturing)
- {
- StartDataCapture();
- }
- else
- {
- StopDataCapture();
- }
- }
- }
- #include <Editor/View/Widgets/LoggingPanel/LiveWindowSession/moc_LiveLoggingWindowSession.cpp>
- }
|