2021-09-28 13:33:00 -04:00
|
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include "StateTreeEvaluatorBase.h"
|
|
|
|
|
#include "StateTreeTaskBase.h"
|
|
|
|
|
#include "Misc/Guid.h"
|
|
|
|
|
#include "InstancedStruct.h"
|
|
|
|
|
#include "StateTreeState.generated.h"
|
|
|
|
|
|
|
|
|
|
class UStateTreeState;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Editor representation of a link to another state in StateTree
|
|
|
|
|
*/
|
|
|
|
|
USTRUCT()
|
|
|
|
|
struct STATETREEEDITORMODULE_API FStateTreeStateLink
|
|
|
|
|
{
|
|
|
|
|
GENERATED_BODY()
|
|
|
|
|
public:
|
|
|
|
|
FStateTreeStateLink() : Type(EStateTreeTransitionType::GotoState) {}
|
|
|
|
|
FStateTreeStateLink(EStateTreeTransitionType InType) : Type(InType) {}
|
|
|
|
|
|
|
|
|
|
void Set(const EStateTreeTransitionType InType, const UStateTreeState* InState = nullptr);
|
|
|
|
|
|
|
|
|
|
bool IsValid() const { return ID.IsValid(); }
|
|
|
|
|
|
|
|
|
|
UPROPERTY(EditDefaultsOnly, Category = Link)
|
|
|
|
|
FName Name;
|
|
|
|
|
|
|
|
|
|
UPROPERTY(EditDefaultsOnly, Category = Link)
|
|
|
|
|
FGuid ID;
|
|
|
|
|
|
2021-11-12 05:49:31 -05:00
|
|
|
UPROPERTY(EditDefaultsOnly, Category = Link)
|
2021-11-24 04:26:29 -05:00
|
|
|
EStateTreeTransitionType Type = EStateTreeTransitionType::GotoState;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Base for Evaluator, Task and Condition items.
|
|
|
|
|
*/
|
|
|
|
|
USTRUCT()
|
|
|
|
|
struct STATETREEEDITORMODULE_API FStateTreeItem
|
|
|
|
|
{
|
|
|
|
|
GENERATED_BODY()
|
|
|
|
|
|
|
|
|
|
void Reset()
|
|
|
|
|
{
|
|
|
|
|
Item.Reset();
|
|
|
|
|
Instance.Reset();
|
|
|
|
|
InstanceObject = nullptr;
|
|
|
|
|
ID = FGuid();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UPROPERTY(EditDefaultsOnly, Category = Item)
|
|
|
|
|
FInstancedStruct Item;
|
|
|
|
|
|
|
|
|
|
UPROPERTY(EditDefaultsOnly, Category = Item)
|
|
|
|
|
FInstancedStruct Instance;
|
|
|
|
|
|
|
|
|
|
UPROPERTY(EditDefaultsOnly, Instanced, Category = Item)
|
|
|
|
|
UObject* InstanceObject = nullptr;
|
|
|
|
|
|
|
|
|
|
UPROPERTY(EditDefaultsOnly, Category = Item)
|
|
|
|
|
FGuid ID;
|
2021-09-28 13:33:00 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Helper struct for Evaluator details customization (i.e. show summary when collapsed)
|
|
|
|
|
*/
|
|
|
|
|
USTRUCT()
|
2021-11-24 04:26:29 -05:00
|
|
|
struct STATETREEEDITORMODULE_API FStateTreeEvaluatorItem : public FStateTreeItem
|
2021-09-28 13:33:00 -04:00
|
|
|
{
|
|
|
|
|
GENERATED_BODY()
|
|
|
|
|
|
2021-11-12 05:49:31 -05:00
|
|
|
FName GetName() const
|
|
|
|
|
{
|
|
|
|
|
if (const FStateTreeEvaluatorBase* Eval = Item.GetPtr<FStateTreeEvaluatorBase>())
|
|
|
|
|
{
|
|
|
|
|
return Eval->Name;
|
|
|
|
|
}
|
|
|
|
|
return FName();
|
|
|
|
|
}
|
2021-09-28 13:33:00 -04:00
|
|
|
};
|
|
|
|
|
|
2021-11-12 05:49:31 -05:00
|
|
|
template <typename T>
|
2021-11-15 10:58:48 -05:00
|
|
|
struct TStateTreeEvaluatorItem : public FStateTreeEvaluatorItem
|
2021-11-12 05:49:31 -05:00
|
|
|
{
|
|
|
|
|
typedef T ItemType;
|
|
|
|
|
FORCEINLINE T& GetItem() { return Item.template GetMutable<T>(); }
|
|
|
|
|
FORCEINLINE typename T::InstanceDataType& GetInstance() { return Instance.template GetMutable<typename T::InstanceDataType>(); }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2021-09-28 13:33:00 -04:00
|
|
|
/**
|
|
|
|
|
* Helper struct for Task details customization (i.e. show summary when collapsed)
|
|
|
|
|
*/
|
|
|
|
|
USTRUCT()
|
2021-11-24 04:26:29 -05:00
|
|
|
struct STATETREEEDITORMODULE_API FStateTreeTaskItem : public FStateTreeItem
|
2021-09-28 13:33:00 -04:00
|
|
|
{
|
|
|
|
|
GENERATED_BODY()
|
|
|
|
|
|
2021-11-12 05:49:31 -05:00
|
|
|
FName GetName() const
|
|
|
|
|
{
|
|
|
|
|
if (const FStateTreeTaskBase* Task = Item.GetPtr<FStateTreeTaskBase>())
|
|
|
|
|
{
|
|
|
|
|
return Task->Name;
|
|
|
|
|
}
|
|
|
|
|
return FName();
|
|
|
|
|
}
|
2021-09-28 13:33:00 -04:00
|
|
|
};
|
|
|
|
|
|
2021-11-12 05:49:31 -05:00
|
|
|
template <typename T>
|
2021-11-15 10:58:48 -05:00
|
|
|
struct TStateTreeTaskItem : public FStateTreeTaskItem
|
2021-11-12 05:49:31 -05:00
|
|
|
{
|
|
|
|
|
typedef T ItemType;
|
|
|
|
|
FORCEINLINE T& GetItem() { return Item.template GetMutable<T>(); }
|
|
|
|
|
FORCEINLINE typename T::InstanceDataType& GetInstance() { return Instance.template GetMutable<typename T::InstanceDataType>(); }
|
|
|
|
|
};
|
2021-09-28 13:33:00 -04:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Helper struct for Condition details customization (i.e. show summary when collapsed)
|
|
|
|
|
*/
|
|
|
|
|
USTRUCT()
|
2021-11-24 04:26:29 -05:00
|
|
|
struct STATETREEEDITORMODULE_API FStateTreeConditionItem : public FStateTreeItem
|
2021-09-28 13:33:00 -04:00
|
|
|
{
|
|
|
|
|
GENERATED_BODY()
|
2021-11-12 05:49:31 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
2021-11-15 10:58:48 -05:00
|
|
|
struct TStateTreeConditionItem : public FStateTreeConditionItem
|
2021-11-12 05:49:31 -05:00
|
|
|
{
|
|
|
|
|
typedef T ItemType;
|
|
|
|
|
FORCEINLINE T& GetItem() { return Item.template GetMutable<T>(); }
|
|
|
|
|
FORCEINLINE typename T::InstanceDataType& GetInstance() { return Instance.template GetMutable<typename T::InstanceDataType>(); }
|
2021-09-28 13:33:00 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Editor representation of a transition in StateTree
|
|
|
|
|
*/
|
|
|
|
|
USTRUCT()
|
2021-10-21 04:12:07 -04:00
|
|
|
struct STATETREEEDITORMODULE_API FStateTreeTransition
|
2021-09-28 13:33:00 -04:00
|
|
|
{
|
|
|
|
|
GENERATED_BODY()
|
|
|
|
|
|
2021-10-21 04:12:07 -04:00
|
|
|
FStateTreeTransition() = default;
|
|
|
|
|
FStateTreeTransition(const EStateTreeTransitionEvent InEvent, const EStateTreeTransitionType InType, const UStateTreeState* InState = nullptr);
|
2021-09-28 13:33:00 -04:00
|
|
|
|
|
|
|
|
template<typename T, typename... TArgs>
|
2021-11-12 05:49:31 -05:00
|
|
|
TStateTreeConditionItem<T>& AddCondition(TArgs&&... InArgs)
|
2021-09-28 13:33:00 -04:00
|
|
|
{
|
|
|
|
|
FStateTreeConditionItem& CondItem = Conditions.AddDefaulted_GetRef();
|
2021-11-12 05:49:31 -05:00
|
|
|
CondItem.ID = FGuid::NewGuid();
|
|
|
|
|
CondItem.Item.InitializeAs<T>(Forward<TArgs>(InArgs)...);
|
|
|
|
|
T& Cond = CondItem.Item.GetMutable<T>();
|
|
|
|
|
if (const UScriptStruct* InstanceType = Cast<const UScriptStruct>(Cond.GetInstanceDataType()))
|
|
|
|
|
{
|
|
|
|
|
CondItem.Instance.InitializeAs(InstanceType);
|
|
|
|
|
}
|
|
|
|
|
return static_cast<TStateTreeConditionItem<T>&>(CondItem);
|
2021-09-28 13:33:00 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UPROPERTY(EditDefaultsOnly, Category = Transition)
|
2021-11-24 04:26:29 -05:00
|
|
|
EStateTreeTransitionEvent Event = EStateTreeTransitionEvent::OnCompleted;
|
2021-09-28 13:33:00 -04:00
|
|
|
|
|
|
|
|
UPROPERTY(EditDefaultsOnly, Category = Transition)
|
|
|
|
|
FStateTreeStateLink State;
|
|
|
|
|
|
|
|
|
|
// Gate delay in seconds.
|
|
|
|
|
UPROPERTY(EditDefaultsOnly, Category = Transition, meta = (UIMin = "0", ClampMin = "0", UIMax = "25", ClampMax = "25"))
|
|
|
|
|
float GateDelay = 0.0f;
|
|
|
|
|
|
2021-11-24 04:26:29 -05:00
|
|
|
UPROPERTY(EditDefaultsOnly, Category = Transition, meta = (BaseStruct = "StateTreeConditionBase", BaseClass = "StateTreeConditionBlueprintBase"))
|
2021-09-28 13:33:00 -04:00
|
|
|
TArray<FStateTreeConditionItem> Conditions;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Editor representation of a state in StateTree
|
|
|
|
|
*/
|
|
|
|
|
UCLASS(BlueprintType, EditInlineNew, CollapseCategories)
|
2021-10-21 04:12:07 -04:00
|
|
|
class STATETREEEDITORMODULE_API UStateTreeState : public UObject
|
2021-09-28 13:33:00 -04:00
|
|
|
{
|
|
|
|
|
GENERATED_BODY()
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
UStateTreeState(const FObjectInitializer& ObjectInitializer);
|
|
|
|
|
|
|
|
|
|
#if WITH_EDITOR
|
|
|
|
|
virtual void PostEditChangeChainProperty(FPropertyChangedChainEvent& PropertyChangedEvent) override;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
UStateTreeState* GetNextSiblingState() const;
|
|
|
|
|
|
|
|
|
|
// StateTree Builder API
|
|
|
|
|
|
|
|
|
|
/** Adds child state with specified name. */
|
|
|
|
|
UStateTreeState& AddChildState(const FName ChildName)
|
|
|
|
|
{
|
|
|
|
|
UStateTreeState* ChildState = NewObject<UStateTreeState>(this);
|
|
|
|
|
check(ChildState);
|
|
|
|
|
ChildState->Name = ChildName;
|
|
|
|
|
ChildState->Parent = this;
|
|
|
|
|
Children.Add(ChildState);
|
|
|
|
|
return *ChildState;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Adds enter condition of specified type.
|
|
|
|
|
* @return reference to the new condition.
|
|
|
|
|
*/
|
|
|
|
|
template<typename T, typename... TArgs>
|
2021-11-12 05:49:31 -05:00
|
|
|
TStateTreeConditionItem<T>& AddEnterCondition(TArgs&&... InArgs)
|
2021-09-28 13:33:00 -04:00
|
|
|
{
|
2021-10-21 04:12:07 -04:00
|
|
|
FStateTreeConditionItem& CondItem = EnterConditions.AddDefaulted_GetRef();
|
2021-11-12 05:49:31 -05:00
|
|
|
CondItem.ID = FGuid::NewGuid();
|
|
|
|
|
CondItem.Item.InitializeAs<T>(Forward<TArgs>(InArgs)...);
|
|
|
|
|
T& Cond = CondItem.Item.GetMutable<T>();
|
|
|
|
|
if (const UScriptStruct* InstanceType = Cast<const UScriptStruct>(Cond.GetInstanceDataType()))
|
|
|
|
|
{
|
|
|
|
|
CondItem.Instance.InitializeAs(InstanceType);
|
|
|
|
|
}
|
|
|
|
|
return static_cast<TStateTreeConditionItem<T>&>(CondItem);
|
2021-09-28 13:33:00 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Adds Task of specified type.
|
|
|
|
|
* @return reference to the new Task.
|
|
|
|
|
*/
|
|
|
|
|
template<typename T, typename... TArgs>
|
2021-11-12 05:49:31 -05:00
|
|
|
TStateTreeTaskItem<T>& AddTask(TArgs&&... InArgs)
|
2021-09-28 13:33:00 -04:00
|
|
|
{
|
2021-10-21 04:12:07 -04:00
|
|
|
FStateTreeTaskItem& TaskItem = Tasks.AddDefaulted_GetRef();
|
2021-11-12 05:49:31 -05:00
|
|
|
TaskItem.ID = FGuid::NewGuid();
|
|
|
|
|
TaskItem.Item.InitializeAs<T>(Forward<TArgs>(InArgs)...);
|
|
|
|
|
T& Task = TaskItem.Item.GetMutable<T>();
|
|
|
|
|
if (const UScriptStruct* InstanceType = Cast<const UScriptStruct>(Task.GetInstanceDataType()))
|
|
|
|
|
{
|
|
|
|
|
TaskItem.Instance.InitializeAs(InstanceType);
|
|
|
|
|
}
|
|
|
|
|
return static_cast<TStateTreeTaskItem<T>&>(TaskItem);
|
2021-09-28 13:33:00 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Adds Evaluator of specified type.
|
|
|
|
|
* @return reference to the new Evaluator.
|
|
|
|
|
*/
|
|
|
|
|
template<typename T, typename... TArgs>
|
2021-11-12 05:49:31 -05:00
|
|
|
TStateTreeEvaluatorItem<T>& AddEvaluator(TArgs&&... InArgs)
|
2021-09-28 13:33:00 -04:00
|
|
|
{
|
2021-10-21 04:12:07 -04:00
|
|
|
FStateTreeEvaluatorItem& EvalItem = Evaluators.AddDefaulted_GetRef();
|
2021-11-12 05:49:31 -05:00
|
|
|
EvalItem.ID = FGuid::NewGuid();
|
|
|
|
|
EvalItem.Item.InitializeAs<T>(Forward<TArgs>(InArgs)...);
|
|
|
|
|
T& Eval = EvalItem.Item.GetMutable<T>();
|
|
|
|
|
if (const UScriptStruct* InstanceType = Cast<const UScriptStruct>(Eval.GetInstanceDataType()))
|
|
|
|
|
{
|
|
|
|
|
EvalItem.Instance.InitializeAs(InstanceType);
|
|
|
|
|
}
|
|
|
|
|
return static_cast<TStateTreeEvaluatorItem<T>&>(EvalItem);
|
2021-09-28 13:33:00 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Adds Transition.
|
|
|
|
|
* @return reference to the new Transition.
|
|
|
|
|
*/
|
2021-10-21 04:12:07 -04:00
|
|
|
FStateTreeTransition& AddTransition(const EStateTreeTransitionEvent InEvent, const EStateTreeTransitionType InType, const UStateTreeState* InState = nullptr)
|
2021-09-28 13:33:00 -04:00
|
|
|
{
|
2021-10-21 04:12:07 -04:00
|
|
|
return Transitions.Emplace_GetRef(InEvent, InType, InState);
|
2021-09-28 13:33:00 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ~StateTree Builder API
|
|
|
|
|
|
2021-11-12 05:49:31 -05:00
|
|
|
UPROPERTY(EditDefaultsOnly, Category = "State")
|
2021-09-28 13:33:00 -04:00
|
|
|
FName Name;
|
|
|
|
|
|
|
|
|
|
UPROPERTY()
|
|
|
|
|
FGuid ID;
|
|
|
|
|
|
2021-11-24 04:26:29 -05:00
|
|
|
UPROPERTY(EditDefaultsOnly, Category = "Enter Conditions", meta = (BaseStruct = "StateTreeConditionBase", BaseClass = "StateTreeConditionBlueprintBase"))
|
2021-10-21 04:12:07 -04:00
|
|
|
TArray<FStateTreeConditionItem> EnterConditions;
|
2021-09-28 13:33:00 -04:00
|
|
|
|
2021-11-24 04:26:29 -05:00
|
|
|
UPROPERTY(EditDefaultsOnly, Category = "Evaluators", meta = (BaseStruct = "StateTreeEvaluatorBase", BaseClass = "StateTreeEvaluatorBlueprintBase"))
|
2021-10-21 04:12:07 -04:00
|
|
|
TArray<FStateTreeEvaluatorItem> Evaluators;
|
2021-09-28 13:33:00 -04:00
|
|
|
|
2021-11-24 04:26:29 -05:00
|
|
|
UPROPERTY(EditDefaultsOnly, Category = "Tasks", meta = (BaseStruct = "StateTreeTaskBase", BaseClass = "StateTreeTaskBlueprintBase"))
|
2021-10-21 04:12:07 -04:00
|
|
|
TArray<FStateTreeTaskItem> Tasks;
|
2021-09-28 13:33:00 -04:00
|
|
|
|
2021-12-08 03:32:02 -05:00
|
|
|
// Single item used when schema calls for single task per state.
|
|
|
|
|
UPROPERTY(EditDefaultsOnly, Category = "Task", meta = (BaseStruct = "StateTreeTaskBase", BaseClass = "StateTreeTaskBlueprintBase"))
|
|
|
|
|
FStateTreeTaskItem SingleTask;
|
|
|
|
|
|
2021-09-28 13:33:00 -04:00
|
|
|
UPROPERTY(EditDefaultsOnly, Category = "Transitions")
|
|
|
|
|
TArray<FStateTreeTransition> Transitions;
|
|
|
|
|
|
|
|
|
|
UPROPERTY()
|
|
|
|
|
TArray<UStateTreeState*> Children;
|
|
|
|
|
|
|
|
|
|
UPROPERTY()
|
|
|
|
|
bool bExpanded;
|
|
|
|
|
|
|
|
|
|
UPROPERTY()
|
|
|
|
|
UStateTreeState* Parent;
|
|
|
|
|
|
|
|
|
|
};
|