2022-05-31 04:51:18 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# pragma once
# include "StateTree.h"
2023-05-23 10:46:16 -04:00
# include "StateTreeExecutionTypes.h"
2022-06-29 04:52:18 -04:00
# include "StateTreeNodeBase.h"
2022-09-23 20:02:42 -04:00
# include "Experimental/ConcurrentLinearAllocator.h"
2022-05-31 04:51:18 -04:00
2023-01-25 02:42:36 -05:00
struct FGameplayTag ;
struct FInstancedPropertyBag ;
2023-12-13 06:34:27 -05:00
struct FStateTreeExecutionContext ;
2022-05-31 04:51:18 -04:00
struct FStateTreeEvaluatorBase ;
struct FStateTreeTaskBase ;
struct FStateTreeConditionBase ;
2022-09-01 09:06:53 -04:00
struct FStateTreeEvent ;
2023-01-23 12:48:04 -05:00
struct FStateTreeTransitionRequest ;
2023-03-14 13:35:46 -04:00
struct FStateTreeInstanceDebugId ;
2022-05-31 04:51:18 -04:00
/**
2023-12-13 06:34:27 -05:00
* Delegate used by the execution context to collect external data views for a given StateTree asset .
* The caller is expected to iterate over the ExternalDataDescs array , find the matching external data ,
* and store it in the OutDataViews at the same index :
*
* for ( int32 Index = 0 ; Index < ExternalDataDescs . Num ( ) ; Index + + )
* {
* const FStateTreeExternalDataDesc & Desc = ExternalDataDescs [ Index ] ;
* // Find data requested by Desc
* OutDataViews [ Index ] = . . . ;
* }
*/
DECLARE_DELEGATE_RetVal_FourParams ( bool , FOnCollectStateTreeExternalData , const FStateTreeExecutionContext & /*Context*/ , const UStateTree * /*StateTree*/ , TArrayView < const FStateTreeExternalDataDesc > /*ExternalDataDescs*/ , TArrayView < FStateTreeDataView > /*OutDataViews*/ ) ;
/**
* StateTree Execution Context is a helper that is used to update StateTree instance data .
2022-09-23 20:02:42 -04:00
*
* The context is meant to be temporary , you should not store a context across multiple frames .
*
2023-12-13 06:34:27 -05:00
* The owner is used as the owner of the instantiated UObjects in the instance data and logging ,
* it should have same or greater lifetime as the InstanceData .
2022-09-23 20:02:42 -04:00
*
2023-12-13 06:34:27 -05:00
* In common case you can use the constructor to initialize the context , and us a helper struct
* to set up the context data and external data getter :
2022-09-23 20:02:42 -04:00
*
* FStateTreeExecutionContext Context ( * GetOwner ( ) , * StateTreeRef . GetStateTree ( ) , InstanceData ) ;
* if ( SetContextRequirements ( Context ) )
* {
* Context . Tick ( DeltaTime ) ;
* }
2023-12-13 06:34:27 -05:00
*
2022-09-23 20:02:42 -04:00
*
* bool UMyComponent : : SetContextRequirements ( FStateTreeExecutionContext & Context )
* {
* if ( ! Context . IsValid ( ) )
* {
* return false ;
* }
* // Setup context data
2023-12-13 06:34:27 -05:00
* Context . SetContextDataByName ( . . . ) ;
* . . .
*
* Context . SetCollectExternalDataCallback ( FOnCollectStateTreeExternalData : : CreateUObject ( this , & UMyComponent : : CollectExternalData ) ;
*
* return Context . AreContextDataViewsValid ( ) ;
* }
*
* bool UMyComponent : : CollectExternalData ( const FStateTreeExecutionContext & Context , const UStateTree * StateTree , TArrayView < const FStateTreeExternalDataDesc > ExternalDataDescs , TArrayView < FStateTreeDataView > OutDataViews )
* {
* . . .
* for ( int32 Index = 0 ; Index < ExternalDataDescs . Num ( ) ; Index + + )
* {
* const FStateTreeExternalDataDesc & Desc = ExternalDataDescs [ Index ] ;
* if ( Desc . Struct - > IsChildOf ( UWorldSubsystem : : StaticClass ( ) ) )
* {
* UWorldSubsystem * Subsystem = World - > GetSubsystemBase ( Cast < UClass > ( const_cast < UStruct * > ( Desc . Struct . Get ( ) ) ) ) ;
* OutDataViews [ Index ] = FStateTreeDataView ( Subsystem ) ;
* }
* . . .
* }
2022-09-23 20:02:42 -04:00
* return true ;
* }
2023-12-13 06:34:27 -05:00
*
* In this example the SetContextRequirements ( ) method is used to set the context defined in the schema ,
* and the delegate FOnCollectStateTreeExternalData is used to query the external data required by the tasks and conditions .
*
* In case the State Tree links to other state tree assets , the collect external data might get called
* multiple times , once for each asset .
2022-05-31 04:51:18 -04:00
*/
struct STATETREEMODULE_API FStateTreeExecutionContext
{
public :
2023-12-13 06:34:27 -05:00
FStateTreeExecutionContext ( UObject & InOwner , const UStateTree & InStateTree , FStateTreeInstanceData & InInstanceData , const FOnCollectStateTreeExternalData & CollectExternalDataCallback = { } ) ;
2022-05-31 04:51:18 -04:00
virtual ~ FStateTreeExecutionContext ( ) ;
/** Updates data view of the parameters by using the default values defined in the StateTree asset. */
2024-01-22 05:38:03 -05:00
UE_DEPRECATED ( 5.4 , " Not providing parameters to Start() leads to setting up default values now. " )
2022-05-31 04:51:18 -04:00
void SetDefaultParameters ( ) ;
/**
* Updates data view of the parameters by replacing the default values defined in the StateTree asset by the provided values .
* Note : caller is responsible to make sure external parameters lifetime matches the context .
*/
2024-01-22 05:38:03 -05:00
UE_DEPRECATED ( 5.4 , " Provide parameters through Start() instead. " )
2022-05-31 04:51:18 -04:00
void SetParameters ( const FInstancedPropertyBag & Parameters ) ;
2023-12-13 06:34:27 -05:00
/** Sets callback used to collect external data views during State Tree execution. */
void SetCollectExternalDataCallback ( const FOnCollectStateTreeExternalData & Callback ) ;
2022-05-31 04:51:18 -04:00
2022-09-23 20:02:42 -04:00
/** @return the StateTree asset in use. */
2023-11-22 04:08:33 -05:00
const UStateTree * GetStateTree ( ) const { return & RootStateTree ; }
2022-05-31 04:51:18 -04:00
2022-11-01 15:11:19 -04:00
/** @return const references to the instance data in use, or nullptr if the context is not valid. */
2022-09-23 20:02:42 -04:00
const FStateTreeInstanceData * GetInstanceData ( ) const { return & InstanceData ; }
2022-05-31 04:51:18 -04:00
2022-11-01 15:11:19 -04:00
/** @retuen mutable references to the instance data in use, or nullptr if the context is not valid. */
2022-09-23 20:02:42 -04:00
FStateTreeInstanceData * GetMutableInstanceData ( ) const { return & InstanceData ; }
2022-11-01 15:11:19 -04:00
2022-11-30 07:17:26 -05:00
/** @return mutable references to the instance data in use. */
const FStateTreeEventQueue & GetEventQueue ( ) const { return InstanceData . GetEventQueue ( ) ; }
/** @return mutable references to the instance data in use. */
FStateTreeEventQueue & GetMutableEventQueue ( ) const { return InstanceData . GetMutableEventQueue ( ) ; }
2022-11-01 15:11:19 -04:00
2022-05-31 04:51:18 -04:00
/** @return The owner of the context */
2022-09-23 20:02:42 -04:00
UObject * GetOwner ( ) const { return & Owner ; }
2022-05-31 04:51:18 -04:00
/** @return The world of the owner or nullptr if the owner is not set. */
2022-09-23 20:02:42 -04:00
UWorld * GetWorld ( ) const { return Owner . GetWorld ( ) ; } ;
2022-05-31 04:51:18 -04:00
/** @return True of the the execution context is valid and initialized. */
2023-11-22 04:08:33 -05:00
bool IsValid ( ) const { return RootStateTree . IsReadyToRun ( ) ; }
2024-01-11 04:24:45 -05:00
/**
* @ param PropertyRef Property ' s reference to get pointer to .
* @ return Pointer to referenced property if succeeded .
*/
template < class T >
T * GetMutablePropertyPtr ( const FStateTreePropertyRef & PropertyRef )
{
const FStateTreePropertyBindings & PropertyBindings = CurrentlyProcessedFrame - > StateTree - > PropertyBindings ;
if ( const FStateTreePropertyAccess * PropertyAccess = PropertyBindings . GetPropertyAccess ( PropertyRef ) )
{
FStateTreeDataView SourceView = GetDataView ( CurrentlyProcessedParentFrame , * CurrentlyProcessedFrame , PropertyAccess - > SourceDataHandle ) ;
return PropertyBindings . GetMutablePropertyPtr < T > ( SourceView , * PropertyAccess ) ;
}
return nullptr ;
}
2022-05-31 04:51:18 -04:00
2024-01-22 05:38:03 -05:00
/**
* Start executing .
* @ param InitialParameters Optional override of parameters initial values
* @ return Tree execution status after the start .
*/
EStateTreeRunStatus Start ( const FInstancedPropertyBag * InitialParameters = nullptr ) ;
2022-09-23 20:02:42 -04:00
2023-06-05 06:33:07 -04:00
/**
* Stop executing if the tree is running .
* @ param CompletionStatus Status ( and terminal state ) reported in the transition when the tree is stopped .
* @ return Tree execution status at stop , can be CompletionStatus , or earlier status if the tree is not running .
*/
EStateTreeRunStatus Stop ( const EStateTreeRunStatus CompletionStatus = EStateTreeRunStatus : : Stopped ) ;
2022-05-31 04:51:18 -04:00
2022-12-16 05:45:13 -05:00
/**
* Tick the state tree logic .
* @ param DeltaTime time to advance the logic .
* @ returns tree run status after the tick .
*/
2022-09-23 20:02:42 -04:00
EStateTreeRunStatus Tick ( const float DeltaTime ) ;
2022-05-31 04:51:18 -04:00
2022-12-16 05:45:13 -05:00
/** @return the tree run status. */
EStateTreeRunStatus GetStateTreeRunStatus ( ) const ;
2022-09-01 09:06:53 -04:00
/** @return the status of the last tick function */
2022-09-23 20:02:42 -04:00
EStateTreeRunStatus GetLastTickStatus ( ) const ;
2022-09-01 09:06:53 -04:00
/** @return reference to the list of currently active states. */
2023-11-22 04:08:33 -05:00
UE_DEPRECATED ( 5.4 , " Use GetActiveFrames() instead. " )
const FStateTreeActiveStates & GetActiveStates ( ) const
{
static FStateTreeActiveStates Dummy ;
return Dummy ;
}
/** @return reference to the list of currently active frames and states. */
TConstArrayView < FStateTreeExecutionFrame > GetActiveFrames ( ) const ;
2022-09-01 09:06:53 -04:00
# if WITH_GAMEPLAY_DEBUGGER
/** @return Debug string describing the current state of the execution */
2022-09-23 20:02:42 -04:00
FString GetDebugInfoString ( ) const ;
2022-09-01 09:06:53 -04:00
# endif // WITH_GAMEPLAY_DEBUGGER
# if WITH_STATETREE_DEBUG
2022-09-23 20:02:42 -04:00
int32 GetStateChangeCount ( ) const ;
2022-09-01 09:06:53 -04:00
2022-09-23 20:02:42 -04:00
void DebugPrintInternalLayout ( ) ;
2022-09-01 09:06:53 -04:00
# endif
/** @return the name of the active state. */
2022-09-23 20:02:42 -04:00
FString GetActiveStateName ( ) const ;
2022-09-01 09:06:53 -04:00
/** @return the names of all the active state. */
2022-09-23 20:02:42 -04:00
TArray < FName > GetActiveStateNames ( ) const ;
2022-09-01 09:06:53 -04:00
2022-09-30 12:21:42 -04:00
/** Sends event for the StateTree. */
2022-11-03 14:21:53 -04:00
UE_DEPRECATED ( 5.2 , " Use AddEvent() with individual parameters instead. " )
2022-11-01 15:11:19 -04:00
void SendEvent ( const FStateTreeEvent & Event ) const ;
/** Sends event for the StateTree. */
void SendEvent ( const FGameplayTag Tag , const FConstStructView Payload = FConstStructView ( ) , const FName Origin = FName ( ) ) const ;
2022-09-01 09:06:53 -04:00
/** Iterates over all events. Can only be used during StateTree tick. Expects a lambda which takes const FStateTreeEvent& Event, and returns EStateTreeLoopEvents. */
template < typename TFunc >
void ForEachEvent ( TFunc & & Function ) const
{
for ( const FStateTreeEvent & Event : EventsToProcess )
{
if ( Function ( Event ) = = EStateTreeLoopEvents : : Break )
{
break ;
}
}
}
/** @return events to process this tick. */
TConstArrayView < FStateTreeEvent > GetEventsToProcess ( ) const { return EventsToProcess ; }
2023-01-23 12:48:04 -05:00
/** @return true if there is a pending event with specified tag. */
bool HasEventToProcess ( const FGameplayTag Tag ) const
{
if ( EventsToProcess . IsEmpty ( ) )
{
return false ;
}
return EventsToProcess . ContainsByPredicate ( [ Tag ] ( const FStateTreeEvent & Event )
{
return Event . Tag . MatchesTag ( Tag ) ;
} ) ;
}
/** @return the currently processed state if applicable. */
FStateTreeStateHandle GetCurrentlyProcessedState ( ) const { return CurrentlyProcessedState ; }
2022-09-01 09:06:53 -04:00
2022-05-31 04:51:18 -04:00
/** @return Pointer to a State or null if state not found */
const FCompactStateTreeState * GetStateFromHandle ( const FStateTreeStateHandle StateHandle ) const
{
2023-11-22 04:08:33 -05:00
return RootStateTree . GetStateFromHandle ( StateHandle ) ;
2022-05-31 04:51:18 -04:00
}
/** @return Array view to external data descriptors associated with this context. Note: Init() must be called before calling this method. */
2023-12-13 06:34:27 -05:00
UE_DEPRECATED ( 5.4 , " Use CollectStateTreeExternalData delegate instead. " )
2022-05-31 04:51:18 -04:00
TConstArrayView < FStateTreeExternalDataDesc > GetExternalDataDescs ( ) const
{
2023-11-22 04:08:33 -05:00
return RootStateTree . ExternalDataDescs ;
2022-05-31 04:51:18 -04:00
}
/** @return Array view to named external data descriptors associated with this context. Note: Init() must be called before calling this method. */
2022-09-19 19:47:11 -04:00
TConstArrayView < FStateTreeExternalDataDesc > GetContextDataDescs ( ) const
2022-05-31 04:51:18 -04:00
{
2023-11-22 04:08:33 -05:00
return RootStateTree . GetContextDataDescs ( ) ;
2022-05-31 04:51:18 -04:00
}
2023-12-13 06:34:27 -05:00
/** @return Handle to external data of type InStruct, or invalid handle if struct not found. */
UE_DEPRECATED ( 5.4 , " Not supported anymore. " )
2022-05-31 04:51:18 -04:00
FStateTreeExternalDataHandle GetExternalDataHandleByStruct ( const UStruct * InStruct ) const
{
2023-11-22 04:08:33 -05:00
const FStateTreeExternalDataDesc * DataDesc = RootStateTree . ExternalDataDescs . FindByPredicate ( [ InStruct ] ( const FStateTreeExternalDataDesc & Item ) { return Item . Struct = = InStruct ; } ) ;
2022-05-31 04:51:18 -04:00
return DataDesc ! = nullptr ? DataDesc - > Handle : FStateTreeExternalDataHandle : : Invalid ;
}
2023-12-13 06:34:27 -05:00
/** Sets context data view value for specific item. */
void SetContextData ( const FStateTreeExternalDataHandle Handle , FStateTreeDataView DataView )
2022-05-31 04:51:18 -04:00
{
check ( Handle . IsValid ( ) ) ;
2023-11-22 04:08:33 -05:00
check ( Handle . DataHandle . GetSource ( ) = = EStateTreeDataSourceType : : ContextData ) ;
2023-12-13 06:34:27 -05:00
ContextAndExternalDataViews [ Handle . DataHandle . GetIndex ( ) ] = DataView ;
}
/** Sets the context data based on name (name is defined in the schema), returns true if data was found */
bool SetContextDataByName ( const FName Name , FStateTreeDataView DataView ) ;
/** @return True if all context data pointers are set. */
bool AreContextDataViewsValid ( ) const ;
/** @return True if all required external data pointers are set. */
UE_DEPRECATED ( 5.4 , " Please AreContextDataViewsValid(). " )
bool AreExternalDataViewsValid ( ) const
{
return AreContextDataViewsValid ( ) ;
}
/** Sets external data view value for specific item. */
UE_DEPRECATED ( 5.4 , " Use SetContextData() for context data, or set SetExternalDataDelegate() to provide external data. " )
void SetExternalData ( const FStateTreeExternalDataHandle Handle , FStateTreeDataView DataView )
{
SetContextData ( Handle , DataView ) ;
2022-05-31 04:51:18 -04:00
}
/**
* Returns reference to external data based on provided handle . The return type is deduced from the handle ' s template type .
* @ param Handle Valid TStateTreeExternalDataHandle < > handle .
* @ return reference to external data based on handle or null if data is not set .
*/
template < typename T >
typename T : : DataType & GetExternalData ( const T Handle ) const
{
check ( Handle . IsValid ( ) ) ;
2023-12-13 06:34:27 -05:00
check ( Handle . DataHandle . GetSource ( ) = = EStateTreeDataSourceType : : ExternalData ) ;
check ( CurrentlyProcessedFrame ) ;
check ( CurrentlyProcessedFrame - > StateTree - > ExternalDataDescs [ Handle . DataHandle . GetIndex ( ) ] . Requirement ! = EStateTreeExternalDataRequirement : : Optional ) ; // Optionals should query pointer instead.
return ContextAndExternalDataViews [ CurrentlyProcessedFrame - > ExternalDataBaseIndex . Get ( ) + Handle . DataHandle . GetIndex ( ) ] . template GetMutable < typename T : : DataType > ( ) ;
2022-05-31 04:51:18 -04:00
}
/**
* Returns pointer to external data based on provided item handle . The return type is deduced from the handle ' s template type .
* @ param Handle Valid TStateTreeExternalDataHandle < > handle .
* @ return pointer to external data based on handle or null if item is not set or handle is invalid .
*/
template < typename T >
typename T : : DataType * GetExternalDataPtr ( const T Handle ) const
{
2023-11-22 04:08:33 -05:00
if ( Handle . IsValid ( ) )
{
2023-12-13 06:34:27 -05:00
check ( CurrentlyProcessedFrame ) ;
check ( Handle . DataHandle . GetSource ( ) = = EStateTreeDataSourceType : : ExternalData ) ;
return ContextAndExternalDataViews [ CurrentlyProcessedFrame - > ExternalDataBaseIndex . Get ( ) + Handle . DataHandle . GetIndex ( ) ] . template GetMutablePtr < typename T : : DataType > ( ) ;
2023-11-22 04:08:33 -05:00
}
return nullptr ;
2022-05-31 04:51:18 -04:00
}
FStateTreeDataView GetExternalDataView ( const FStateTreeExternalDataHandle Handle )
{
if ( Handle . IsValid ( ) )
{
2023-12-13 06:34:27 -05:00
check ( CurrentlyProcessedFrame ) ;
check ( Handle . DataHandle . GetSource ( ) = = EStateTreeDataSourceType : : ExternalData ) ;
return ContextAndExternalDataViews [ CurrentlyProcessedFrame - > ExternalDataBaseIndex . Get ( ) + Handle . DataHandle . GetIndex ( ) ] ;
2022-05-31 04:51:18 -04:00
}
return FStateTreeDataView ( ) ;
}
2022-06-29 04:52:18 -04:00
/** @returns pointer to the instance data of specified node. */
template < typename T >
T * GetInstanceDataPtr ( const FStateTreeNodeBase & Node ) const
{
2023-11-30 07:03:20 -05:00
check ( CurrentNodeDataHandle = = Node . InstanceDataHandle ) ;
return CurrentNodeInstanceData . template GetMutablePtr < T > ( ) ;
2022-06-29 04:52:18 -04:00
}
/** @returns reference to the instance data of specified node. */
template < typename T >
T & GetInstanceData ( const FStateTreeNodeBase & Node ) const
{
2023-11-30 07:03:20 -05:00
check ( CurrentNodeDataHandle = = Node . InstanceDataHandle ) ;
return CurrentNodeInstanceData . template GetMutable < T > ( ) ;
2022-06-29 04:52:18 -04:00
}
2022-09-29 20:26:53 -04:00
/** @returns reference to the instance data of specified node. Infers the instance data type from the node's FInstanceDataType. */
template < typename T >
typename T : : FInstanceDataType & GetInstanceData ( const T & Node ) const
{
static_assert ( TIsDerivedFrom < T , FStateTreeNodeBase > : : IsDerived , " Expecting Node to derive from FStateTreeNodeBase. " ) ;
2023-11-30 07:03:20 -05:00
check ( CurrentNodeDataHandle = = Node . InstanceDataHandle ) ;
return CurrentNodeInstanceData . template GetMutable < typename T : : FInstanceDataType > ( ) ;
2022-09-29 20:26:53 -04:00
}
2022-11-01 15:11:19 -04:00
/** @returns reference to instance data struct that can be passed to lambdas. See TStateTreeInstanceDataStructRef for usage. */
template < typename T >
TStateTreeInstanceDataStructRef < typename T : : FInstanceDataType > GetInstanceDataStructRef ( const T & Node ) const
{
static_assert ( TIsDerivedFrom < T , FStateTreeNodeBase > : : IsDerived , " Expecting Node to derive from FStateTreeNodeBase. " ) ;
2023-11-22 04:08:33 -05:00
check ( CurrentlyProcessedFrame ) ;
2023-11-30 07:03:20 -05:00
return TStateTreeInstanceDataStructRef < typename T : : FInstanceDataType > ( InstanceData , * CurrentlyProcessedFrame , Node . InstanceDataHandle ) ;
2022-11-01 15:11:19 -04:00
}
2023-01-23 12:48:04 -05:00
/**
* Requests transition to a state .
* If called during during transition processing ( e . g . from FStateTreeTaskBase : : TriggerTransitions ( ) ) the transition
* is attempted to be activate immediately ( it can fail e . g . because of preconditions on a target state ) .
* If called outside the transition handling , the request is buffered and handled at the beginning of next transition processing .
* @ param Request The state to transition to .
*/
void RequestTransition ( const FStateTreeTransitionRequest & Request ) ;
2022-05-31 04:51:18 -04:00
protected :
2023-11-22 04:08:33 -05:00
/** Max number of execution frames handled during state selection. */
static constexpr int32 MaxExecutionFrames = 8 ;
2023-03-14 13:35:46 -04:00
# if WITH_STATETREE_DEBUGGER
FStateTreeInstanceDebugId GetInstanceDebugId ( ) const ;
# endif // WITH_STATETREE_DEBUGGER
/** @return Prefix that will be used by STATETREE_LOG and STATETREE_CLOG, Owner name by default. */
2022-05-31 04:51:18 -04:00
virtual FString GetInstanceDescription ( ) const ;
2022-12-02 07:57:31 -05:00
/** Callback when delayed transition is triggered. Contexts that are event based can use this to trigger a future event. */
virtual void BeginDelayedTransition ( const FStateTreeTransitionDelayedState & DelayedState ) { } ;
2022-05-31 04:51:18 -04:00
2023-11-22 04:08:33 -05:00
void UpdateInstanceData ( TConstArrayView < FStateTreeExecutionFrame > CurrentActiveFrames , TArrayView < FStateTreeExecutionFrame > NextActiveFrames ) ;
2022-05-31 04:51:18 -04:00
/**
* Handles logic for entering State . EnterState is called on new active Evaluators and Tasks that are part of the re - planned tree .
* Re - planned tree is from the transition target up to the leaf state . States that are parent to the transition target state
* and still active after the transition will remain intact .
* @ return Run status returned by the tasks .
*/
2023-11-22 04:08:33 -05:00
EStateTreeRunStatus EnterState ( FStateTreeTransitionResult & Transition ) ;
2022-05-31 04:51:18 -04:00
/**
* Handles logic for exiting State . ExitState is called on current active Evaluators and Tasks that are part of the re - planned tree .
* Re - planned tree is from the transition target up to the leaf state . States that are parent to the transition target state
* and still active after the transition will remain intact .
*/
2022-09-23 20:02:42 -04:00
void ExitState ( const FStateTreeTransitionResult & Transition ) ;
2022-05-31 04:51:18 -04:00
/**
* Handles logic for signalling State completed . StateCompleted is called on current active Evaluators and Tasks in reverse order ( from leaf to root ) .
*/
2022-09-23 20:02:42 -04:00
void StateCompleted ( ) ;
2022-05-31 04:51:18 -04:00
/**
2023-01-10 15:44:28 -05:00
* Tick evaluators and global tasks by delta time .
2022-05-31 04:51:18 -04:00
*/
2023-01-10 15:44:28 -05:00
EStateTreeRunStatus TickEvaluatorsAndGlobalTasks ( const float DeltaTime , bool bTickGlobalTasks = true ) ;
2022-05-31 04:51:18 -04:00
2023-01-10 15:44:28 -05:00
/**
* Starts evaluators and global tasks .
2023-06-05 06:33:07 -04:00
* @ return run status returned by the global tasks .
2023-01-10 15:44:28 -05:00
*/
2023-06-05 06:33:07 -04:00
EStateTreeRunStatus StartEvaluatorsAndGlobalTasks ( FStateTreeIndex16 & OutLastInitializedTaskIndex ) ;
2022-05-31 04:51:18 -04:00
2023-01-10 15:44:28 -05:00
/**
* Stops evaluators and global tasks .
*/
2023-06-05 06:33:07 -04:00
void StopEvaluatorsAndGlobalTasks ( const EStateTreeRunStatus CompletionStatus , const FStateTreeIndex16 LastInitializedTaskIndex = FStateTreeIndex16 ( ) ) ;
2022-05-31 04:51:18 -04:00
2023-11-30 07:03:20 -05:00
/** Starts temporary instances of global evaluators and tasks for a given frame. */
EStateTreeRunStatus StartTemporaryEvaluatorsAndGlobalTasks ( const FStateTreeExecutionFrame * CurrentParentFrame , const FStateTreeExecutionFrame & CurrentFrame ) ;
/** Stops leftover global evaluators and tasks in the provided temporary instance data. */
void StopTemporaryEvaluatorsAndGlobalTasks ( TArrayView < FStateTreeTemporaryInstanceData > TempInstances ) ;
2022-05-31 04:51:18 -04:00
/**
* Ticks tasks of all active states starting from current state by delta time .
* @ return Run status returned by the tasks .
*/
2022-09-23 20:02:42 -04:00
EStateTreeRunStatus TickTasks ( const float DeltaTime ) ;
2022-05-31 04:51:18 -04:00
/**
* Checks all conditions at given range
* @ return True if all conditions pass .
*/
2023-11-30 07:03:20 -05:00
bool TestAllConditions ( const FStateTreeExecutionFrame * CurrentParentFrame , const FStateTreeExecutionFrame & CurrentFrame , const int32 ConditionsOffset , const int32 ConditionsNum ) ;
2022-05-31 04:51:18 -04:00
2022-12-02 07:57:31 -05:00
/**
2023-01-23 12:48:04 -05:00
* Requests transition to a specified state with specified priority .
2022-12-02 07:57:31 -05:00
*/
2023-11-22 04:08:33 -05:00
bool RequestTransition (
const FStateTreeExecutionFrame & CurrentFrame ,
const FStateTreeStateHandle NextState ,
const EStateTreeTransitionPriority Priority ,
const EStateTreeSelectionFallback Fallback = EStateTreeSelectionFallback : : None ) ;
2023-09-22 09:53:34 -04:00
/**
* Sets up NextTransition based on the provided parameters and the current execution status .
*/
2023-11-22 04:08:33 -05:00
void SetupNextTransition ( const FStateTreeExecutionFrame & CurrentFrame , const FStateTreeStateHandle NextState , const EStateTreeTransitionPriority Priority ) ;
2022-12-02 07:57:31 -05:00
2022-05-31 04:51:18 -04:00
/**
* Triggers transitions based on current run status . CurrentStatus is used to select which transitions events are triggered .
* If CurrentStatus is " Running " , " Conditional " transitions pass , " Completed/Failed " will trigger " OnCompleted/OnSucceeded/OnFailed " transitions .
* Transition target state can point to a selector state . For that reason the result contains both the target state , as well ass
* the actual next state returned by the selector .
* @ return Transition result describing the source state , state transitioned to , and next selected state .
*/
2023-01-23 12:48:04 -05:00
bool TriggerTransitions ( ) ;
2022-05-31 04:51:18 -04:00
/**
* Runs state selection logic starting at the specified state , walking towards the leaf states .
* If a state cannot be selected , false is returned .
* If NextState is a selector state , SelectStateInternal is called recursively ( depth - first ) to all child states ( where NextState will be one of child states ) .
* If NextState is a leaf state , the active states leading from root to the leaf are returned .
2023-11-22 04:08:33 -05:00
* @ param CurrentFrame The frame where the NextState is valid .
2022-05-31 04:51:18 -04:00
* @ param NextState The state which we try to select next .
2023-11-22 04:08:33 -05:00
* @ param OutNextActiveFrames Active frames and states that got selected .
2023-10-17 16:15:53 -04:00
* @ param Fallback selection behavior to execute if it fails to select the desired state
2022-05-31 04:51:18 -04:00
* @ return True if succeeded to select new active states .
*/
2023-11-22 04:08:33 -05:00
bool SelectState (
const FStateTreeExecutionFrame & CurrentFrame ,
const FStateTreeStateHandle NextState ,
TArray < FStateTreeExecutionFrame , TFixedAllocator < MaxExecutionFrames > > & OutNextActiveFrames ,
const EStateTreeSelectionFallback Fallback = EStateTreeSelectionFallback : : None ) ;
2022-05-31 04:51:18 -04:00
/**
* Used internally to do the recursive part of the SelectState ( ) .
*/
2023-11-22 04:08:33 -05:00
bool SelectStateInternal (
2023-11-30 07:03:20 -05:00
const FStateTreeExecutionFrame * CurrentParentFrame ,
2023-11-22 04:08:33 -05:00
FStateTreeExecutionFrame & CurrentFrame ,
2023-12-01 06:43:27 -05:00
const FStateTreeExecutionFrame * CurrentFrameInActiveFrames ,
2023-11-30 07:03:20 -05:00
const FStateTreeStateHandle NextStateHandle ,
2023-11-22 04:08:33 -05:00
TArray < FStateTreeExecutionFrame , TFixedAllocator < MaxExecutionFrames > > & OutNextActiveFrames ) ;
2022-05-31 04:51:18 -04:00
/** @return StateTree execution state from the instance storage. */
2022-09-23 20:02:42 -04:00
FStateTreeExecutionState & GetExecState ( )
2022-05-31 04:51:18 -04:00
{
2023-11-22 04:08:33 -05:00
return * InstanceData . GetMutableExecutionState ( ) ;
2022-05-31 04:51:18 -04:00
}
/** @return const StateTree execution state from the instance storage. */
2022-09-23 20:02:42 -04:00
const FStateTreeExecutionState & GetExecState ( ) const
2022-05-31 04:51:18 -04:00
{
2023-11-22 04:08:33 -05:00
return * InstanceData . GetExecutionState ( ) ;
2022-05-31 04:51:18 -04:00
}
/** @return String describing state status for logging and debug. */
FString GetStateStatusString ( const FStateTreeExecutionState & ExecState ) const ;
/** @return String describing state name for logging and debug. */
2023-11-22 04:08:33 -05:00
FString GetSafeStateName ( const FStateTreeExecutionFrame & CurrentFrame , const FStateTreeStateHandle State ) const ;
2022-05-31 04:51:18 -04:00
/** @return String describing full path of an activate state for logging and debug. */
2023-11-22 04:08:33 -05:00
FString DebugGetStatePath ( TConstArrayView < FStateTreeExecutionFrame > ActiveFrames , const FStateTreeExecutionFrame * CurrentFrame = nullptr , const int32 ActiveStateIndex = INDEX_NONE ) const ;
2022-05-31 04:51:18 -04:00
2022-11-01 15:11:19 -04:00
/** @return String describing all events that are currently being processed for logging and debug. */
FString DebugGetEventsAsString ( ) const ;
2023-11-22 04:08:33 -05:00
/** @return data view of the specified handle relative to given frame. */
2023-11-30 07:03:20 -05:00
FStateTreeDataView GetDataView ( const FStateTreeExecutionFrame * ParentFrame , const FStateTreeExecutionFrame & CurrentFrame , const FStateTreeDataHandle Handle ) const ;
2023-11-22 04:08:33 -05:00
/** @return data view of the specified handle relative to given frame. */
2023-11-30 07:03:20 -05:00
bool IsHandleSourceValid ( const FStateTreeExecutionFrame * ParentFrame , const FStateTreeExecutionFrame & CurrentFrame , const FStateTreeDataHandle Handle ) const ;
2022-09-23 20:02:42 -04:00
2023-11-30 07:03:20 -05:00
/** @return data view of the specified handle relative to the given frame, or tries to find a matching temporary instance. */
FStateTreeDataView GetDataViewOrTemporary ( const FStateTreeExecutionFrame * ParentFrame , const FStateTreeExecutionFrame & CurrentFrame , const FStateTreeDataHandle Handle ) const ;
/**
* Adds a temporary instance that can be located using frame and data handle later .
* @ returns view to the newly added instance . If NewInstanceData is Object wrapper , the new object is returned .
*/
FStateTreeDataView AddTemporaryInstance ( const FStateTreeExecutionFrame & Frame , const FStateTreeIndex16 OwnerNodeIndex , const FStateTreeDataHandle DataHandle , FConstStructView NewInstanceData ) ;
/** Copies a batch of properties to the data in TargetView. Should be used only on active instances, assumes valid handles and does not consider temporary instances. */
bool CopyBatchOnActiveInstances ( const FStateTreeExecutionFrame * ParentFrame , const FStateTreeExecutionFrame & CurrentFrame , const FStateTreeDataView TargetView , const FStateTreeIndex16 BindingsBatch ) const ;
/** Copies a batch of properties to the data in TargetView. This version validates the data handles and looks up temporary instances. */
bool CopyBatchWithValidation ( const FStateTreeExecutionFrame * ParentFrame , const FStateTreeExecutionFrame & CurrentFrame , const FStateTreeDataView TargetView , const FStateTreeIndex16 BindingsBatch ) const ;
2023-12-13 06:34:27 -05:00
2023-12-14 03:17:43 -05:00
/**
* Collects external data for all StateTrees in active frames .
* @ returns true if all external data are set successfully . */
2023-12-13 06:34:27 -05:00
bool CollectActiveExternalData ( ) ;
/**
2023-12-14 03:17:43 -05:00
* Collects external data for specific State Tree asset . If the data is already collected , cached index is returned .
2023-12-13 06:34:27 -05:00
* @ returns index in ContextAndExternalDataViews for the first external data .
*/
FStateTreeIndex16 CollectExternalData ( const UStateTree * StateTree ) ;
2024-01-22 05:38:03 -05:00
/**
* Stores copy of provided parameters as State Tree global parameters .
* @ param Parameters parameters to copy
* @ returns true if successfully set the parameters
*/
bool SetGlobalParameters ( const FInstancedPropertyBag & Parameters ) ;
2023-11-30 07:03:20 -05:00
2022-09-23 20:02:42 -04:00
/** Owner of the instance data. */
UObject & Owner ;
2022-05-31 04:51:18 -04:00
/** The StateTree asset the context is initialized for */
2023-11-22 04:08:33 -05:00
const UStateTree & RootStateTree ;
2022-05-31 04:51:18 -04:00
2022-09-01 09:06:53 -04:00
/** Instance data used during current tick. */
2022-09-23 20:02:42 -04:00
FStateTreeInstanceData & InstanceData ;
2022-09-01 09:06:53 -04:00
2023-11-22 04:08:33 -05:00
/** Data storage of the instance data, cached for less indirections. */
FStateTreeInstanceStorage * InstanceDataStorage = nullptr ;
2022-09-01 09:06:53 -04:00
2023-11-22 04:08:33 -05:00
/** Data view of the context data. */
2023-12-13 06:34:27 -05:00
TArray < FStateTreeDataView , TConcurrentLinearArrayAllocator < FDefaultBlockAllocationTag > > ContextAndExternalDataViews ;
2022-09-01 09:06:53 -04:00
/** Events to process in current tick. */
2022-09-23 20:02:42 -04:00
TArray < FStateTreeEvent , TConcurrentLinearArrayAllocator < FDefaultBlockAllocationTag > > EventsToProcess ;
2023-01-23 12:48:04 -05:00
2023-12-13 06:34:27 -05:00
FOnCollectStateTreeExternalData CollectExternalDataDelegate ;
struct FCollectedExternalDataCache
{
const UStateTree * StateTree = nullptr ;
FStateTreeIndex16 BaseIndex ;
} ;
TArray < FCollectedExternalDataCache , TConcurrentLinearArrayAllocator < FDefaultBlockAllocationTag > > CollectedExternalCache ;
bool bActiveExternalDataCollected = false ;
2023-11-22 04:08:33 -05:00
2023-01-23 12:48:04 -05:00
/** Next transition, used by RequestTransition(). */
FStateTreeTransitionResult NextTransition ;
2023-08-04 14:55:23 -04:00
/** Structure describing the origin of the state transition that caused the state change. */
FStateTreeTransitionSource NextTransitionSource ;
2023-06-20 13:49:25 -04:00
2023-11-22 04:08:33 -05:00
/** Current frame we're processing. */
2023-11-30 07:03:20 -05:00
const FStateTreeExecutionFrame * CurrentlyProcessedParentFrame = nullptr ;
2023-11-22 04:08:33 -05:00
const FStateTreeExecutionFrame * CurrentlyProcessedFrame = nullptr ;
/** Pointer to the shared instance data of the current frame we're processing. */
FStateTreeInstanceStorage * CurrentlyProcessedSharedInstanceStorage = nullptr ;
/** Helper struct to track currently processed frame. */
struct FCurrentlyProcessedFrameScope
{
2023-12-13 10:21:13 -05:00
FCurrentlyProcessedFrameScope ( FStateTreeExecutionContext & InContext , const FStateTreeExecutionFrame * CurrentParentFrame , const FStateTreeExecutionFrame & CurrentFrame ) ;
2023-11-22 04:08:33 -05:00
2023-12-13 10:21:13 -05:00
~ FCurrentlyProcessedFrameScope ( ) ;
2023-11-22 04:08:33 -05:00
private :
FStateTreeExecutionContext & Context ;
int32 SavedFrameIndex = 0 ;
FStateTreeInstanceStorage * SavedSharedInstanceDataStorage = nullptr ;
const FStateTreeExecutionFrame * SavedFrame = nullptr ;
2023-11-30 07:03:20 -05:00
const FStateTreeExecutionFrame * SavedParentFrame = nullptr ;
2023-11-22 04:08:33 -05:00
} ;
2023-01-23 12:48:04 -05:00
/** Current state we're processing, or invalid if not applicable. */
FStateTreeStateHandle CurrentlyProcessedState ;
2023-11-22 04:08:33 -05:00
/** Helper struct to track currently processed state. */
struct FCurrentlyProcessedStateScope
{
FCurrentlyProcessedStateScope ( FStateTreeExecutionContext & InContext , const FStateTreeStateHandle State )
: Context ( InContext )
{
SavedState = Context . CurrentlyProcessedState ;
Context . CurrentlyProcessedState = State ;
}
~ FCurrentlyProcessedStateScope ( )
{
Context . CurrentlyProcessedState = SavedState ;
}
private :
FStateTreeExecutionContext & Context ;
FStateTreeStateHandle SavedState = FStateTreeStateHandle : : Invalid ;
} ;
2023-01-23 12:48:04 -05:00
/** True if transitions are allowed to be requested directly instead of buffering. */
bool bAllowDirectTransitions = false ;
/** Helper struct to track when it is allowed to request transitions. */
struct FAllowDirectTransitionsScope
{
FAllowDirectTransitionsScope ( FStateTreeExecutionContext & InContext )
: Context ( InContext )
{
2023-11-30 07:03:20 -05:00
bSavedAllowDirectTransitions = Context . bAllowDirectTransitions ;
2023-01-23 12:48:04 -05:00
Context . bAllowDirectTransitions = true ;
}
~ FAllowDirectTransitionsScope ( )
{
2023-11-30 07:03:20 -05:00
Context . bAllowDirectTransitions = bSavedAllowDirectTransitions ;
2023-01-23 12:48:04 -05:00
}
2023-11-22 04:08:33 -05:00
private :
2023-01-23 12:48:04 -05:00
FStateTreeExecutionContext & Context ;
2023-11-30 07:03:20 -05:00
bool bSavedAllowDirectTransitions = false ;
} ;
/** Currently processed nodes instance data. Ideally we would pass these to the nodes directly, but do not want to change the API currently. */
FStateTreeDataHandle CurrentNodeDataHandle ;
FStateTreeDataView CurrentNodeInstanceData ;
/** Helper struct to set current node data. */
struct FNodeInstanceDataScope
{
FNodeInstanceDataScope ( FStateTreeExecutionContext & InContext , const FStateTreeDataHandle InNodeDataHandle , const FStateTreeDataView InNodeInstanceData )
: Context ( InContext )
{
SavedNodeDataHandle = Context . CurrentNodeDataHandle ;
SavedNodeInstanceData = Context . CurrentNodeInstanceData ;
Context . CurrentNodeDataHandle = InNodeDataHandle ;
Context . CurrentNodeInstanceData = InNodeInstanceData ;
}
~ FNodeInstanceDataScope ( )
{
Context . CurrentNodeDataHandle = SavedNodeDataHandle ;
Context . CurrentNodeInstanceData = SavedNodeInstanceData ;
}
private :
FStateTreeExecutionContext & Context ;
FStateTreeDataHandle SavedNodeDataHandle ;
FStateTreeDataView SavedNodeInstanceData ;
2023-01-23 12:48:04 -05:00
} ;
2022-05-31 04:51:18 -04:00
} ;