Files
UnrealEngine/Engine/Source/Runtime/MassEntity/Public/MassExecutionContext.h
2025-05-18 13:04:45 +08:00

677 lines
25 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "MassEntityHandle.h"
#include "MassEntityTypes.h"
#if UE_ENABLE_INCLUDE_ORDER_DEPRECATED_IN_5_6
#include "MassExternalSubsystemTraits.h"
#include "MassEntityQuery.h"
#endif // UE_ENABLE_INCLUDE_ORDER_DEPRECATED_IN_5_6
#include "MassArchetypeTypes.h"
#include "MassSubsystemAccess.h"
#include "MassProcessor.h"
#define CHECK_IF_VALID(View, Type) \
checkf(View \
, TEXT("Requested fragment type not bound, type %s. Make sure it has been listed as required."), *GetNameSafe(Type))
#define CHECK_IF_READWRITE(View) \
checkf(View == nullptr || View->Requirement.AccessMode == EMassFragmentAccess::ReadWrite \
, TEXT("Requested fragment type not bound for writing, type %s. Make sure it has been listed as required in ReadWrite mode.") \
, View ? *GetNameSafe(View->Requirement.StructType) : TEXT("[Not found]"))
struct FMassEntityQuery;
struct FMassExecutionContext
{
private:
template< typename ViewType >
struct TFragmentView
{
FMassFragmentRequirementDescription Requirement;
ViewType FragmentView;
TFragmentView() {}
explicit TFragmentView(const FMassFragmentRequirementDescription& InRequirement) : Requirement(InRequirement) {}
bool operator==(const UScriptStruct* FragmentType) const { return Requirement.StructType == FragmentType; }
};
using FFragmentView = TFragmentView<TArrayView<FMassFragment>>;
TArray<FFragmentView, TInlineAllocator<8>> FragmentViews;
using FChunkFragmentView = TFragmentView<FStructView>;
TArray<FChunkFragmentView, TInlineAllocator<4>> ChunkFragmentViews;
using FConstSharedFragmentView = TFragmentView<FConstStructView>;
TArray<FConstSharedFragmentView, TInlineAllocator<4>> ConstSharedFragmentViews;
using FSharedFragmentView = TFragmentView<FStructView>;
TArray<FSharedFragmentView, TInlineAllocator<4>> SharedFragmentViews;
FMassSubsystemAccess SubsystemAccess;
// mz@todo make this shared ptr thread-safe and never auto-flush in MT environment.
TSharedPtr<FMassCommandBuffer> DeferredCommandBuffer;
TArrayView<FMassEntityHandle> EntityListView;
/** If set this indicates the exact archetype and its chunks to be processed.
* @todo this data should live somewhere else, preferably be just a parameter to Query.ForEachEntityChunk function */
FMassArchetypeEntityCollection EntityCollection;
/** @todo rename to "payload" */
FInstancedStruct AuxData;
float DeltaTimeSeconds = 0.0f;
int32 ChunkSerialModificationNumber = -1;
FMassArchetypeCompositionDescriptor CurrentArchetypeCompositionDescriptor;
#if WITH_MASSENTITY_DEBUG
FColor DebugColor;
#endif // WITH_MASSENTITY_DEBUG
TSharedRef<FMassEntityManager> EntityManager;
struct FQueryTransientRuntime
{
TNotNull<FMassEntityQuery*> Query;
FMassExternalSubsystemBitSet ConstSubsystemsBitSet;
FMassExternalSubsystemBitSet MutableSubsystemsBitSet;
#if WITH_MASSENTITY_DEBUG
/** MaxBreakFragmentCount needs to be bigger than the greatest number of fragments a query has a write requirement for to that can have a breakpoint set */
static constexpr uint32 MaxFragmentBreakpointCount = 8;
TStaticArray<const UScriptStruct*, MaxFragmentBreakpointCount> FragmentTypesToBreakOn;
bool bCheckProcessorBreaks = false;
int32 BreakFragmentsCount = 0;
#endif // WITH_MASSENTITY_DEBUG
/** Serial number to ensure iterator consistency (subsequent calls to CreateEntityIterator should not pass equivelncy test) */
uint32 IteratorSerialNumber = 0;
/** Helper function to create an empty instance with a valid Query ptr */
static FQueryTransientRuntime& GetDummyInstance();
};
/** We usually expect the queries to go only a single layer deep, so 2 elements here should suffice most of the time */
TArray<FQueryTransientRuntime, TInlineAllocator<2>> QueriesStack;
/** Track the serial number for FEntityIterator creation */
uint32 IteratorSerialNumberGenerator = 0;
#if WITH_MASSENTITY_DEBUG
FString DebugExecutionDescription;
/** Currently executing processor, used for debugger breakpoint checking */
// js@todo make this more generic
TWeakObjectPtr<UMassProcessor> DebugProcessor;
#endif // WITH_MASSENTITY_DEBUG
/** Used to control when the context is allowed to flush commands collected in DeferredCommandBuffer. This mechanism
* is mainly utilized to avoid numerous small flushes in favor of fewer larger ones. */
bool bFlushDeferredCommands = true;
TArrayView<FFragmentView> GetMutableRequirements() { return FragmentViews; }
TArrayView<FChunkFragmentView> GetMutableChunkRequirements() { return ChunkFragmentViews; }
TArrayView<FConstSharedFragmentView> GetMutableConstSharedRequirements() { return ConstSharedFragmentViews; }
TArrayView<FSharedFragmentView> GetMutableSharedRequirements() { return SharedFragmentViews; }
void GetSubsystemRequirementBits(FMassExternalSubsystemBitSet& OutConstSubsystemsBitSet, FMassExternalSubsystemBitSet& OutMutableSubsystemsBitSet)
{
SubsystemAccess.GetSubsystemRequirementBits(OutConstSubsystemsBitSet, OutMutableSubsystemsBitSet);
}
void SetSubsystemRequirementBits(const FMassExternalSubsystemBitSet& InConstSubsystemsBitSet, const FMassExternalSubsystemBitSet& InMutableSubsystemsBitSet)
{
SubsystemAccess.SetSubsystemRequirementBits(InConstSubsystemsBitSet, InMutableSubsystemsBitSet);
}
EMassExecutionContextType ExecutionType = EMassExecutionContextType::Local;
friend FMassArchetypeData;
/**
* Note that this operator is private on purpose, used to simplify the implementation of constructors.
* The context itself does not support assignment.
*/
FMassExecutionContext& operator=(const FMassExecutionContext& Other) = default;
public:
MASSENTITY_API explicit FMassExecutionContext(FMassEntityManager& InEntityManager, const float InDeltaTimeSeconds = 0.f, const bool bInFlushDeferredCommands = true);
FMassExecutionContext(FMassExecutionContext&& Other) = default;
MASSENTITY_API FMassExecutionContext(const FMassExecutionContext& Other);
MASSENTITY_API FMassExecutionContext(const FMassExecutionContext& Other, FMassEntityQuery& Query, const TSharedPtr<FMassCommandBuffer>& InCommandBuffer = {});
MASSENTITY_API ~FMassExecutionContext();
/** For internal use only, should never be exported as part of API */
MASSENTITY_API static FMassExecutionContext& GetDummyInstance();
FMassEntityManager& GetEntityManagerChecked() const;
const TSharedRef<FMassEntityManager>& GetSharedEntityManager();
#if WITH_MASSENTITY_DEBUG
const FString& DebugGetExecutionDesc() const { return DebugExecutionDescription; }
void DebugSetExecutionDesc(const FString& Description) { DebugExecutionDescription = Description; }
void DebugSetExecutionDesc(FString&& Description) { DebugExecutionDescription = MoveTemp(Description); }
UMassProcessor* DebugGetProcessor() const { return DebugProcessor.Get(); }
void DebugSetProcessor(UMassProcessor* Processor) { DebugProcessor = Processor; }
#endif
void PushQuery(FMassEntityQuery& InQuery);
void PopQuery(const FMassEntityQuery& InQuery);
const FMassEntityQuery& GetCurrentQuery() const;
bool IsCurrentQuery(const FMassEntityQuery& Query) const;
void ApplyFragmentRequirements(const FMassEntityQuery& RequestingQuery);
void ClearFragmentViews(const FMassEntityQuery& RequestingQuery);
/**
* Iterator to easily loop through entities in the current chunk.
* Supports ranged for and can be used directly as an entity index for the current chunk.
*/
struct FEntityIterator
{
FORCEINLINE int32 operator*() const
{
return EntityIndex;
}
FORCEINLINE bool operator!=(const int& Other) const
{
return EntityIndex != Other;
}
FORCEINLINE operator int32() const
{
return EntityIndex;
}
FORCEINLINE operator bool() const
{
return SerialNumber && EntityIndex < NumEntities;
}
FORCEINLINE bool operator<(const int32 Other) const
{
return SerialNumber && EntityIndex != INDEX_NONE && EntityIndex < Other;
}
FORCEINLINE FEntityIterator& operator++()
{
++EntityIndex;
#if WITH_MASSENTITY_DEBUG
if (UNLIKELY(QueryRuntime.bCheckProcessorBreaks || QueryRuntime.BreakFragmentsCount != 0)
&& EntityIndex < NumEntities)
{
TestBreakpoints();
}
#endif //WITH_MASSENTITY_DEBUG
return *this;
}
FORCEINLINE void operator++(int)
{
++(*this);
}
FEntityIterator&& begin()
{
return MoveTemp(*this);
}
FEntityIterator end() const
{
FEntityIterator End;
End.EntityIndex = NumEntities;
return End;
}
MASSENTITY_API FEntityIterator();
FEntityIterator(FEntityIterator&&) = default;
FEntityIterator& operator=(const FEntityIterator&) = delete;
FEntityIterator& operator=(FEntityIterator&&) = delete;
/**
* Iterator copying is disabled to avoid additional checks to detect if entity chunk being iterated on changed.
* This decision is to be reconsidered when valid iterator-copying scenarios emerge.
*/
FEntityIterator(const FEntityIterator&) = delete;
private:
friend FMassExecutionContext;
FEntityIterator(FMassExecutionContext& InExecutionContext);
FEntityIterator(FMassExecutionContext& InExecutionContext, FQueryTransientRuntime& InQueryRuntime);
#if WITH_MASSENTITY_DEBUG
MASSENTITY_API void TestBreakpoints();
#endif //!WITH_MASSENTITY_DEBUG
const FMassExecutionContext& ExecutionContext;
const FQueryTransientRuntime& QueryRuntime;
int32 EntityIndex = INDEX_NONE;
const int32 NumEntities = INDEX_NONE;
const uint32 SerialNumber = 0;
};
/**
* Creates an Entity Iterator for the current chunk.
* Supports range-based for loop and can be used directly as an entity index for the current chunk.
*/
MASSENTITY_API FEntityIterator CreateEntityIterator();
/** Sets bFlushDeferredCommands. Note that setting to True while the system is being executed doesn't result in
* immediate commands flushing */
void SetFlushDeferredCommands(const bool bNewFlushDeferredCommands);
void SetDeferredCommandBuffer(const TSharedPtr<FMassCommandBuffer>& InDeferredCommandBuffer);
MASSENTITY_API void SetEntityCollection(const FMassArchetypeEntityCollection& InEntityCollection);
MASSENTITY_API void SetEntityCollection(FMassArchetypeEntityCollection&& InEntityCollection);
void ClearEntityCollection();
void SetAuxData(const FInstancedStruct& InAuxData);
void SetExecutionType(EMassExecutionContextType InExecutionType);
EMassExecutionContextType GetExecutionType() const;
float GetDeltaTimeSeconds() const;
MASSENTITY_API UWorld* GetWorld();
TSharedPtr<FMassCommandBuffer> GetSharedDeferredCommandBuffer() const { return DeferredCommandBuffer; }
FMassCommandBuffer& Defer() const { checkSlow(DeferredCommandBuffer.IsValid()); return *DeferredCommandBuffer.Get(); }
TConstArrayView<FMassEntityHandle> GetEntities() const { return EntityListView; }
int32 GetNumEntities() const { return EntityListView.Num(); }
FMassEntityHandle GetEntity(const int32 Index) const
{
return EntityListView[Index];
}
void ForEachEntityInChunk(const FMassEntityExecuteFunction& EntityExecuteFunction)
{
for (FEntityIterator EntityIterator = CreateEntityIterator(); EntityIterator; ++EntityIterator)
{
EntityExecuteFunction(*this, EntityIterator);
}
}
bool DoesArchetypeHaveFragment(const UScriptStruct& FragmentType) const
{
return CurrentArchetypeCompositionDescriptor.Fragments.Contains(FragmentType);
}
template<typename T>
bool DoesArchetypeHaveFragment() const
{
static_assert(UE::Mass::CFragment<T>, "Given struct is not of a valid fragment type.");
return CurrentArchetypeCompositionDescriptor.Fragments.Contains<T>();
}
bool DoesArchetypeHaveTag(const UScriptStruct& TagType) const
{
return CurrentArchetypeCompositionDescriptor.Tags.Contains(TagType);
}
template<typename T>
bool DoesArchetypeHaveTag() const
{
static_assert(UE::Mass::CTag<T>, "Given struct is not of a valid tag type.");
return CurrentArchetypeCompositionDescriptor.Tags.Contains<T>();
}
#if WITH_MASSENTITY_DEBUG
FColor DebugGetArchetypeColor() const
{
return DebugColor;
}
#endif // WITH_MASSENTITY_DEBUG
/** Chunk related operations */
void SetCurrentChunkSerialModificationNumber(const int32 SerialModificationNumber) { ChunkSerialModificationNumber = SerialModificationNumber; }
int32 GetChunkSerialModificationNumber() const { return ChunkSerialModificationNumber; }
template<typename T>
T* GetMutableChunkFragmentPtr()
{
static_assert(UE::Mass::CChunkFragment<T>, "Given struct doesn't represent a valid chunk fragment type. Make sure to inherit from FMassChunkFragment or one of its child-types.");
const UScriptStruct* Type = T::StaticStruct();
FChunkFragmentView* FoundChunkFragmentData = ChunkFragmentViews.FindByPredicate([Type](const FChunkFragmentView& Element) { return Element.Requirement.StructType == Type; } );
CHECK_IF_READWRITE(FoundChunkFragmentData);
return FoundChunkFragmentData ? FoundChunkFragmentData->FragmentView.GetPtr<T>() : static_cast<T*>(nullptr);
}
template<typename T>
T& GetMutableChunkFragment()
{
T* ChunkFragment = GetMutableChunkFragmentPtr<T>();
CHECK_IF_VALID(ChunkFragment, T::StaticStruct());
return *ChunkFragment;
}
template<typename T>
const T* GetChunkFragmentPtr() const
{
static_assert(UE::Mass::CChunkFragment<T>, "Given struct doesn't represent a valid chunk fragment type. Make sure to inherit from FMassChunkFragment or one of its child-types.");
const UScriptStruct* Type = T::StaticStruct();
const FChunkFragmentView* FoundChunkFragmentData = ChunkFragmentViews.FindByPredicate([Type](const FChunkFragmentView& Element) { return Element.Requirement.StructType == Type; } );
return FoundChunkFragmentData ? FoundChunkFragmentData->FragmentView.GetPtr<T>() : static_cast<const T*>(nullptr);
}
template<typename T>
const T& GetChunkFragment() const
{
const T* ChunkFragment = GetChunkFragmentPtr<T>();
CHECK_IF_VALID(ChunkFragment, T::StaticStruct());
return *ChunkFragment;
}
/** Shared fragment related operations */
const void* GetConstSharedFragmentPtr(const UScriptStruct& SharedFragmentType) const
{
const FConstSharedFragmentView* FoundSharedFragmentData = ConstSharedFragmentViews.FindByPredicate([&SharedFragmentType](const FConstSharedFragmentView& Element) { return Element.Requirement.StructType == &SharedFragmentType; });
return FoundSharedFragmentData ? FoundSharedFragmentData->FragmentView.GetMemory() : nullptr;
}
template<typename T>
const T* GetConstSharedFragmentPtr() const
{
static_assert(UE::Mass::CConstSharedFragment<T>, "Given struct doesn't represent a valid const shared fragment type. Make sure to inherit from FMassConstSharedFragment or one of its child-types.");
const FConstSharedFragmentView* FoundSharedFragmentData = ConstSharedFragmentViews.FindByPredicate([](const FConstSharedFragmentView& Element) { return Element.Requirement.StructType == T::StaticStruct(); });
return FoundSharedFragmentData ? FoundSharedFragmentData->FragmentView.GetPtr<const T>() : static_cast<const T*>(nullptr);
}
template<typename T>
const T& GetConstSharedFragment() const
{
const T* SharedFragment = GetConstSharedFragmentPtr<const T>();
CHECK_IF_VALID(SharedFragment, T::StaticStruct());
return *SharedFragment;
}
template<typename T>
T* GetMutableSharedFragmentPtr()
{
static_assert(UE::Mass::CSharedFragment<T>, "Given struct doesn't represent a valid shared fragment type. Make sure to inherit from FMassSharedFragment or one of its child-types.");
FSharedFragmentView* FoundSharedFragmentData = SharedFragmentViews.FindByPredicate([](const FSharedFragmentView& Element) { return Element.Requirement.StructType == T::StaticStruct(); });
CHECK_IF_READWRITE(FoundSharedFragmentData);
return FoundSharedFragmentData ? FoundSharedFragmentData->FragmentView.GetPtr<T>() : static_cast<T*>(nullptr);
}
template<typename T>
const T* GetSharedFragmentPtr() const
{
static_assert(UE::Mass::CSharedFragment<T>, "Given struct doesn't represent a valid shared fragment type. Make sure to inherit from FMassSharedFragment or one of its child-types.");
const FSharedFragmentView* FoundSharedFragmentData = SharedFragmentViews.FindByPredicate([](const FSharedFragmentView& Element) { return Element.Requirement.StructType == T::StaticStruct(); });
return FoundSharedFragmentData ? FoundSharedFragmentData->FragmentView.GetPtr<T>() : static_cast<const T*>(nullptr);
}
template<typename T>
T& GetMutableSharedFragment()
{
T* SharedFragment = GetMutableSharedFragmentPtr<T>();
CHECK_IF_VALID(SharedFragment, T::StaticStruct());
return *SharedFragment;
}
template<typename T>
const T& GetSharedFragment() const
{
const T* SharedFragment = GetSharedFragmentPtr<T>();
CHECK_IF_VALID(SharedFragment, T::StaticStruct());
return *SharedFragment;
}
/* Fragments related operations */
template<typename TFragment>
TArrayView<TFragment> GetMutableFragmentView()
{
const UScriptStruct* FragmentType = TFragment::StaticStruct();
const FFragmentView* View = FragmentViews.FindByPredicate([FragmentType](const FFragmentView& Element) { return Element.Requirement.StructType == FragmentType; });
CHECK_IF_VALID(View, FragmentType);
CHECK_IF_READWRITE(View);
return MakeArrayView<TFragment>((TFragment*)View->FragmentView.GetData(), View->FragmentView.Num());
}
template<typename TFragment>
TConstArrayView<TFragment> GetFragmentView() const
{
const UScriptStruct* FragmentType = TFragment::StaticStruct();
const FFragmentView* View = FragmentViews.FindByPredicate([FragmentType](const FFragmentView& Element) { return Element.Requirement.StructType == FragmentType; });
CHECK_IF_VALID(View, TFragment::StaticStruct());
return TConstArrayView<TFragment>((const TFragment*)View->FragmentView.GetData(), View->FragmentView.Num());
}
TConstArrayView<FMassFragment> GetFragmentView(const UScriptStruct* FragmentType) const
{
const FFragmentView* View = FragmentViews.FindByPredicate([FragmentType](const FFragmentView& Element) { return Element.Requirement.StructType == FragmentType; });
CHECK_IF_VALID(View, FragmentType);
return TConstArrayView<FMassFragment>((const FMassFragment*)View->FragmentView.GetData(), View->FragmentView.Num());;
}
TArrayView<FMassFragment> GetMutableFragmentView(const UScriptStruct* FragmentType)
{
const FFragmentView* View = FragmentViews.FindByPredicate([FragmentType](const FFragmentView& Element) { return Element.Requirement.StructType == FragmentType; });
CHECK_IF_VALID(View, FragmentType);
CHECK_IF_READWRITE(View);
return View->FragmentView;
}
template<typename TFragmentBase>
TConstArrayView<TFragmentBase> GetFragmentView(TNotNull<const UScriptStruct*> FragmentType) const
{
check(FragmentType->IsChildOf(TFragmentBase::StaticStruct()));
TConstArrayView<FMassFragment> View = GetFragmentView(FragmentType);
return TConstArrayView<TFragmentBase>(reinterpret_cast<const TFragmentBase*>(View.GetData()), View.Num());
}
template<typename TFragmentBase>
TArrayView<TFragmentBase> GetMutableFragmentView(TNotNull<const UScriptStruct*> FragmentType)
{
check(FragmentType->IsChildOf(TFragmentBase::StaticStruct()));
TArrayView<FMassFragment> View = GetMutableFragmentView(FragmentType);
return TArrayView<TFragmentBase>(reinterpret_cast<TFragmentBase*>(View.GetData()), View.Num());;
}
template<typename T, typename = typename TEnableIf<TIsDerivedFrom<T, USubsystem>::IsDerived>::Type>
T* GetMutableSubsystem()
{
return SubsystemAccess.GetMutableSubsystem<T>();
}
template<typename T, typename = typename TEnableIf<TIsDerivedFrom<T, USubsystem>::IsDerived>::Type>
T& GetMutableSubsystemChecked()
{
return SubsystemAccess.GetMutableSubsystemChecked<T>();
}
template<typename T, typename = typename TEnableIf<TIsDerivedFrom<T, USubsystem>::IsDerived>::Type>
const T* GetSubsystem()
{
return SubsystemAccess.GetSubsystem<T>();
}
template<typename T, typename = typename TEnableIf<TIsDerivedFrom<T, USubsystem>::IsDerived>::Type>
const T& GetSubsystemChecked()
{
return SubsystemAccess.GetSubsystemChecked<T>();
}
template<typename T, typename = typename TEnableIf<TIsDerivedFrom<T, USubsystem>::IsDerived>::Type>
T* GetMutableSubsystem(const TSubclassOf<USubsystem> SubsystemClass)
{
return SubsystemAccess.GetMutableSubsystem<T>(SubsystemClass);
}
template<typename T, typename = typename TEnableIf<TIsDerivedFrom<T, USubsystem>::IsDerived>::Type>
T& GetMutableSubsystemChecked(const TSubclassOf<USubsystem> SubsystemClass)
{
return SubsystemAccess.GetMutableSubsystemChecked<T>(SubsystemClass);
}
template<typename T, typename = typename TEnableIf<TIsDerivedFrom<T, USubsystem>::IsDerived>::Type>
const T* GetSubsystem(const TSubclassOf<USubsystem> SubsystemClass)
{
return SubsystemAccess.GetSubsystem<T>(SubsystemClass);
}
template<typename T, typename = typename TEnableIf<TIsDerivedFrom<T, USubsystem>::IsDerived>::Type>
const T& GetSubsystemChecked(const TSubclassOf<USubsystem> SubsystemClass)
{
return SubsystemAccess.GetSubsystemChecked<T>(SubsystemClass);
}
/** Sparse chunk related operation */
const FMassArchetypeEntityCollection& GetEntityCollection() const { return EntityCollection; }
const FInstancedStruct& GetAuxData() const { return AuxData; }
FInstancedStruct& GetMutableAuxData() { return AuxData; }
template<typename TFragment>
bool ValidateAuxDataType() const
{
const UScriptStruct* FragmentType = GetAuxData().GetScriptStruct();
return FragmentType != nullptr && FragmentType == TFragment::StaticStruct();
}
MASSENTITY_API void FlushDeferred();
void ClearExecutionData();
void SetCurrentArchetypeCompositionDescriptor(const FMassArchetypeCompositionDescriptor& Descriptor)
{
CurrentArchetypeCompositionDescriptor = Descriptor;
}
#if WITH_MASSENTITY_DEBUG
void DebugSetColor(FColor InColor)
{
DebugColor = InColor;
}
#endif // WITH_MASSENTITY_DEBUG
/**
* Processes SubsystemRequirements to fetch and cache all the indicated subsystems. If a UWorld is required to fetch
* a specific subsystem then the one associated with the stored EntityManager will be used.
*
* @param SubsystemRequirements indicates all the subsystems that are expected to be accessed. Requesting a subsystem
* not indicated by the SubsystemRequirements will result in a failure.
*
* @return `true` if all required subsystems have been found, `false` otherwise.
*/
bool CacheSubsystemRequirements(const FMassSubsystemRequirements& SubsystemRequirements);
protected:
void SetSubsystemRequirements(const FMassSubsystemRequirements& SubsystemRequirements)
{
SubsystemAccess.SetSubsystemRequirements(SubsystemRequirements);
}
void SetFragmentRequirements(const FMassFragmentRequirements& FragmentRequirements);
void ClearFragmentViews()
{
for (FFragmentView& View : FragmentViews)
{
View.FragmentView = TArrayView<FMassFragment>();
}
for (FChunkFragmentView& View : ChunkFragmentViews)
{
View.FragmentView.Reset();
}
for (FConstSharedFragmentView& View : ConstSharedFragmentViews)
{
View.FragmentView.Reset();
}
for (FSharedFragmentView& View : SharedFragmentViews)
{
View.FragmentView.Reset();
}
}
public:
//-----------------------------------------------------------------------------
// DEPRECATED functions
//-----------------------------------------------------------------------------
UE_DEPRECATED(5.4, "Deprecated in favor of 'SetCurrentArchetypeCompositionDescriptor' as this provides information on the entire archetype.")
void SetCurrentArchetypesTagBitSet(const FMassTagBitSet&) {}
};
//-----------------------------------------------------------------------------
// Inlines
//-----------------------------------------------------------------------------
inline FMassEntityManager& FMassExecutionContext::GetEntityManagerChecked() const
{
return EntityManager.Get();
}
inline const TSharedRef<FMassEntityManager>& FMassExecutionContext::GetSharedEntityManager()
{
return EntityManager;
}
inline void FMassExecutionContext::SetFlushDeferredCommands(const bool bNewFlushDeferredCommands)
{
bFlushDeferredCommands = bNewFlushDeferredCommands;
}
inline void FMassExecutionContext::SetDeferredCommandBuffer(const TSharedPtr<FMassCommandBuffer>& InDeferredCommandBuffer)
{
DeferredCommandBuffer = InDeferredCommandBuffer;
}
inline void FMassExecutionContext::ClearEntityCollection()
{
EntityCollection.Reset();
}
inline void FMassExecutionContext::SetAuxData(const FInstancedStruct& InAuxData)
{
AuxData = InAuxData;
}
inline float FMassExecutionContext::GetDeltaTimeSeconds() const
{
return DeltaTimeSeconds;
}
inline void FMassExecutionContext::SetExecutionType(EMassExecutionContextType InExecutionType)
{
check(InExecutionType != EMassExecutionContextType::MAX);
ExecutionType = InExecutionType;
}
inline EMassExecutionContextType FMassExecutionContext::GetExecutionType() const
{
return ExecutionType;
}
inline const FMassEntityQuery& FMassExecutionContext::GetCurrentQuery() const
{
check(QueriesStack.Num());
return *QueriesStack.Last().Query;
}
inline bool FMassExecutionContext::IsCurrentQuery(const FMassEntityQuery& Query) const
{
return QueriesStack.Num() && QueriesStack.Last().Query == &Query;
}
inline void FMassExecutionContext::ApplyFragmentRequirements(const FMassEntityQuery& RequestingQuery)
{
check(IsCurrentQuery(RequestingQuery));
SetFragmentRequirements(RequestingQuery);
}
inline void FMassExecutionContext::ClearFragmentViews(const FMassEntityQuery& RequestingQuery)
{
check(IsCurrentQuery(RequestingQuery));
ClearFragmentViews();
}
#undef CHECK_IF_VALID
#undef CHECK_IF_READWRITE