// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "Containers/ArrayView.h" #include "Misc/NotNull.h" #include "StateTreeTypes.h" #define UE_API STATETREEMODULE_API class UStateTree; struct FStateTreeExecutionFrame; namespace UE::StateTree { /** A unique ID for FStateTreeExecutionFrame. */ struct FActiveFrameID { private: static constexpr uint32 InvalidValue = 0; public: UE_API static const FActiveFrameID Invalid; explicit FActiveFrameID() = default; explicit FActiveFrameID(uint32 NewID) : Value(NewID) { check(NewID != InvalidValue); } [[nodiscard]] bool operator==(const FActiveFrameID&) const = default; [[nodiscard]] bool operator!=(const FActiveFrameID&) const = default; [[nodiscard]] bool IsValid() const { return Value != InvalidValue; } private: uint32 Value = InvalidValue; }; /** A unique ID for FStateTreeActiveStates state. */ struct FActiveStateID { private: static constexpr uint32 InvalidValue = 0; public: UE_API static const FActiveStateID Invalid; explicit FActiveStateID() = default; explicit FActiveStateID(uint32 NewID) : Value(NewID) { check(NewID != InvalidValue); } [[nodiscard]] bool operator==(const FActiveStateID&) const = default; [[nodiscard]] bool operator!=(const FActiveStateID&) const = default; [[nodiscard]] bool IsValid() const { return Value != InvalidValue; } private: uint32 Value = InvalidValue; }; /** A state entry in the state path. */ struct FActiveState { FActiveState() = default; inline explicit FActiveState(FActiveFrameID InFrameID, FActiveStateID InStateID, FStateTreeStateHandle InHandle); [[nodiscard]] bool operator==(const FActiveState&) const = default; [[nodiscard]] bool operator!=(const FActiveState&) const = default; [[nodiscard]] bool IsValid() const { return StateHandle.IsValid(); } [[nodiscard]] FActiveFrameID GetFrameID() const { return FrameID; } [[nodiscard]] FActiveStateID GetStateID() const { return StateID; } [[nodiscard]] FStateTreeStateHandle GetStateHandle() const { return StateHandle; } private: /** The unique ID of the state for this instance. */ FActiveFrameID FrameID; /** The unique ID of the state for this instance. */ FActiveStateID StateID; /** The index of the state handle the state tree asset. */ FStateTreeStateHandle StateHandle; }; /** * Describe the state list used to get to a specific state. * Since a state can be a subtree and can be linked to other states, the path to activate the subtree can be different. * A state can enter, then exit, then reenter. It is considered the same state path but not the same unique state path. * For a tree like * RootA(0) * StateA(1) * StateB(2) * LinkedStateA(3) * StateC(4) * LinkedStateA(5) * SubTreeA(6) * StateD(7) * The path to get to StateD can be RootA.StateB.LinkedStateA.SubTreeA.StateD(0.2.3.6.7) */ class FActiveStatePath { public: explicit FActiveStatePath() = default; UE_API explicit FActiveStatePath(TNotNull InStateTree, const TArrayView InElements); UE_API explicit FActiveStatePath(TNotNull InStateTree, TArray InElements); /** @return the number of elements in the path. */ [[nodiscard]] int32 Num() const { return States.Num(); } /** @return a view of the states in the path. */ [[nodiscard]] const TArrayView GetView() const { return States; } /** @return true if both paths match exactly. */ [[nodiscard]] UE_API static bool Matches(const TArrayView& A, const TArrayView& B); /** @return true if both paths match exactly. */ [[nodiscard]] UE_API bool Matches(const FActiveStatePath& Other) const; /** @return true if the last element in the path matches. */ [[nodiscard]] UE_API static bool Matches(const TArrayView& Path, FActiveState Other); /** @return true if the last element in the path matches. */ [[nodiscard]] UE_API bool Matches(FActiveState Other) const; /** @return true if the last element in the path matches. */ [[nodiscard]] UE_API static bool Matches(const TArrayView& Path, FActiveStateID Other); /** @return true if the last element in the path matches. */ [[nodiscard]] UE_API bool Matches(FActiveStateID Other) const; /** @return the elements that are in both paths. */ [[nodiscard]] UE_API static const TArrayView Intersect(const TArrayView& A, const TArrayView& B); /** @return the path where the 2 paths intersect. */ [[nodiscard]] UE_API const TArrayView Intersect(const FActiveStatePath& Other) const; /** @return true if the path starts with and contains the other path. */ [[nodiscard]]UE_API static bool StartsWith(const TArrayView& Path, const TArrayView& B); /** @return true if this path starts with and contains the other path. */ [[nodiscard]] UE_API bool StartsWith(const FActiveStatePath& Other) const; /** @return true if the path contains anywhere the other element. */ [[nodiscard]] UE_API static bool Contains(const TArrayView& Path, FActiveState Other); /** @return true if this path contains anywhere the other element. */ [[nodiscard]] UE_API bool Contains(FActiveState Other) const; /** @return true if the path contains anywhere the other element. */ [[nodiscard]] UE_API static bool Contains(const TArrayView& Path, FActiveStateID Other); /** @return true if this path contains anywhere the other element. */ [[nodiscard]] UE_API bool Contains(FActiveStateID Other) const; /** @return true the index of element inside the path. */ [[nodiscard]] UE_API static int32 IndexOf(const TArrayView& Path, FActiveState Other); /** @return true the index of element inside the path. */ [[nodiscard]]UE_API int32 IndexOf(FActiveState Other) const; /** @return true the index of element inside the path. */ [[nodiscard]] UE_API static int32 IndexOf(const TArrayView& Path, FActiveStateID Other); /** @return true the index of element inside the path. */ [[nodiscard]] UE_API int32 IndexOf(FActiveStateID Other) const; /** @return debugging information about the path. */ [[nodiscard]] UE_API static TValueOrError Describe(TNotNull StateTree, const TArrayView& Path); /** @return debugging information about the path. */ [[nodiscard]] UE_API TValueOrError Describe() const; private: TWeakObjectPtr StateTree; TArray States; }; // Inlined functions FActiveState::FActiveState(FActiveFrameID InFrameID, FActiveStateID InStateID, FStateTreeStateHandle InHandle) : FrameID(InFrameID) , StateID(InStateID) , StateHandle(InHandle) { } } #undef UE_API