|
@@ -23,23 +23,23 @@
|
|
|
|
|
|
#define EZ_ABILITY_TRACE_SCOPED_PHASE(Phase) \
|
|
|
FEzAbilityInstanceDebugId ID_NAME = GetInstanceDebugId(); \
|
|
|
- TRACE_EZ_ABILITY_PHASE_EVENT(ID_NAME, Phase, EEzAbilityTraceEventType::Push, FStateTreeStateHandle::Invalid) \
|
|
|
- ON_SCOPE_EXIT { TRACE_EZ_ABILITY_PHASE_EVENT(ID_NAME, Phase, EEzAbilityTraceEventType::Pop, FStateTreeStateHandle::Invalid) }
|
|
|
+ TRACE_EZ_ABILITY_PHASE_EVENT(ID_NAME, Phase, EEzAbilityTraceEventType::Push, FEzAbilityStateHandle::Invalid) \
|
|
|
+ ON_SCOPE_EXIT { TRACE_EZ_ABILITY_PHASE_EVENT(ID_NAME, Phase, EEzAbilityTraceEventType::Pop, FEzAbilityStateHandle::Invalid) }
|
|
|
|
|
|
#define EZ_ABILITY_TRACE_SCOPED_STATE(StateHandle) \
|
|
|
FEzAbilityInstanceDebugId ID_NAME = GetInstanceDebugId(); \
|
|
|
- TRACE_EZ_ABILITY_PHASE_EVENT(ID_NAME, EStateTreeUpdatePhase::Unset, EEzAbilityTraceEventType::Push, StateHandle) \
|
|
|
- ON_SCOPE_EXIT { TRACE_EZ_ABILITY_PHASE_EVENT(ID_NAME, EStateTreeUpdatePhase::Unset, EEzAbilityTraceEventType::Pop, StateHandle) }
|
|
|
+ TRACE_EZ_ABILITY_PHASE_EVENT(ID_NAME, EEzAbilityUpdatePhase::Unset, EEzAbilityTraceEventType::Push, StateHandle) \
|
|
|
+ ON_SCOPE_EXIT { TRACE_EZ_ABILITY_PHASE_EVENT(ID_NAME, EEzAbilityUpdatePhase::Unset, EEzAbilityTraceEventType::Pop, StateHandle) }
|
|
|
|
|
|
#define EZ_ABILITY_TRACE_SCOPED_STATE_PHASE(StateHandle, Phase) \
|
|
|
FEzAbilityInstanceDebugId ID_NAME = GetInstanceDebugId(); \
|
|
|
TRACE_EZ_ABILITY_PHASE_EVENT(ID_NAME, Phase, EEzAbilityTraceEventType::Push, StateHandle) \
|
|
|
ON_SCOPE_EXIT { TRACE_EZ_ABILITY_PHASE_EVENT(ID_NAME, Phase, EEzAbilityTraceEventType::Pop, StateHandle) }
|
|
|
|
|
|
- #define EZ_ABILITY_TRACE_INSTANCE_EVENT(EventType) TRACE_EZ_ABILITY_INSTANCE_EVENT(GetInstanceDebugId(), GetStateTree(), *GetInstanceDescription(), EventType);
|
|
|
+ #define EZ_ABILITY_TRACE_INSTANCE_EVENT(EventType) TRACE_EZ_ABILITY_INSTANCE_EVENT(GetInstanceDebugId(), GetAbility(), *GetInstanceDescription(), EventType);
|
|
|
#define EZ_ABILITY_TRACE_INSTANCE_FRAME_EVENT(InstanceDebugId, Frame) TRACE_EZ_ABILITY_INSTANCE_FRAME_EVENT(InstanceDebugId, Frame);
|
|
|
- #define EZ_ABILITY_TRACE_PHASE_BEGIN(Phase) TRACE_EZ_ABILITY_PHASE_EVENT(GetInstanceDebugId(), Phase, EEzAbilityTraceEventType::Push, FStateTreeStateHandle::Invalid)
|
|
|
- #define EZ_ABILITY_TRACE_PHASE_END(Phase) TRACE_EZ_ABILITY_PHASE_EVENT(GetInstanceDebugId(), Phase, EEzAbilityTraceEventType::Pop, FStateTreeStateHandle::Invalid)
|
|
|
+ #define EZ_ABILITY_TRACE_PHASE_BEGIN(Phase) TRACE_EZ_ABILITY_PHASE_EVENT(GetInstanceDebugId(), Phase, EEzAbilityTraceEventType::Push, FEzAbilityStateHandle::Invalid)
|
|
|
+ #define EZ_ABILITY_TRACE_PHASE_END(Phase) TRACE_EZ_ABILITY_PHASE_EVENT(GetInstanceDebugId(), Phase, EEzAbilityTraceEventType::Pop, FEzAbilityStateHandle::Invalid)
|
|
|
#define EZ_ABILITY_TRACE_ACTIVE_STATES_EVENT(ActiveFrames) TRACE_EZ_ABILITY_ACTIVE_STATES_EVENT(GetInstanceDebugId(), ActiveFrames);
|
|
|
#define EZ_ABILITY_TRACE_LOG_EVENT(Format, ...) TRACE_EZ_ABILITY_LOG_EVENT(GetInstanceDebugId(), Format, ##__VA_ARGS__)
|
|
|
#define EZ_ABILITY_TRACE_STATE_EVENT(StateHandle, EventType) TRACE_EZ_ABILITY_STATE_EVENT(GetInstanceDebugId(), StateHandle, EventType);
|
|
@@ -64,6 +64,11 @@
|
|
|
#define EZ_ABILITY_TRACE_TRANSITION_EVENT(Source, EventType)
|
|
|
#endif // WITH_EZABILITY_DEBUGGER
|
|
|
|
|
|
+namespace UE::EzAbility
|
|
|
+{
|
|
|
+ constexpr int32 DebugIndentSize = 2; // Debug printing indent for hierarchical data.
|
|
|
+}
|
|
|
+
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
///Ability Context
|
|
|
|
|
@@ -150,7 +155,7 @@ bool FEzAbilityContext::IsValid() const
|
|
|
bool FEzAbilityContext::SetGlobalParameters(const FInstancedPropertyBag& Parameters) const
|
|
|
{
|
|
|
if (ensureMsgf(Ability->GetDefaultParameters().GetPropertyBagStruct() == Parameters.GetPropertyBagStruct(),
|
|
|
- TEXT("Parameters must be of the same struct type. Make sure to migrate the provided parameters to the same type as the StateTree default parameters.")))
|
|
|
+ TEXT("Parameters must be of the same struct type. Make sure to migrate the provided parameters to the same type as the EzAbility default parameters.")))
|
|
|
{
|
|
|
InstanceDataStorage->SetGlobalParameters(Parameters);
|
|
|
return true;
|
|
@@ -201,12 +206,64 @@ EAbilityRunStatus FEzAbilityContext::Start(UEzAbility* InAbility, const FEzAbili
|
|
|
InitFrame.bIsGlobalFrame = true;
|
|
|
|
|
|
UpdateInstanceData({}, State.ActiveFrames);
|
|
|
+
|
|
|
+ // Must sent instance creation event first
|
|
|
+ EZ_ABILITY_TRACE_INSTANCE_EVENT(EEzAbilityTraceEventType::Push);
|
|
|
|
|
|
- //TODO 设置默认参数
|
|
|
- //TODO 设置InstanceData
|
|
|
+ // Set scoped phase only for properly initialized context with valid Instance data
|
|
|
+ // since we need it to output the InstanceId
|
|
|
+ EZ_ABILITY_TRACE_SCOPED_PHASE(EEzAbilityUpdatePhase::Start);
|
|
|
|
|
|
+ // From this point any calls to Stop should be deferred.
|
|
|
+ State.CurrentPhase = EEzAbilityUpdatePhase::Start;
|
|
|
+
|
|
|
+ // Start evaluators and global tasks. Fail the execution if any global task fails.
|
|
|
+ FEzAbilityIndex16 LastInitializedTaskIndex;
|
|
|
+ const EAbilityRunStatus GlobalTasksRunStatus = StartEvaluatorsAndGlobalTasks(LastInitializedTaskIndex);
|
|
|
+
|
|
|
+ if (GlobalTasksRunStatus == EAbilityRunStatus::Running)
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ //StopEvaluatorsAndGlobalTasks(GlobalTasksRunStatus, LastInitializedTaskIndex);
|
|
|
+
|
|
|
+ EZ_ABILITY_LOG(VeryVerbose, TEXT("%hs: Global tasks completed the EzAbility %s on start in status '%s'."),
|
|
|
+ __FUNCTION__, *GetNameSafe(Owner), *GetFullNameSafe(GetAbility()), *UEnum::GetDisplayValueAsText(GlobalTasksRunStatus).ToString());
|
|
|
+
|
|
|
+ // No active states or global tasks anymore, reset frames.
|
|
|
+ State.ActiveFrames.Reset();
|
|
|
+
|
|
|
+ // We are not considered as running yet so we only set the status without requiring a stop.
|
|
|
+ State.TreeRunStatus = GlobalTasksRunStatus;
|
|
|
+ }
|
|
|
|
|
|
- return EAbilityRunStatus::Running;
|
|
|
+ // Reset phase since we are now safe to stop.
|
|
|
+ State.CurrentPhase = EEzAbilityUpdatePhase::Unset;
|
|
|
+
|
|
|
+ // Use local for resulting run state since Stop will reset the instance data.
|
|
|
+ EAbilityRunStatus Result = State.TreeRunStatus;
|
|
|
+
|
|
|
+ if (State.RequestedStop != EAbilityRunStatus::Unset)
|
|
|
+ {
|
|
|
+ EZ_ABILITY_LOG_AND_TRACE(VeryVerbose, TEXT("Processing Deferred Stop"));
|
|
|
+ Result = Stop(State.RequestedStop);
|
|
|
+ }
|
|
|
+
|
|
|
+ return Result;
|
|
|
+}
|
|
|
+
|
|
|
+EAbilityRunStatus FEzAbilityContext::Stop(const EAbilityRunStatus CompletionStatus)
|
|
|
+{
|
|
|
+ // Trace before resetting the instance data since it is required to provide all the event information
|
|
|
+ EZ_ABILITY_TRACE_ACTIVE_STATES_EVENT({});
|
|
|
+ EZ_ABILITY_TRACE_INSTANCE_EVENT(EEzAbilityTraceEventType::Pop);
|
|
|
+
|
|
|
+ // Destruct all allocated instance data (does not shrink the buffer). This will invalidate Exec too.
|
|
|
+ InstanceData.Reset();
|
|
|
+
|
|
|
+ return EAbilityRunStatus::Failed;
|
|
|
}
|
|
|
|
|
|
EAbilityRunStatus FEzAbilityContext::GetAbilityRunStatus() const
|
|
@@ -298,13 +355,13 @@ TArray<FName> FEzAbilityContext::GetActiveStateNames() const
|
|
|
// Active States
|
|
|
for (const FEzAbilityExecutionFrame& CurrentFrame : Exec.ActiveFrames)
|
|
|
{
|
|
|
- const UEzAbility* CurrentStateTree = CurrentFrame.Ability;
|
|
|
+ const UEzAbility* CurrentEzAbility = CurrentFrame.Ability;
|
|
|
for (int32 Index = 0; Index < CurrentFrame.ActiveStates.Num(); Index++)
|
|
|
{
|
|
|
const FEzAbilityStateHandle Handle = CurrentFrame.ActiveStates[Index];
|
|
|
if (Handle.IsValid())
|
|
|
{
|
|
|
- const FCompactEzAbilityState& State = CurrentStateTree->States[Handle.Index];
|
|
|
+ const FCompactEzAbilityState& State = CurrentEzAbility->States[Handle.Index];
|
|
|
Result.Add(State.Name);
|
|
|
}
|
|
|
}
|
|
@@ -611,6 +668,94 @@ void FEzAbilityContext::StopTemporaryEvaluatorsAndGlobalTasks(TArrayView<FEzAbil
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+EAbilityRunStatus FEzAbilityContext::StartEvaluatorsAndGlobalTasks(FEzAbilityIndex16& OutLastInitializedTaskIndex)
|
|
|
+{
|
|
|
+ CSV_SCOPED_TIMING_STAT_EXCLUSIVE(EzAbility_StartEvaluators);
|
|
|
+ EZ_ABILITY_TRACE_SCOPED_PHASE(EEzAbilityUpdatePhase::StartGlobalTasks);
|
|
|
+
|
|
|
+ EZ_ABILITY_LOG(Verbose, TEXT("Start Evaluators & Global tasks"));
|
|
|
+
|
|
|
+ FEzAbilityExecutionState& State = GetExecState();
|
|
|
+
|
|
|
+ OutLastInitializedTaskIndex = FEzAbilityIndex16();
|
|
|
+ EAbilityRunStatus Result = EAbilityRunStatus::Running;
|
|
|
+
|
|
|
+ for (int32 FrameIndex = 0; FrameIndex < State.ActiveFrames.Num(); FrameIndex++)
|
|
|
+ {
|
|
|
+ FEzAbilityExecutionFrame* CurrentParentFrame = FrameIndex > 0 ? &State.ActiveFrames[FrameIndex - 1] : nullptr;
|
|
|
+ FEzAbilityExecutionFrame& CurrentFrame = State.ActiveFrames[FrameIndex];
|
|
|
+
|
|
|
+ if (CurrentFrame.bIsGlobalFrame)
|
|
|
+ {
|
|
|
+ FCurrentlyProcessedFrameScope FrameScope(*this, CurrentParentFrame, CurrentFrame);
|
|
|
+
|
|
|
+ const UEzAbility* CurrentAbility = CurrentFrame.Ability;
|
|
|
+
|
|
|
+ // Start evaluators
|
|
|
+ for (int32 EvalIndex = CurrentAbility->EvaluatorsBegin; EvalIndex < (CurrentAbility->EvaluatorsBegin + CurrentAbility->EvaluatorsNum); EvalIndex++)
|
|
|
+ {
|
|
|
+ const FEzAbilityEvaluator& Eval = CurrentAbility->Nodes[EvalIndex].Get<const FEzAbilityEvaluator>();
|
|
|
+ const FEzAbilityDataView EvalInstanceView = GetDataView(CurrentParentFrame, CurrentFrame, Eval.InstanceDataHandle);
|
|
|
+ FNodeInstanceDataScope DataScope(*this, Eval.InstanceDataHandle, EvalInstanceView);
|
|
|
+
|
|
|
+ // Copy bound properties.
|
|
|
+ if (Eval.BindingsBatch.IsValid())
|
|
|
+ {
|
|
|
+ //CopyBatchOnActiveInstances(CurrentParentFrame, CurrentFrame, EvalInstanceView, Eval.BindingsBatch);
|
|
|
+ }
|
|
|
+ EZ_ABILITY_LOG(Verbose, TEXT(" Start: '%s'"), *Eval.Name.ToString());
|
|
|
+ {
|
|
|
+ QUICK_SCOPE_CYCLE_COUNTER(EzAbility_Eval_TreeStart);
|
|
|
+ // Eval.TreeStart(*this);
|
|
|
+ //
|
|
|
+ // EZ_ABILITY_TRACE_EVALUATOR_EVENT(EvalIndex, EvalInstanceView, EEzAbilityTraceEventType::OnTreeStarted);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Start Global tasks
|
|
|
+ // Even if we call Enter/ExitState() on global tasks, they do not enter any specific state.
|
|
|
+ const FEzAbilityTransitionResult Transition = {}; // Empty transition
|
|
|
+
|
|
|
+ for (int32 TaskIndex = CurrentAbility->GlobalTasksBegin; TaskIndex < (CurrentAbility->GlobalTasksBegin + CurrentAbility->GlobalTasksNum); TaskIndex++)
|
|
|
+ {
|
|
|
+ const FEzAbilityTask& Task = CurrentAbility->Nodes[TaskIndex].Get<const FEzAbilityTask>();
|
|
|
+ const FEzAbilityDataView TaskInstanceView = GetDataView(CurrentParentFrame, CurrentFrame, Task.InstanceDataHandle);
|
|
|
+ FNodeInstanceDataScope DataScope(*this, Task.InstanceDataHandle, TaskInstanceView);
|
|
|
+
|
|
|
+ // Copy bound properties.
|
|
|
+ if (Task.BindingsBatch.IsValid())
|
|
|
+ {
|
|
|
+ //CopyBatchOnActiveInstances(CurrentParentFrame, CurrentFrame, TaskInstanceView, Task.BindingsBatch);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Ignore disabled task
|
|
|
+ if (Task.bTaskEnabled == false)
|
|
|
+ {
|
|
|
+ EZ_ABILITY_LOG(VeryVerbose, TEXT("%*sSkipped 'EnterState' for disabled Task: '%s'"), UE::EzAbility::DebugIndentSize, TEXT(""), *Task.Name.ToString());
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ EZ_ABILITY_LOG(Verbose, TEXT(" Start: '%s'"), *Task.Name.ToString());
|
|
|
+ {
|
|
|
+ QUICK_SCOPE_CYCLE_COUNTER(EzAbility_Task_TreeStart);
|
|
|
+ // const EAbilityRunStatus TaskStatus = Task.EnterState(*this, Transition);
|
|
|
+ //
|
|
|
+ // EZ_ABILITY_TRACE_TASK_EVENT(TaskIndex, TaskInstanceView, EEzAbilityTraceEventType::OnEntered, TaskStatus);
|
|
|
+ //
|
|
|
+ // if (TaskStatus != EAbilityRunStatus::Running)
|
|
|
+ // {
|
|
|
+ // OutLastInitializedTaskIndex = FEzAbilityIndex16(TaskIndex);
|
|
|
+ // Result = TaskStatus;
|
|
|
+ // break;
|
|
|
+ // }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return Result;
|
|
|
+}
|
|
|
+
|
|
|
FEzAbilityContext::FCurrentlyProcessedFrameScope::FCurrentlyProcessedFrameScope(FEzAbilityContext& InContext, const FEzAbilityExecutionFrame* CurrentParentFrame, const FEzAbilityExecutionFrame& CurrentFrame)
|
|
|
: Context(InContext)
|
|
|
{
|