// Copyright Epic Games, Inc. All Rights Reserved. #include "NetworkingProfilerManager.h" #include "Modules/ModuleManager.h" #include "TraceServices/AnalysisService.h" #include "WorkspaceMenuStructure.h" #include "WorkspaceMenuStructureModule.h" // Insights #include "Insights/Common/InsightsMenuBuilder.h" #include "Insights/InsightsManager.h" #include "Insights/InsightsStyle.h" #include "Insights/NetworkingProfiler/Widgets/SNetworkingProfilerWindow.h" //////////////////////////////////////////////////////////////////////////////////////////////////// #define LOCTEXT_NAMESPACE "NetworkingProfilerManager" DEFINE_LOG_CATEGORY(NetworkingProfiler); TSharedPtr FNetworkingProfilerManager::Instance = nullptr; //////////////////////////////////////////////////////////////////////////////////////////////////// TSharedPtr FNetworkingProfilerManager::Get() { return FNetworkingProfilerManager::Instance; } //////////////////////////////////////////////////////////////////////////////////////////////////// TSharedPtr FNetworkingProfilerManager::CreateInstance() { ensure(!FNetworkingProfilerManager::Instance.IsValid()); if (FNetworkingProfilerManager::Instance.IsValid()) { FNetworkingProfilerManager::Instance.Reset(); } FNetworkingProfilerManager::Instance = MakeShared(FInsightsManager::Get()->GetCommandList()); return FNetworkingProfilerManager::Instance; } //////////////////////////////////////////////////////////////////////////////////////////////////// FNetworkingProfilerManager::FNetworkingProfilerManager(TSharedRef InCommandList) : bIsInitialized(false), bIsAvailable(false), CommandList(InCommandList), ActionManager(this), ProfilerWindows() { } //////////////////////////////////////////////////////////////////////////////////////////////////// void FNetworkingProfilerManager::Initialize(IUnrealInsightsModule& InsightsModule) { ensure(!bIsInitialized); if (bIsInitialized) { return; } bIsInitialized = true; UE_LOG(NetworkingProfiler, Log, TEXT("Initialize")); // Register tick functions. OnTick = FTickerDelegate::CreateSP(this, &FNetworkingProfilerManager::Tick); OnTickHandle = FTicker::GetCoreTicker().AddTicker(OnTick, 0.0f); FNetworkingProfilerCommands::Register(); BindCommands(); FInsightsManager::Get()->GetSessionChangedEvent().AddSP(this, &FNetworkingProfilerManager::OnSessionChanged); OnSessionChanged(); } //////////////////////////////////////////////////////////////////////////////////////////////////// void FNetworkingProfilerManager::Shutdown() { if (!bIsInitialized) { return; } bIsInitialized = false; FInsightsManager::Get()->GetSessionChangedEvent().RemoveAll(this); FNetworkingProfilerCommands::Unregister(); // Unregister tick function. FTicker::GetCoreTicker().RemoveTicker(OnTickHandle); FNetworkingProfilerManager::Instance.Reset(); UE_LOG(NetworkingProfiler, Log, TEXT("Shutdown")); } //////////////////////////////////////////////////////////////////////////////////////////////////// FNetworkingProfilerManager::~FNetworkingProfilerManager() { ensure(!bIsInitialized); } //////////////////////////////////////////////////////////////////////////////////////////////////// void FNetworkingProfilerManager::BindCommands() { } //////////////////////////////////////////////////////////////////////////////////////////////////// static TSharedPtr NeverReuse(const FTabId&) { return nullptr; } void FNetworkingProfilerManager::RegisterMajorTabs(IUnrealInsightsModule& InsightsModule) { const FInsightsMajorTabConfig& Config = InsightsModule.FindMajorTabConfig(FInsightsManagerTabs::NetworkingProfilerTabId); if (Config.bIsAvailable) { // Register tab spawner(s) for the Networking Insights. // for (int32 ReservedId = 0; ReservedId < 10; ++ReservedId) { FName TabId = FInsightsManagerTabs::NetworkingProfilerTabId; // TabId.SetNumber(ReservedId); FTabSpawnerEntry& TabSpawnerEntry = FGlobalTabmanager::Get()->RegisterNomadTabSpawner(TabId, FOnSpawnTab::CreateRaw(this, &FNetworkingProfilerManager::SpawnTab), FCanSpawnTab::CreateRaw(this, &FNetworkingProfilerManager::CanSpawnTab)) .SetReuseTabMethod(FOnFindTabToReuse::CreateStatic(&NeverReuse)) .SetDisplayName(Config.TabLabel.IsSet() ? Config.TabLabel.GetValue() : LOCTEXT("NetworkingProfilerTabTitle", "Networking Insights")) .SetTooltipText(Config.TabTooltip.IsSet() ? Config.TabTooltip.GetValue() : LOCTEXT("NetworkingProfilerTooltipText", "Open the Networking Insights tab.")) .SetIcon(Config.TabIcon.IsSet() ? Config.TabIcon.GetValue() : FSlateIcon(FInsightsStyle::GetStyleSetName(), "NetworkingProfiler.Icon.Small")); TSharedRef Group = Config.WorkspaceGroup.IsValid() ? Config.WorkspaceGroup.ToSharedRef() : FInsightsManager::Get()->GetInsightsMenuBuilder()->GetInsightsToolsGroup(); TabSpawnerEntry.SetGroup(Group); } } } //////////////////////////////////////////////////////////////////////////////////////////////////// void FNetworkingProfilerManager::UnregisterMajorTabs() { // for (int32 ReservedId = 0; ReservedId < 10; ++ReservedId) { FName TabId = FInsightsManagerTabs::NetworkingProfilerTabId; // TabId.SetNumber(ReservedId); FGlobalTabmanager::Get()->UnregisterNomadTabSpawner(TabId); } } //////////////////////////////////////////////////////////////////////////////////////////////////// TSharedRef FNetworkingProfilerManager::SpawnTab(const FSpawnTabArgs& Args) { const TSharedRef DockTab = SNew(SDockTab) .TabRole(ETabRole::NomadTab); // Register OnTabClosed to handle I/O profiler manager shutdown. DockTab->SetOnTabClosed(SDockTab::FOnTabClosedCallback::CreateRaw(this, &FNetworkingProfilerManager::OnTabClosed)); // Create the SNetworkingProfilerWindow widget. TSharedRef Window = SNew(SNetworkingProfilerWindow, DockTab, Args.GetOwnerWindow()); DockTab->SetContent(Window); AddProfilerWindow(Window); return DockTab; } //////////////////////////////////////////////////////////////////////////////////////////////////// bool FNetworkingProfilerManager::CanSpawnTab(const FSpawnTabArgs& Args) const { return bIsAvailable; } //////////////////////////////////////////////////////////////////////////////////////////////////// void FNetworkingProfilerManager::OnTabClosed(TSharedRef TabBeingClosed) { TSharedRef Window = StaticCastSharedRef(TabBeingClosed->GetContent()); RemoveProfilerWindow(Window); // Disable TabClosed delegate. TabBeingClosed->SetOnTabClosed(SDockTab::FOnTabClosedCallback()); } //////////////////////////////////////////////////////////////////////////////////////////////////// const TSharedRef FNetworkingProfilerManager::GetCommandList() const { return CommandList; } //////////////////////////////////////////////////////////////////////////////////////////////////// const FNetworkingProfilerCommands& FNetworkingProfilerManager::GetCommands() { return FNetworkingProfilerCommands::Get(); } //////////////////////////////////////////////////////////////////////////////////////////////////// FNetworkingProfilerActionManager& FNetworkingProfilerManager::GetActionManager() { return FNetworkingProfilerManager::Instance->ActionManager; } //////////////////////////////////////////////////////////////////////////////////////////////////// bool FNetworkingProfilerManager::Tick(float DeltaTime) { // Check if session has Networking events (to spawn the tab), but not too often. if (!bIsAvailable && AvailabilityCheck.Tick()) { uint32 NetTraceVersion = 0; TSharedPtr Session = FInsightsManager::Get()->GetSession(); if (Session.IsValid()) { Trace::FAnalysisSessionReadScope SessionReadScope(*Session.Get()); if (Session->IsAnalysisComplete()) { // Never check again during this session. AvailabilityCheck.Disable(); } const Trace::INetProfilerProvider& NetProfilerProvider = Trace::ReadNetProfilerProvider(*Session.Get()); NetTraceVersion = NetProfilerProvider.GetNetTraceVersion(); } else { // Do not check again until the next session changed event (see OnSessionChanged). AvailabilityCheck.Disable(); } if (NetTraceVersion > 0) { bIsAvailable = true; const FName& TabId = FInsightsManagerTabs::NetworkingProfilerTabId; if (FGlobalTabmanager::Get()->HasTabSpawner(TabId)) { // Spawn 2 tabs. UE_LOG(NetworkingProfiler, Log, TEXT("Opening the \"Networking Insights\" tabs...")); FGlobalTabmanager::Get()->TryInvokeTab(TabId); FGlobalTabmanager::Get()->TryInvokeTab(TabId); } // int32 SpawnTabCount = 2; // we want to spawn 2 tabs // for (int32 ReservedId = 0; SpawnTabCount > 0 && ReservedId < 10; ++ReservedId) //{ // FName TabId = FInsightsManagerTabs::NetworkingProfilerTabId; // TabId.SetNumber(ReservedId); // // if (FGlobalTabmanager::Get()->HasTabSpawner(TabId) && // !FGlobalTabmanager::Get()->FindExistingLiveTab(TabId).IsValid()) // { // UE_LOG(NetworkingProfiler, Log, TEXT("Opening the \"Networking Insights\" tab...")); // FGlobalTabmanager::Get()->TryInvokeTab(TabId); // --SpawnTabCount; // } // } // ActivateTimingInsightsTab(); } } return true; } //////////////////////////////////////////////////////////////////////////////////////////////////// void FNetworkingProfilerManager::OnSessionChanged() { UE_LOG(NetworkingProfiler, Log, TEXT("OnSessionChanged")); bIsAvailable = false; if (FInsightsManager::Get()->GetSession().IsValid()) { AvailabilityCheck.Enable(1.0); } else { AvailabilityCheck.Disable(); } for (TWeakPtr WndWeakPtr: ProfilerWindows) { TSharedPtr Wnd = WndWeakPtr.Pin(); if (Wnd.IsValid()) { Wnd->Reset(); } } } //////////////////////////////////////////////////////////////////////////////////////////////////// #undef LOCTEXT_NAMESPACE