2021-09-28 13:33:17 -04:00
|
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
|
|
|
|
#include "StateTreeModule.h"
|
2023-08-17 11:23:30 -04:00
|
|
|
|
2023-03-14 13:35:46 -04:00
|
|
|
#include "StateTreeTypes.h"
|
|
|
|
|
|
|
|
|
|
#if WITH_STATETREE_DEBUGGER
|
2023-05-26 11:59:58 -04:00
|
|
|
#include "Debugger/StateTreeTrace.h"
|
2023-03-14 13:35:46 -04:00
|
|
|
#include "Debugger/StateTreeTraceModule.h"
|
|
|
|
|
#include "Features/IModularFeatures.h"
|
2023-04-19 13:26:23 -04:00
|
|
|
#include "HAL/IConsoleManager.h"
|
2023-03-14 13:35:46 -04:00
|
|
|
#include "Misc/CoreDelegates.h"
|
|
|
|
|
#include "ProfilingDebugging/TraceAuxiliary.h"
|
2023-08-17 11:23:30 -04:00
|
|
|
#include "StateTreeDelegates.h"
|
2023-03-14 13:35:46 -04:00
|
|
|
#include "StateTreeSettings.h"
|
|
|
|
|
#include "Trace/StoreClient.h"
|
|
|
|
|
#include "Trace/StoreService.h"
|
|
|
|
|
#include "TraceServices/AnalysisService.h"
|
|
|
|
|
#include "TraceServices/ITraceServicesModule.h"
|
|
|
|
|
|
|
|
|
|
#endif // WITH_STATETREE_DEBUGGER
|
2021-09-28 13:33:17 -04:00
|
|
|
|
2024-01-30 06:46:14 -05:00
|
|
|
#if WITH_EDITORONLY_DATA
|
|
|
|
|
#include "StateTreeInstanceData.h"
|
|
|
|
|
#endif // WITH_EDITORONLY_DATA
|
|
|
|
|
|
2021-09-28 13:33:17 -04:00
|
|
|
#define LOCTEXT_NAMESPACE "StateTree"
|
|
|
|
|
|
|
|
|
|
class FStateTreeModule : public IStateTreeModule
|
|
|
|
|
{
|
|
|
|
|
// Begin IModuleInterface
|
|
|
|
|
virtual void StartupModule() override;
|
|
|
|
|
virtual void ShutdownModule() override;
|
2023-03-14 13:35:46 -04:00
|
|
|
|
2023-06-22 14:18:20 -04:00
|
|
|
virtual bool StartTraces(int32& OutTraceId) override;
|
|
|
|
|
virtual bool IsTracing() const override;
|
2023-05-26 11:59:58 -04:00
|
|
|
virtual void StopTraces() override;
|
2023-03-14 13:35:46 -04:00
|
|
|
|
|
|
|
|
#if WITH_STATETREE_DEBUGGER
|
|
|
|
|
/**
|
|
|
|
|
* Gets the store client.
|
|
|
|
|
*/
|
2023-05-26 11:59:58 -04:00
|
|
|
virtual UE::Trace::FStoreClient* GetStoreClient() override
|
|
|
|
|
{
|
|
|
|
|
if (!StoreClient.IsValid())
|
|
|
|
|
{
|
|
|
|
|
StoreClient = TUniquePtr<UE::Trace::FStoreClient>(UE::Trace::FStoreClient::Connect(TEXT("localhost")));
|
|
|
|
|
}
|
|
|
|
|
return StoreClient.Get();
|
|
|
|
|
}
|
2023-03-14 13:35:46 -04:00
|
|
|
|
|
|
|
|
TSharedPtr<TraceServices::IAnalysisService> TraceAnalysisService;
|
|
|
|
|
TSharedPtr<TraceServices::IModuleService> TraceModuleService;
|
|
|
|
|
|
2023-05-26 11:59:58 -04:00
|
|
|
TArray<const FString> ChannelsToRestore;
|
2023-03-14 13:35:46 -04:00
|
|
|
|
|
|
|
|
/** The client used to connect to the trace store. */
|
|
|
|
|
TUniquePtr<UE::Trace::FStoreClient> StoreClient;
|
|
|
|
|
|
|
|
|
|
FStateTreeTraceModule StateTreeTraceModule;
|
2023-04-19 13:26:23 -04:00
|
|
|
|
2023-06-21 12:05:31 -04:00
|
|
|
/** Keep track if StartTraces was explicitly called. */
|
|
|
|
|
bool bIsTracing = false;
|
|
|
|
|
|
|
|
|
|
FAutoConsoleCommand StartDebuggerTracesCommand = FAutoConsoleCommand(
|
|
|
|
|
TEXT("statetree.startdebuggertraces"),
|
|
|
|
|
TEXT("Turns on StateTree debugger traces if not already active."),
|
|
|
|
|
FConsoleCommandDelegate::CreateLambda([]
|
2023-06-22 14:18:20 -04:00
|
|
|
{
|
|
|
|
|
IStateTreeModule& StateTreeModule = FModuleManager::GetModuleChecked<IStateTreeModule>("StateTreeModule");
|
|
|
|
|
int32 TraceId = 0;
|
|
|
|
|
StateTreeModule.StartTraces(TraceId);
|
|
|
|
|
}));
|
2023-06-21 12:05:31 -04:00
|
|
|
|
|
|
|
|
FAutoConsoleCommand StopDebuggerTracesCommand = FAutoConsoleCommand(
|
|
|
|
|
TEXT("statetree.stopdebuggertraces"),
|
|
|
|
|
TEXT("Turns off StateTree debugger traces if active."),
|
|
|
|
|
FConsoleCommandDelegate::CreateLambda([]
|
2023-06-22 14:18:20 -04:00
|
|
|
{
|
|
|
|
|
IStateTreeModule& StateTreeModule = FModuleManager::GetModuleChecked<IStateTreeModule>("StateTreeModule");
|
|
|
|
|
StateTreeModule.StopTraces();
|
|
|
|
|
}));
|
2023-03-14 13:35:46 -04:00
|
|
|
#endif // WITH_STATETREE_DEBUGGER
|
2021-09-28 13:33:17 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
IMPLEMENT_MODULE(FStateTreeModule, StateTreeModule)
|
|
|
|
|
|
|
|
|
|
void FStateTreeModule::StartupModule()
|
|
|
|
|
{
|
2023-05-26 11:59:58 -04:00
|
|
|
#if WITH_STATETREE_DEBUGGER
|
|
|
|
|
ITraceServicesModule& TraceServicesModule = FModuleManager::LoadModuleChecked<ITraceServicesModule>("TraceServices");
|
|
|
|
|
TraceAnalysisService = TraceServicesModule.GetAnalysisService();
|
|
|
|
|
TraceModuleService = TraceServicesModule.GetModuleService();
|
|
|
|
|
|
|
|
|
|
IModularFeatures::Get().RegisterModularFeature(TraceServices::ModuleFeatureName, &StateTreeTraceModule);
|
|
|
|
|
|
|
|
|
|
UE::StateTreeTrace::RegisterGlobalDelegates();
|
|
|
|
|
#if !WITH_EDITOR
|
|
|
|
|
// We don't automatically start traces for Editor targets since we rely on the debugger
|
|
|
|
|
// to start recording either on user action or on PIE session start.
|
2023-06-21 12:05:31 -04:00
|
|
|
if (UStateTreeSettings::Get().bAutoStartDebuggerTracesOnNonEditorTargets)
|
|
|
|
|
{
|
2023-06-22 14:18:20 -04:00
|
|
|
int32 TraceId = INDEX_NONE;
|
|
|
|
|
StartTraces(TraceId);
|
2023-06-21 12:05:31 -04:00
|
|
|
}
|
2023-05-26 11:59:58 -04:00
|
|
|
#endif // !WITH_EDITOR
|
|
|
|
|
|
|
|
|
|
#endif // WITH_STATETREE_DEBUGGER
|
2024-01-30 06:46:14 -05:00
|
|
|
|
|
|
|
|
#if WITH_EDITORONLY_DATA
|
|
|
|
|
UE::StateTree::RegisterInstanceDataForLocalization();
|
|
|
|
|
#endif // WITH_EDITORONLY_DATA
|
2021-09-28 13:33:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FStateTreeModule::ShutdownModule()
|
|
|
|
|
{
|
2023-05-26 11:59:58 -04:00
|
|
|
#if WITH_STATETREE_DEBUGGER
|
2023-03-14 13:35:46 -04:00
|
|
|
StopTraces();
|
2023-05-26 11:59:58 -04:00
|
|
|
|
|
|
|
|
if (StoreClient.IsValid())
|
|
|
|
|
{
|
2023-05-26 12:18:32 -04:00
|
|
|
StoreClient.Reset();
|
2023-05-26 11:59:58 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UE::StateTreeTrace::UnregisterGlobalDelegates();
|
|
|
|
|
|
|
|
|
|
IModularFeatures::Get().UnregisterModularFeature(TraceServices::ModuleFeatureName, &StateTreeTraceModule);
|
|
|
|
|
#endif // WITH_STATETREE_DEBUGGER
|
2023-03-14 13:35:46 -04:00
|
|
|
}
|
|
|
|
|
|
2023-06-22 14:18:20 -04:00
|
|
|
bool FStateTreeModule::StartTraces(int32& OutTraceId)
|
2023-03-14 13:35:46 -04:00
|
|
|
{
|
2023-06-22 14:18:20 -04:00
|
|
|
OutTraceId = INDEX_NONE;
|
2023-03-14 13:35:46 -04:00
|
|
|
#if WITH_STATETREE_DEBUGGER
|
2023-06-21 12:05:31 -04:00
|
|
|
if (IsRunningCommandlet() || bIsTracing)
|
2023-03-14 13:35:46 -04:00
|
|
|
{
|
2023-06-22 14:18:20 -04:00
|
|
|
return false;
|
2023-03-14 13:35:46 -04:00
|
|
|
}
|
|
|
|
|
|
2023-06-22 14:18:20 -04:00
|
|
|
FGuid SessionGuid, TraceGuid;
|
|
|
|
|
const bool bAlreadyConnected = FTraceAuxiliary::IsConnected(SessionGuid, TraceGuid);
|
|
|
|
|
|
|
|
|
|
if (UE::Trace::FStoreClient* Client = GetStoreClient())
|
|
|
|
|
{
|
|
|
|
|
const UE::Trace::FStoreClient::FSessionInfo* SessionInfo = StoreClient->GetSessionInfoByGuid(TraceGuid);
|
|
|
|
|
// Note that 0 is returned instead of INDEX_NONE to match default invalid value for GetTraceId
|
|
|
|
|
OutTraceId = SessionInfo != nullptr ? SessionInfo->GetTraceId(): 0;
|
|
|
|
|
}
|
2023-03-14 13:35:46 -04:00
|
|
|
|
2023-05-26 11:59:58 -04:00
|
|
|
// If trace is already connected let's keep track of enabled channels to restore them when we stop recording
|
|
|
|
|
if (bAlreadyConnected)
|
2023-03-14 13:35:46 -04:00
|
|
|
{
|
2023-05-26 11:59:58 -04:00
|
|
|
UE::Trace::EnumerateChannels([](const ANSICHAR* Name, const bool bIsEnabled, void* Channels)
|
|
|
|
|
{
|
2023-05-30 11:37:35 -04:00
|
|
|
TArray<FString>* EnabledChannels = static_cast<TArray<FString>*>(Channels);
|
2023-05-26 11:59:58 -04:00
|
|
|
if (bIsEnabled)
|
|
|
|
|
{
|
2023-05-30 11:37:35 -04:00
|
|
|
EnabledChannels->Emplace(ANSI_TO_TCHAR(Name));
|
2023-05-26 11:59:58 -04:00
|
|
|
}
|
|
|
|
|
}, &ChannelsToRestore);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Disable all channels and then enable only those we need to minimize trace file size.
|
2023-03-14 13:35:46 -04:00
|
|
|
UE::Trace::EnumerateChannels([](const ANSICHAR* ChannelName, const bool bEnabled, void*)
|
|
|
|
|
{
|
|
|
|
|
if (bEnabled)
|
|
|
|
|
{
|
|
|
|
|
FString ChannelNameFString(ChannelName);
|
|
|
|
|
UE::Trace::ToggleChannel(ChannelNameFString.GetCharArray().GetData(), false);
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-05-26 11:59:58 -04:00
|
|
|
, nullptr);
|
2023-03-14 13:35:46 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UE::Trace::ToggleChannel(TEXT("StateTreeDebugChannel"), true);
|
|
|
|
|
UE::Trace::ToggleChannel(TEXT("FrameChannel"), true);
|
|
|
|
|
|
2023-06-22 14:18:20 -04:00
|
|
|
bool bAreTracesStarted = false;
|
2023-05-26 11:59:58 -04:00
|
|
|
if (bAlreadyConnected == false)
|
2023-03-14 13:35:46 -04:00
|
|
|
{
|
2023-05-26 11:59:58 -04:00
|
|
|
FTraceAuxiliary::FOptions Options;
|
|
|
|
|
Options.bExcludeTail = true;
|
2023-06-22 14:18:20 -04:00
|
|
|
bAreTracesStarted = FTraceAuxiliary::Start(FTraceAuxiliary::EConnectionType::Network, TEXT("localhost"), TEXT(""), &Options, LogStateTree);
|
2023-05-26 11:59:58 -04:00
|
|
|
}
|
2023-06-21 12:05:31 -04:00
|
|
|
|
|
|
|
|
bIsTracing = true;
|
2023-08-17 11:23:30 -04:00
|
|
|
if (UE::StateTree::Delegates::OnTracingStateChanged.IsBound())
|
|
|
|
|
{
|
|
|
|
|
UE_LOG(LogStateTree, Log, TEXT("StateTree traces enabled"));
|
|
|
|
|
UE::StateTree::Delegates::OnTracingStateChanged.Broadcast(bIsTracing);
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-22 14:18:20 -04:00
|
|
|
return bAreTracesStarted;
|
|
|
|
|
#else
|
|
|
|
|
return false;
|
|
|
|
|
#endif // WITH_STATETREE_DEBUGGER
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FStateTreeModule::IsTracing() const
|
|
|
|
|
{
|
|
|
|
|
#if WITH_STATETREE_DEBUGGER
|
|
|
|
|
return bIsTracing;
|
|
|
|
|
#else
|
|
|
|
|
return false;
|
2023-03-14 13:35:46 -04:00
|
|
|
#endif // WITH_STATETREE_DEBUGGER
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FStateTreeModule::StopTraces()
|
|
|
|
|
{
|
|
|
|
|
#if WITH_STATETREE_DEBUGGER
|
2023-06-21 12:05:31 -04:00
|
|
|
if (bIsTracing == false)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
2023-05-26 11:59:58 -04:00
|
|
|
|
|
|
|
|
UE::Trace::ToggleChannel(TEXT("StateTreeDebugChannel"), false);
|
|
|
|
|
UE::Trace::ToggleChannel(TEXT("FrameChannel"), false);
|
|
|
|
|
|
|
|
|
|
// When we have channels to restore it also indicates that the trace were active
|
|
|
|
|
// so we only toggle the channels back (i.e. not calling FTraceAuxiliary::Stop)
|
|
|
|
|
if (ChannelsToRestore.Num() > 0)
|
2023-03-14 13:35:46 -04:00
|
|
|
{
|
2023-05-26 11:59:58 -04:00
|
|
|
for (const FString& ChannelName : ChannelsToRestore)
|
2023-03-14 13:35:46 -04:00
|
|
|
{
|
2023-05-26 11:59:58 -04:00
|
|
|
UE::Trace::ToggleChannel(ChannelName.GetCharArray().GetData(), true);
|
2023-03-14 13:35:46 -04:00
|
|
|
}
|
2023-05-26 11:59:58 -04:00
|
|
|
ChannelsToRestore.Reset();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
FTraceAuxiliary::Stop();
|
2023-03-14 13:35:46 -04:00
|
|
|
}
|
2023-06-21 12:05:31 -04:00
|
|
|
|
|
|
|
|
bIsTracing = false;
|
2023-08-17 11:23:30 -04:00
|
|
|
|
|
|
|
|
if (UE::StateTree::Delegates::OnTracingStateChanged.IsBound())
|
|
|
|
|
{
|
|
|
|
|
UE_LOG(LogStateTree, Log, TEXT("StateTree traces disabled"));
|
|
|
|
|
UE::StateTree::Delegates::OnTracingStateChanged.Broadcast(bIsTracing);
|
|
|
|
|
}
|
2023-03-14 13:35:46 -04:00
|
|
|
#endif // WITH_STATETREE_DEBUGGER
|
2021-09-28 13:33:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#undef LOCTEXT_NAMESPACE
|