Files
2025-05-18 13:04:45 +08:00

219 lines
6.9 KiB
C++

// 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<const UStateTree*> InStateTree, const TArrayView<const FActiveState> InElements);
UE_API explicit FActiveStatePath(TNotNull<const UStateTree*> InStateTree, TArray<FActiveState> 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<const FActiveState> GetView() const
{
return States;
}
/** @return true if both paths match exactly. */
[[nodiscard]] UE_API static bool Matches(const TArrayView<const FActiveState>& A, const TArrayView<const FActiveState>& 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<const FActiveState>& 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<const FActiveState>& 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<const FActiveState> Intersect(const TArrayView<const FActiveState>& A, const TArrayView<const FActiveState>& B);
/** @return the path where the 2 paths intersect. */
[[nodiscard]] UE_API const TArrayView<const FActiveState> 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<const FActiveState>& Path, const TArrayView<const FActiveState>& 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<const FActiveState>& 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<const FActiveState>& 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<const FActiveState>& 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<const FActiveState>& 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<FString, void> Describe(TNotNull<const UStateTree*> StateTree, const TArrayView<const FActiveState>& Path);
/** @return debugging information about the path. */
[[nodiscard]] UE_API TValueOrError<FString, void> Describe() const;
private:
TWeakObjectPtr<const UStateTree> StateTree;
TArray<FActiveState> States;
};
// Inlined functions
FActiveState::FActiveState(FActiveFrameID InFrameID, FActiveStateID InStateID, FStateTreeStateHandle InHandle)
: FrameID(InFrameID)
, StateID(InStateID)
, StateHandle(InHandle)
{
}
}
#undef UE_API