2021-09-28 13:33:17 -04:00
|
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
|
|
|
|
#include "StateTreeState.h"
|
|
|
|
|
#include "StateTree.h"
|
|
|
|
|
#include "StateTreeConditionBase.h"
|
2022-02-03 09:13:49 -05:00
|
|
|
#include "StateTreeEvaluatorBase.h"
|
|
|
|
|
#include "StateTreeTaskBase.h"
|
2021-09-28 13:33:17 -04:00
|
|
|
#include "StateTreeDelegates.h"
|
|
|
|
|
#include "CoreMinimal.h"
|
|
|
|
|
#include "UObject/Field.h"
|
|
|
|
|
|
2021-10-21 04:08:20 -04:00
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// FStateTreeStateLink
|
|
|
|
|
|
2021-09-28 13:33:17 -04:00
|
|
|
void FStateTreeStateLink::Set(const EStateTreeTransitionType InType, const UStateTreeState* InState)
|
|
|
|
|
{
|
|
|
|
|
Type = InType;
|
|
|
|
|
if (Type == EStateTreeTransitionType::GotoState)
|
|
|
|
|
{
|
|
|
|
|
check(InState);
|
|
|
|
|
Name = InState->Name;
|
|
|
|
|
ID = InState->ID;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-10-21 04:08:20 -04:00
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// FStateTreeTransition
|
|
|
|
|
|
|
|
|
|
FStateTreeTransition::FStateTreeTransition(const EStateTreeTransitionEvent InEvent, const EStateTreeTransitionType InType, const UStateTreeState* InState)
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
|
|
|
|
Event = InEvent;
|
|
|
|
|
State.Set(InType, InState);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-10-21 04:08:20 -04:00
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// UStateTreeState
|
|
|
|
|
|
2021-09-28 13:33:17 -04:00
|
|
|
UStateTreeState::UStateTreeState(const FObjectInitializer& ObjectInitializer)
|
|
|
|
|
: Super(ObjectInitializer)
|
|
|
|
|
, ID(FGuid::NewGuid())
|
|
|
|
|
, Parent(nullptr)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if WITH_EDITOR
|
|
|
|
|
void UStateTreeState::PostEditChangeChainProperty(FPropertyChangedChainEvent& PropertyChangedEvent)
|
|
|
|
|
{
|
|
|
|
|
Super::PostEditChangeChainProperty(PropertyChangedEvent);
|
|
|
|
|
|
|
|
|
|
FProperty* Property = PropertyChangedEvent.Property;
|
|
|
|
|
FProperty* MemberProperty = nullptr;
|
|
|
|
|
if (PropertyChangedEvent.PropertyChain.GetActiveMemberNode())
|
|
|
|
|
{
|
|
|
|
|
MemberProperty = PropertyChangedEvent.PropertyChain.GetActiveMemberNode()->GetValue();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Property)
|
|
|
|
|
{
|
2022-04-05 03:20:57 -04:00
|
|
|
if (Property->GetOwnerClass() == UStateTreeState::StaticClass()
|
|
|
|
|
&& Property->GetFName() == GET_MEMBER_NAME_CHECKED(UStateTreeState, Name))
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
|
|
|
|
UStateTree* StateTree = GetTypedOuter<UStateTree>();
|
|
|
|
|
if (ensure(StateTree))
|
|
|
|
|
{
|
|
|
|
|
UE::StateTree::Delegates::OnIdentifierChanged.Broadcast(*StateTree);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-05 03:20:57 -04:00
|
|
|
if (Property->GetOwnerClass() == UStateTreeState::StaticClass()
|
|
|
|
|
&& Property->GetFName() == GET_MEMBER_NAME_CHECKED(UStateTreeState, Type))
|
|
|
|
|
{
|
|
|
|
|
if (Type == EStateTreeStateType::Group || Type == EStateTreeStateType::Linked)
|
|
|
|
|
{
|
|
|
|
|
// Remove any tasks and evaluators.
|
|
|
|
|
Tasks.Reset();
|
|
|
|
|
Evaluators.Reset();
|
|
|
|
|
}
|
|
|
|
|
if (Type != EStateTreeStateType::Linked)
|
|
|
|
|
{
|
|
|
|
|
LinkedState = FStateTreeStateLink();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-21 04:08:20 -04:00
|
|
|
if (MemberProperty)
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
|
|
|
|
// Ensure unique ID on duplicated items.
|
2021-10-21 04:08:20 -04:00
|
|
|
if (PropertyChangedEvent.ChangeType == EPropertyChangeType::Duplicate)
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
2021-10-21 04:08:20 -04:00
|
|
|
if (MemberProperty->GetFName() == GET_MEMBER_NAME_CHECKED(UStateTreeState, Evaluators))
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
2021-10-21 04:08:20 -04:00
|
|
|
const int32 ArrayIndex = PropertyChangedEvent.GetArrayIndex(MemberProperty->GetFName().ToString());
|
|
|
|
|
if (Evaluators.IsValidIndex(ArrayIndex))
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
2022-02-03 09:13:49 -05:00
|
|
|
if (FStateTreeEvaluatorBase* Eval = Evaluators[ArrayIndex].Node.GetMutablePtr<FStateTreeEvaluatorBase>())
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
2021-10-21 04:08:20 -04:00
|
|
|
Eval->Name = FName(Eval->Name.ToString() + TEXT(" Duplicate"));
|
2021-09-28 13:33:17 -04:00
|
|
|
}
|
2021-11-12 05:48:11 -05:00
|
|
|
Evaluators[ArrayIndex].ID = FGuid::NewGuid();
|
2021-09-28 13:33:17 -04:00
|
|
|
}
|
|
|
|
|
}
|
2021-10-21 04:08:20 -04:00
|
|
|
if (MemberProperty->GetFName() == GET_MEMBER_NAME_CHECKED(UStateTreeState, Tasks))
|
|
|
|
|
{
|
|
|
|
|
const int32 ArrayIndex = PropertyChangedEvent.GetArrayIndex(MemberProperty->GetFName().ToString());
|
|
|
|
|
if (Tasks.IsValidIndex(ArrayIndex))
|
|
|
|
|
{
|
2022-02-03 09:13:49 -05:00
|
|
|
if (FStateTreeTaskBase* Task = Tasks[ArrayIndex].Node.GetMutablePtr<FStateTreeTaskBase>())
|
2021-10-21 04:08:20 -04:00
|
|
|
{
|
|
|
|
|
Task->Name = FName(Task->Name.ToString() + TEXT(" Duplicate"));
|
|
|
|
|
}
|
2021-11-12 05:48:11 -05:00
|
|
|
Tasks[ArrayIndex].ID = FGuid::NewGuid();
|
2021-10-21 04:08:20 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (MemberProperty->GetFName() == GET_MEMBER_NAME_CHECKED(UStateTreeState, EnterConditions))
|
|
|
|
|
{
|
|
|
|
|
const int32 ArrayIndex = PropertyChangedEvent.GetArrayIndex(MemberProperty->GetFName().ToString());
|
|
|
|
|
if (EnterConditions.IsValidIndex(ArrayIndex))
|
|
|
|
|
{
|
2021-11-12 05:48:11 -05:00
|
|
|
EnterConditions[ArrayIndex].ID = FGuid::NewGuid();
|
2021-10-21 04:08:20 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// TODO: Transition conditions.
|
2021-09-28 13:33:17 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
UStateTreeState* UStateTreeState::GetNextSiblingState() const
|
|
|
|
|
{
|
|
|
|
|
if (!Parent)
|
|
|
|
|
{
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
for (int32 ChildIdx = 0; ChildIdx < Parent->Children.Num(); ChildIdx++)
|
|
|
|
|
{
|
|
|
|
|
if (Parent->Children[ChildIdx] == this)
|
|
|
|
|
{
|
|
|
|
|
const int NextIdx = ChildIdx + 1;
|
|
|
|
|
if (NextIdx < Parent->Children.Num())
|
|
|
|
|
{
|
|
|
|
|
return Parent->Children[NextIdx];
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|