2021-09-28 13:33:17 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "StateTreeModule.h"
2024-08-07 08:47:03 -04:00
# include "StateTreeModuleImpl.h"
2023-08-17 11:23:30 -04:00
2023-03-14 13:35:46 -04:00
# include "StateTreeTypes.h"
2024-05-02 11:47:26 -04:00
# if WITH_STATETREE_TRACE
2023-05-26 11:59:58 -04:00
# include "Debugger/StateTreeTrace.h"
2024-05-02 11:47:26 -04:00
# include "Debugger/StateTreeTraceTypes.h"
2023-04-19 13:26:23 -04:00
# include "HAL/IConsoleManager.h"
2023-03-14 13:35:46 -04:00
# 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"
2024-05-02 11:47:26 -04:00
# endif // WITH_STATETREE_TRACE
# if WITH_STATETREE_TRACE_DEBUGGER
# include "Debugger/StateTreeDebuggerTypes.h"
# include "Debugger/StateTreeTraceModule.h"
# include "Features/IModularFeatures.h"
# include "Misc/CoreDelegates.h"
2023-03-14 13:35:46 -04:00
# include "Trace/StoreClient.h"
# include "TraceServices/AnalysisService.h"
# include "TraceServices/ITraceServicesModule.h"
2024-05-02 11:47:26 -04:00
# endif // WITH_STATETREE_TRACE_DEBUGGER
2021-09-28 13:33:17 -04:00
2024-01-30 03:18:31 -05:00
# if WITH_EDITORONLY_DATA
# include "StateTreeInstanceData.h"
# endif // WITH_EDITORONLY_DATA
2024-08-07 08:47:03 -04:00
# if WITH_EDITOR
# include "StructUtilsDelegates.h"
# endif
2021-09-28 13:33:17 -04:00
# define LOCTEXT_NAMESPACE "StateTree"
2024-05-02 11:47:26 -04:00
# if WITH_STATETREE_TRACE_DEBUGGER
2024-08-07 08:47:03 -04:00
UE : : Trace : : FStoreClient * FStateTreeModule : : GetStoreClient ( )
{
if ( ! StoreClient . IsValid ( ) )
2023-05-26 11:59:58 -04:00
{
2024-08-07 08:47:03 -04:00
StoreClient = TUniquePtr < UE : : Trace : : FStoreClient > ( UE : : Trace : : FStoreClient : : Connect ( TEXT ( " localhost " ) ) ) ;
2023-05-26 11:59:58 -04:00
}
2024-08-07 08:47:03 -04:00
return StoreClient . Get ( ) ;
}
2024-05-02 11:47:26 -04:00
# endif // WITH_STATETREE_TRACE_DEBUGGER
2024-08-07 08:47:03 -04:00
FStateTreeModule : : FStateTreeModule ( )
2024-05-02 11:47:26 -04:00
# if WITH_STATETREE_TRACE
2024-08-07 08:47:03 -04:00
: StartDebuggerTracesCommand ( FAutoConsoleCommand (
2023-06-21 12:05:31 -04:00
TEXT ( " statetree.startdebuggertraces " ) ,
TEXT ( " Turns on StateTree debugger traces if not already active. " ) ,
FConsoleCommandDelegate : : CreateLambda ( [ ]
2023-06-22 14:18:20 -04:00
{
int32 TraceId = 0 ;
2024-08-07 08:47:03 -04:00
IStateTreeModule : : Get ( ) . StartTraces ( TraceId ) ;
} ) ) )
, StopDebuggerTracesCommand ( FAutoConsoleCommand (
2023-06-21 12:05:31 -04:00
TEXT ( " statetree.stopdebuggertraces " ) ,
TEXT ( " Turns off StateTree debugger traces if active. " ) ,
FConsoleCommandDelegate : : CreateLambda ( [ ]
2023-06-22 14:18:20 -04:00
{
2024-08-07 08:47:03 -04:00
IStateTreeModule : : Get ( ) . StopTraces ( ) ;
} ) ) )
2024-05-02 11:47:26 -04:00
# endif // WITH_STATETREE_TRACE
2024-08-07 08:47:03 -04:00
{
}
2021-09-28 13:33:17 -04:00
void FStateTreeModule : : StartupModule ( )
{
2024-05-02 11:47:26 -04:00
# if WITH_STATETREE_TRACE_DEBUGGER
2023-05-26 11:59:58 -04:00
ITraceServicesModule & TraceServicesModule = FModuleManager : : LoadModuleChecked < ITraceServicesModule > ( " TraceServices " ) ;
TraceAnalysisService = TraceServicesModule . GetAnalysisService ( ) ;
TraceModuleService = TraceServicesModule . GetModuleService ( ) ;
IModularFeatures : : Get ( ) . RegisterModularFeature ( TraceServices : : ModuleFeatureName , & StateTreeTraceModule ) ;
2024-05-02 11:47:26 -04:00
# endif // WITH_STATETREE_TRACE_DEBUGGER
2023-05-26 11:59:58 -04:00
2024-05-02 11:47:26 -04:00
# if WITH_STATETREE_TRACE
2023-05-26 11:59:58 -04:00
UE : : StateTreeTrace : : RegisterGlobalDelegates ( ) ;
2024-05-02 11:47:26 -04:00
2023-05-26 11:59:58 -04:00
# 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
2024-05-02 11:47:26 -04:00
# endif // WITH_STATETREE_TRACE
2024-01-30 03:18:31 -05:00
# if WITH_EDITORONLY_DATA
UE : : StateTree : : RegisterInstanceDataForLocalization ( ) ;
# endif // WITH_EDITORONLY_DATA
2024-08-07 08:47:03 -04:00
# if WITH_EDITOR
// Register thread safe delegates, which allows the StateTree objects to safely register to these delegates e.g. in PostInitProperties() which may be called from another thread.
OnObjectsReinstancedHandle = FCoreUObjectDelegates : : OnObjectsReinstanced . AddRaw ( this , & FStateTreeModule : : HandleObjectsReinstanced ) ;
OnUserDefinedStructReinstancedHandle = UE : : StructUtils : : Delegates : : OnUserDefinedStructReinstanced . AddRaw ( this , & FStateTreeModule : : HandleUserDefinedStructReinstanced ) ;
OnPreBeginPIEHandle = FEditorDelegates : : PreBeginPIE . AddRaw ( this , & FStateTreeModule : : HandlePreBeginPIE ) ;
# endif //WITH_EDITOR
2021-09-28 13:33:17 -04:00
}
void FStateTreeModule : : ShutdownModule ( )
{
2024-08-07 08:47:03 -04:00
# if WITH_EDITOR
FCoreUObjectDelegates : : OnObjectsReinstanced . Remove ( OnObjectsReinstancedHandle ) ;
UE : : StructUtils : : Delegates : : OnUserDefinedStructReinstanced . Remove ( OnUserDefinedStructReinstancedHandle ) ;
FEditorDelegates : : PreBeginPIE . Remove ( OnPreBeginPIEHandle ) ;
# endif //WITH_EDITOR
2024-05-02 11:47:26 -04:00
# if WITH_STATETREE_TRACE
2023-03-14 13:35:46 -04:00
StopTraces ( ) ;
2023-05-26 11:59:58 -04:00
2024-05-02 11:47:26 -04:00
UE : : StateTreeTrace : : UnregisterGlobalDelegates ( ) ;
# endif // WITH_STATETREE_TRACE
# if WITH_STATETREE_TRACE_DEBUGGER
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
}
IModularFeatures : : Get ( ) . UnregisterModularFeature ( TraceServices : : ModuleFeatureName , & StateTreeTraceModule ) ;
2024-05-02 11:47:26 -04:00
# endif // WITH_STATETREE_TRACE_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 ;
2024-05-02 11:47:26 -04:00
# if WITH_STATETREE_TRACE
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 ) ;
2024-05-02 11:47:26 -04:00
# if WITH_STATETREE_TRACE_DEBUGGER
if ( const UE : : Trace : : FStoreClient * Client = GetStoreClient ( ) )
2023-06-22 14:18:20 -04:00
{
2024-05-02 11:47:26 -04:00
const UE : : Trace : : FStoreClient : : FSessionInfo * SessionInfo = Client - > GetSessionInfoByGuid ( TraceGuid ) ;
2023-06-22 14:18:20 -04:00
// Note that 0 is returned instead of INDEX_NONE to match default invalid value for GetTraceId
OutTraceId = SessionInfo ! = nullptr ? SessionInfo - > GetTraceId ( ) : 0 ;
}
2024-05-02 11:47:26 -04:00
# endif // WITH_STATETREE_TRACE_DEBUGGER
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 " ) ) ;
2024-04-26 12:01:04 -04:00
UE : : StateTree : : Delegates : : OnTracingStateChanged . Broadcast ( EStateTreeTraceStatus : : TracesStarted ) ;
2023-08-17 11:23:30 -04:00
}
2023-06-22 14:18:20 -04:00
return bAreTracesStarted ;
# else
return false ;
2024-05-02 11:47:26 -04:00
# endif // WITH_STATETREE_TRACE
2023-06-22 14:18:20 -04:00
}
bool FStateTreeModule : : IsTracing ( ) const
{
2024-05-02 11:47:26 -04:00
# if WITH_STATETREE_TRACE
2023-06-22 14:18:20 -04:00
return bIsTracing ;
# else
return false ;
2024-05-02 11:47:26 -04:00
# endif // WITH_STATETREE_TRACE
2023-03-14 13:35:46 -04:00
}
void FStateTreeModule : : StopTraces ( )
{
2024-05-02 11:47:26 -04:00
# if WITH_STATETREE_TRACE
2023-06-21 12:05:31 -04:00
if ( bIsTracing = = false )
{
return ;
}
2023-05-26 11:59:58 -04:00
2024-04-26 12:01:04 -04:00
if ( UE : : StateTree : : Delegates : : OnTracingStateChanged . IsBound ( ) )
{
UE_LOG ( LogStateTree , Log , TEXT ( " Stopping StateTree traces... " ) ) ;
UE : : StateTree : : Delegates : : OnTracingStateChanged . Broadcast ( EStateTreeTraceStatus : : StoppingTrace ) ;
}
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 ( ) )
{
2024-04-26 12:01:04 -04:00
UE_LOG ( LogStateTree , Log , TEXT ( " StateTree traces stopped " ) ) ;
UE : : StateTree : : Delegates : : OnTracingStateChanged . Broadcast ( EStateTreeTraceStatus : : TracesStopped ) ;
2023-08-17 11:23:30 -04:00
}
2024-05-02 11:47:26 -04:00
# endif // WITH_STATETREE_TRACE
2021-09-28 13:33:17 -04:00
}
2024-08-07 08:47:03 -04:00
# if WITH_EDITOR
void FStateTreeModule : : HandleObjectsReinstanced ( const FReplacementObjectMap & ObjectMap )
{
OnObjectsReinstanced . Broadcast ( ObjectMap ) ;
}
void FStateTreeModule : : HandlePreBeginPIE ( const bool bIsSimulating )
{
OnPreBeginPIE . Broadcast ( bIsSimulating ) ;
}
void FStateTreeModule : : HandleUserDefinedStructReinstanced ( const UUserDefinedStruct & UserDefinedStruct )
{
OnUserDefinedStructReinstanced . Broadcast ( UserDefinedStruct ) ;
}
# endif
IMPLEMENT_MODULE ( FStateTreeModule , StateTreeModule )
2021-09-28 13:33:17 -04:00
# undef LOCTEXT_NAMESPACE