Files
UnrealEngine/Engine/Source/Developer/TraceTools/Private/Widgets/STraceControlToolbar.cpp
2025-05-18 13:04:45 +08:00

411 lines
12 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "STraceControlToolbar.h"
#include "ITraceController.h"
#include "Framework/MultiBox/MultiBoxDefs.h"
#include "Framework/MultiBox/MultiBoxBuilder.h"
#include "SlateOptMacros.h"
#include "SocketSubsystem.h"
#include "Styling/AppStyle.h"
#include "Styling/StyleColors.h"
#include "Widgets/Images/SImage.h"
#include "Widgets/Input/SButton.h"
#include "Widgets/Layout/SBorder.h"
#include "Widgets/SBoxPanel.h"
//TraceTools
#include "Models/TraceControlCommands.h"
#include "TraceTools/Widgets/SToggleTraceButton.h"
#define LOCTEXT_NAMESPACE "STraceControlToolbar"
namespace UE::TraceTools
{
STraceControlToolbar::STraceControlToolbar()
{
}
STraceControlToolbar::~STraceControlToolbar()
{
TraceController->OnStatusReceived().RemoveAll(this);
}
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
void STraceControlToolbar::Construct(const FArguments& InArgs, const TSharedRef<FUICommandList>& CommandList, TSharedPtr<ITraceController> InTraceController)
{
InitializeSettings();
FTraceControlCommands::Register();
TraceController = InTraceController;
OnStatusReceivedDelegate = TraceController->OnStatusReceived().AddRaw(this, &STraceControlToolbar::OnTraceStatusUpdated);
BindCommands(CommandList);
// create the toolbar
FSlimHorizontalToolBarBuilder Toolbar(CommandList, FMultiBoxCustomization::None);
{
Toolbar.SetStyle(&FTraceToolsStyle::Get(), "TraceControlToolbar");
Toolbar.AddComboButton(
FUIAction(),
FOnGetContent::CreateSP(this, &STraceControlToolbar::BuildTraceTargetMenu, CommandList),
TAttribute<FText>::CreateSP(this, &STraceControlToolbar::GetTraceTargetLabelText),
TAttribute<FText>::CreateSP(this, &STraceControlToolbar::GetTraceTargetTooltipText),
TAttribute<FSlateIcon>::CreateSP(this, &STraceControlToolbar::GetTraceTargetIcon),
false);
Toolbar.AddSeparator();
Toolbar.SetLabelVisibility(EVisibility::Collapsed);
TSharedRef<SWidget> ToggleTraceWidget =
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.Padding(0.0f, 2.0f, 0.0f, 0.0f)
[
SNew(SToggleTraceButton)
.OnToggleTraceRequested(this, &STraceControlToolbar::ToggleTrace_Execute)
.IsTraceRunning_Lambda([this]() {return bIsTracing; })
.IsEnabled(this, &STraceControlToolbar::ToggleTrace_CanExecute)
.ButtonSize(SToggleTraceButton::EButtonSize::SlimToolbar)
];
Toolbar.AddToolBarWidget(ToggleTraceWidget);
Toolbar.AddToolBarButton(FTraceControlCommands::Get().TraceSnapshot);
Toolbar.AddSeparator();
TSharedRef<SWidget> PauseResumeWidget =
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
[
SNew(SButton)
.ButtonStyle(FAppStyle::Get(), "SimpleButton")
.ContentPadding(FMargin(0.0f, 0.0f, 0.0f, 3.0f))
.HAlign(HAlign_Left)
.VAlign(VAlign_Bottom)
.ToolTipText(this, &STraceControlToolbar::TogglePauseResume_GetTooltip)
.OnClicked(this, &STraceControlToolbar::TogglePauseResume_OnClicked)
.IsEnabled(this, &STraceControlToolbar::TogglePauseResume_CanExecute)
.Content()
[
SNew(SImage)
.Image(this, &STraceControlToolbar::GetPauseResumeBrush)
.ColorAndOpacity(FStyleColors::Foreground)
]
];
Toolbar.AddWidget(PauseResumeWidget);
Toolbar.AddSeparator();
Toolbar.AddToolBarButton(FTraceControlCommands::Get().TraceBookmark);
Toolbar.AddToolBarButton(FTraceControlCommands::Get().TraceScreenshot);
Toolbar.AddSeparator();
Toolbar.AddToolBarButton(FTraceControlCommands::Get().ToggleStatNamedEvents);
}
ChildSlot
[
SNew(SBorder)
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
.Padding(0.0f)
[
Toolbar.MakeWidget()
]
];
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION
TSharedRef<SWidget> STraceControlToolbar::BuildTraceTargetMenu(const TSharedRef<FUICommandList> CommandList)
{
FMenuBuilder MenuBuilder(/*bInShouldCloseWindowAfterMenuSelection=*/true, CommandList);
MenuBuilder.SetSearchable(false);
MenuBuilder.AddMenuEntry(FTraceControlCommands::Get().SetTraceTargetServer);
MenuBuilder.AddMenuEntry(FTraceControlCommands::Get().SetTraceTargetFile);
return MenuBuilder.MakeWidget();
}
void STraceControlToolbar::BindCommands(const TSharedRef<FUICommandList>& CommandList)
{
CommandList->MapAction(FTraceControlCommands::Get().SetTraceTargetServer,
FExecuteAction::CreateSP(this, &STraceControlToolbar::SetTraceTarget_Execute, ETraceTarget::Server),
FCanExecuteAction::CreateSP(this, &STraceControlToolbar::SetTraceTarget_CanExecute));
CommandList->MapAction(FTraceControlCommands::Get().SetTraceTargetFile,
FExecuteAction::CreateSP(this, &STraceControlToolbar::SetTraceTarget_Execute, ETraceTarget::File),
FCanExecuteAction::CreateSP(this, &STraceControlToolbar::SetTraceTarget_CanExecute));
CommandList->MapAction(FTraceControlCommands::Get().TraceSnapshot,
FExecuteAction::CreateSP(this, &STraceControlToolbar::TraceSnapshot_Execute),
FCanExecuteAction::CreateSP(this, &STraceControlToolbar::TraceSnapshot_CanExecute));
CommandList->MapAction(FTraceControlCommands::Get().TraceBookmark,
FExecuteAction::CreateSP(this, &STraceControlToolbar::TraceBookmark_Execute),
FCanExecuteAction::CreateSP(this, &STraceControlToolbar::TraceBookmark_CanExecute));
CommandList->MapAction(FTraceControlCommands::Get().TraceScreenshot,
FExecuteAction::CreateSP(this, &STraceControlToolbar::TraceScreenshot_Execute),
FCanExecuteAction::CreateSP(this, &STraceControlToolbar::TraceScreenshot_CanExecute));
CommandList->MapAction(FTraceControlCommands::Get().ToggleStatNamedEvents,
FExecuteAction::CreateSP(this, &STraceControlToolbar::ToggleStatNamedEvents_Execute),
FCanExecuteAction::CreateSP(this, &STraceControlToolbar::ToggleStatNamedEvents_CanExecute),
FIsActionChecked::CreateSP(this, &STraceControlToolbar::ToggleStatNamedEvents_IsChecked));
}
void STraceControlToolbar::InitializeSettings()
{
TSharedPtr<FInternetAddr> RecorderAddr;
if (ISocketSubsystem* Sockets = ISocketSubsystem::Get())
{
bool bCanBindAll = false;
RecorderAddr = Sockets->GetLocalHostAddr(*GLog, bCanBindAll);
}
if (RecorderAddr.IsValid())
{
TraceHostAddr = RecorderAddr->ToString(false);
}
else
{
TraceHostAddr = TEXT("127.0.0.1");
}
}
bool STraceControlToolbar::SetTraceTarget_CanExecute() const
{
return IsInstanceAvailable() && !bIsTracing;
}
void STraceControlToolbar::SetTraceTarget_Execute(ETraceTarget InTraceTarget)
{
TraceTarget = InTraceTarget;
}
bool STraceControlToolbar::IsInstanceAvailable() const
{
return InstanceId.IsValid() && TraceController->HasAvailableInstance(InstanceId) && bIsTracingAvailable;
}
bool STraceControlToolbar::ToggleTrace_CanExecute() const
{
return IsInstanceAvailable();
}
void STraceControlToolbar::ToggleTrace_Execute()
{
if (!bIsTracing)
{
TraceController->WithInstance(InstanceId, [&](const FTraceStatus& Status, ITraceControllerCommands& Commands)
{
if (TraceTarget == ETraceTarget::Server)
{
Commands.Send(TraceHostAddr, TEXT(""));
}
else if (TraceTarget == ETraceTarget::File)
{
Commands.File(TEXT(""), TEXT(""));
}
});
bIsTracing = true;
}
else
{
TraceController->WithInstance(InstanceId, [&](const FTraceStatus& Status, ITraceControllerCommands& Commands)
{
Commands.Stop();
});
bIsTracing = false;
}
}
bool STraceControlToolbar::TraceSnapshot_CanExecute() const
{
return IsInstanceAvailable();
}
void STraceControlToolbar::TraceSnapshot_Execute()
{
TraceController->WithInstance(InstanceId, [&](const FTraceStatus& Status, ITraceControllerCommands& Commands)
{
if (TraceTarget == ETraceTarget::Server)
{
Commands.SnapshotSend(TraceHostAddr);
}
else if (TraceTarget == ETraceTarget::File)
{
Commands.SnapshotFile(TEXT(""));
}
});
}
bool STraceControlToolbar::TraceBookmark_CanExecute() const
{
return IsInstanceAvailable() && bIsTracing && !bIsPaused;
}
void STraceControlToolbar::TraceBookmark_Execute()
{
const FString BookmarkName = FDateTime::Now().ToString(TEXT("Bookmark_%Y%m%d_%H%M%S"));
TraceController->WithInstance(InstanceId, [&](const FTraceStatus& Status, ITraceControllerCommands& Commands)
{
Commands.Bookmark(BookmarkName);
});
}
bool STraceControlToolbar::TraceScreenshot_CanExecute() const
{
return IsInstanceAvailable() && bIsTracing && !bIsPaused;
}
void STraceControlToolbar::TraceScreenshot_Execute()
{
TraceController->WithInstance(InstanceId, [&](const FTraceStatus& Status, ITraceControllerCommands& Commands)
{
Commands.Screenshot(TEXT(""), false);
});
}
bool STraceControlToolbar::ToggleStatNamedEvents_CanExecute() const
{
return IsInstanceAvailable();
}
bool STraceControlToolbar::ToggleStatNamedEvents_IsChecked() const
{
return bAreStatNamedEventsEnabled;
}
void STraceControlToolbar::ToggleStatNamedEvents_Execute()
{
bAreStatNamedEventsEnabled = !bAreStatNamedEventsEnabled;
TraceController->WithInstance(InstanceId, [&](const FTraceStatus& Status, ITraceControllerCommands& Commands)
{
Commands.SetStatNamedEventsEnabled(bAreStatNamedEventsEnabled);
});
}
FText STraceControlToolbar::GetTraceTargetLabelText() const
{
if (TraceTarget == ETraceTarget::Server)
{
return LOCTEXT("TraceTargetServerLabel", "Server");
}
return LOCTEXT("TraceTargetFileLabel", "File");
}
FText STraceControlToolbar::GetTraceTargetTooltipText() const
{
return LOCTEXT("TraceTargetTooltip", "Set the trace target. Can only be set when trace is not running.");
}
FSlateIcon STraceControlToolbar::GetTraceTargetIcon() const
{
if (TraceTarget == ETraceTarget::Server)
{
return FSlateIcon(FTraceToolsStyle::GetStyleSetName(), "TraceControl.SetTraceTargetServer");
}
return FSlateIcon(FTraceToolsStyle::GetStyleSetName(), "TraceControl.SetTraceTargetFile");
}
void STraceControlToolbar::OnTraceStatusUpdated(const FTraceStatus& InStatus, FTraceStatus::EUpdateType InUpdateType, ITraceControllerCommands& Commands)
{
if (!InstanceId.IsValid() || InstanceId != InStatus.InstanceId)
{
return;
}
bIsTracing = InStatus.bIsTracing;
bIsPaused = InStatus.bIsPaused;
bAreStatNamedEventsEnabled = InStatus.bAreStatNamedEventsEnabled;
bIsTracingAvailable = InStatus.TraceSystemStatus != FTraceStatus::ETraceSystemStatus::NotAvailable;
if (InStatus.TraceSystemStatus == FTraceStatus::ETraceSystemStatus::TracingToServer)
{
TraceTarget = ETraceTarget::Server;
}
else if (InStatus.TraceSystemStatus == FTraceStatus::ETraceSystemStatus::TracingToFile)
{
TraceTarget = ETraceTarget::File;
}
}
bool STraceControlToolbar::TogglePauseResume_CanExecute() const
{
return IsInstanceAvailable() && bIsTracing;
}
FReply STraceControlToolbar::TogglePauseResume_OnClicked()
{
if (bIsPaused)
{
TraceController->WithInstance(InstanceId, [&](const FTraceStatus& Status, ITraceControllerCommands& Commands)
{
Commands.Resume();
});
bIsPaused = false;
}
else
{
TraceController->WithInstance(InstanceId, [&](const FTraceStatus& Status, ITraceControllerCommands& Commands)
{
Commands.Pause();
});
bIsPaused = true;
}
return FReply::Handled();
}
const FSlateBrush* STraceControlToolbar::GetPauseResumeBrush() const
{
if (bIsPaused)
{
return FTraceToolsStyle::GetBrush("TraceControl.ResumeTrace.Small");
}
return FTraceToolsStyle::GetBrush("TraceControl.PauseTrace.Small");
}
FText STraceControlToolbar::TogglePauseResume_GetTooltip() const
{
if (bIsPaused)
{
return LOCTEXT("ResumeTraceTooltip", "Enable the channels that were enabled before trace was paused.");
}
return LOCTEXT("PauseTraceTooltip", "Disable all the trace channels and save the channel list so they can be enabled again with the resume command.");
}
void STraceControlToolbar::SetInstanceId(const FGuid& Id)
{
InstanceId = Id;
Reset();
}
void STraceControlToolbar::Reset()
{
TraceTarget = ETraceTarget::Server;
bIsTracing = false;
bIsPaused = false;
bAreStatNamedEventsEnabled = false;
bIsTracingAvailable = false;
}
} // namespace UE::TraceTools
#undef LOCTEXT_NAMESPACE