// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "EntitySystem/MovieSceneEntitySystemTypes.h" namespace UE { namespace MovieScene { /** Facade for any component data type */ template struct TComponentPtr { /** Value type is either a T or const T& for read-only types, or T& for writeable types */ using ValueType = std::conditional_t::Value, typename TCallTraits::ParamType, T&>; TComponentPtr() : ComponentPtr(nullptr) {} explicit TComponentPtr(T* InComponentPtr) : ComponentPtr(InComponentPtr) {} TComponentPtr(const TComponentPtr& RHS) = default; TComponentPtr& operator=(const TComponentPtr& RHS) = default; TComponentPtr(TComponentPtr&& RHS) : ComponentPtr(RHS.ComponentPtr) { RHS.ComponentPtr = nullptr; } TComponentPtr& operator=(TComponentPtr&& RHS) { ComponentPtr = RHS.ComponentPtr; RHS.ComponentPtr = nullptr; return *this; } FORCEINLINE explicit operator bool() const { return IsValid(); } FORCEINLINE bool IsValid() const { return ComponentPtr != nullptr; } /** Explicitly convert this component data to its underlying pointer type */ FORCEINLINE T* AsPtr() const { return ComponentPtr; } /** Retrieve this component data as an array view of the specified size (usually the size will be FEntityAllocation::Num()) */ FORCEINLINE TArrayView AsArray(int32 Num) const { return MakeArrayView(ComponentPtr, Num); } /** Retrieve a slice of this component data as an array view of the specified size and offset (usually the size will be FEntityAllocation::Num()) */ FORCEINLINE TArrayView Slice(int32 StartIndex, int32 Num) const { return MakeArrayView(ComponentPtr + StartIndex, Num); } FORCEINLINE T* operator->() const { return ComponentPtr; } FORCEINLINE ValueType operator*() const { return *ComponentPtr; } FORCEINLINE ValueType operator[](int32 Index) const { return ComponentPtr[Index]; } ValueType ComponentAtIndex(int32 Index) const { return (*this)[Index]; } FORCEINLINE operator T*() const { return ComponentPtr; } protected: T* ComponentPtr; }; /** * Typed write-lock for component data */ template struct TComponentLock; template struct TComponentLockMixin; template<> struct TComponentLockMixin { TComponentLockMixin() = default; explicit TComponentLockMixin(const FComponentHeader* InHeader, EComponentHeaderLockMode InLockMode) : Lock(InHeader, InLockMode) {} private: FScopedHeaderReadLock Lock; }; template<> struct TComponentLockMixin { TComponentLockMixin() = default; explicit TComponentLockMixin(const FComponentHeader* InHeader, EComponentHeaderLockMode InLockMode, FEntityAllocationWriteContext InWriteContext) : Lock(InHeader, InLockMode, InWriteContext) {} private: FScopedHeaderWriteLock Lock; }; struct FReadErased { FReadErased(const FComponentHeader* InHeader, int32 ComponentOffset = 0) : ComponentPtr(InHeader->Components + ComponentOffset*InHeader->Sizeof) , Sizeof(InHeader->Sizeof) {} FORCEINLINE const void* AsPtr() const { return ComponentPtr; } FORCEINLINE const void* operator[](int32 Index) const { return ComponentPtr + Sizeof*Index; } FORCEINLINE const void* ComponentAtIndex(int32 Index) const { return ComponentPtr + Sizeof*Index; } FORCEINLINE bool IsValid() const { return ComponentPtr != nullptr; } protected: FReadErased() : ComponentPtr(nullptr) , Sizeof(0) {} const uint8* ComponentPtr; int32 Sizeof; }; struct FReadErasedOptional : FReadErased { FReadErasedOptional() = default; explicit FReadErasedOptional(const FComponentHeader* InHeader, int32 ComponentOffset = 0) { if (InHeader) { ComponentPtr = InHeader->Components + ComponentOffset*InHeader->Sizeof; Sizeof = InHeader->Sizeof; } else { ComponentPtr = nullptr; Sizeof = 0; } } const void* ComponentAtIndex(int32 Index) const { return this->ComponentPtr ? FReadErased::ComponentAtIndex(Index) : nullptr; } }; template struct TRead : TComponentPtr { TRead() = default; explicit TRead(const T* ComponentPtr, int32 ComponentOffset = 0) : TComponentPtr(ComponentPtr + ComponentOffset) {} explicit TRead(const FComponentHeader* InHeader, int32 ComponentOffset = 0) : TComponentPtr(reinterpret_cast(InHeader->Components) + ComponentOffset) {} }; using FReadEntityIDs = TRead; template struct TReadOptional : TComponentPtr { TReadOptional() = default; explicit TReadOptional(const T* InData, int32 ComponentOffset = 0) { if (InData) { this->ComponentPtr = InData + ComponentOffset; } } explicit TReadOptional(const FComponentHeader* InHeader, int32 ComponentOffset = 0) { if (InHeader) { this->ComponentPtr = reinterpret_cast(InHeader->Components) + ComponentOffset; } } const T* ComponentAtIndex(int32 Index) const { return this->ComponentPtr ? &this->ComponentPtr[Index] : nullptr; } }; struct FWriteErased { FWriteErased() : ComponentPtr(nullptr) , Sizeof(0) {} FWriteErased(const FComponentHeader* InHeader, int32 ComponentOffset = 0) : ComponentPtr(InHeader->Components + ComponentOffset*InHeader->Sizeof) , Sizeof(InHeader->Sizeof) {} FORCEINLINE void* AsPtr() const { return ComponentPtr; } FORCEINLINE void* operator[](int32 Index) const { return ComponentPtr + Sizeof*Index; } FORCEINLINE bool IsValid() const { return ComponentPtr != nullptr; } void* ComponentAtIndex(int32 Index) const { return (*this)[Index]; } protected: uint8* ComponentPtr; int32 Sizeof; }; struct FWriteErasedOptional : FWriteErased { FWriteErasedOptional() = default; FWriteErasedOptional(const FComponentHeader* InHeader, int32 ComponentOffset = 0) { if (InHeader) { ComponentPtr = InHeader->Components + ComponentOffset*InHeader->Sizeof; Sizeof = InHeader->Sizeof; } else { ComponentPtr = nullptr; Sizeof = 0; } } void* ComponentAtIndex(int32 Index) const { return ComponentPtr ? (*this)[Index] : nullptr; } }; template struct TWrite : TComponentPtr { TWrite() = default; explicit TWrite(T* InData, int32 ComponentOffset = 0) : TComponentPtr(InData + ComponentOffset) {} explicit TWrite(const FComponentHeader* InHeader, int32 ComponentOffset = 0) : TComponentPtr(reinterpret_cast(InHeader->Components) + ComponentOffset) {} }; template struct TWriteOptional : TComponentPtr { TWriteOptional() = default; explicit TWriteOptional(T* InData, int32 ComponentOffset = 0) { if (InData) { this->ComponentPtr = InData + ComponentOffset; } } explicit TWriteOptional(const FComponentHeader* InHeader, int32 ComponentOffset = 0) { if (InHeader) { this->ComponentPtr = reinterpret_cast(InHeader->Components) + ComponentOffset; } } T* ComponentAtIndex(int32 Index) const { return this->ComponentPtr ? &this->ComponentPtr[Index] : nullptr; } }; template struct TComponentLock; template<> struct TComponentLock : TComponentLockMixin, FReadErased { explicit TComponentLock(const FComponentHeader* InHeader, EComponentHeaderLockMode InLockMode, int32 ComponentOffset = 0) : TComponentLockMixin(InHeader, InLockMode) , FReadErased(InHeader, ComponentOffset) {} const void* ComponentAtIndex(int32 Index) const { return (*this)[Index]; } }; template<> struct TComponentLock : TComponentLockMixin, FReadErasedOptional { TComponentLock() = default; explicit TComponentLock(const FComponentHeader* InHeader, EComponentHeaderLockMode InLockMode, int32 ComponentOffset = 0) { if (InHeader) { *static_cast*>(this) = TComponentLockMixin(InHeader, InLockMode); *static_cast(this) = FReadErasedOptional(InHeader, ComponentOffset); } } explicit operator bool() const { return this->ComponentPtr != nullptr; } }; template<> struct TComponentLock : TComponentLockMixin, FWriteErased { explicit TComponentLock(const FComponentHeader* InHeader, EComponentHeaderLockMode InLockMode, FEntityAllocationWriteContext InWriteContext, int32 ComponentOffset = 0) : TComponentLockMixin(InHeader, InLockMode, InWriteContext) , FWriteErased(InHeader, ComponentOffset) {} }; template<> struct TComponentLock : TComponentLockMixin, FWriteErasedOptional { TComponentLock() = default; explicit TComponentLock(const FComponentHeader* InHeader, EComponentHeaderLockMode InLockMode, FEntityAllocationWriteContext InWriteContext, int32 ComponentOffset = 0) { if (InHeader) { *static_cast*>(this) = TComponentLockMixin(InHeader, InLockMode, InWriteContext); *static_cast(this) = FWriteErasedOptional(InHeader, ComponentOffset); } } }; template struct TComponentLock> : TComponentLockMixin, TRead { explicit TComponentLock(const FComponentHeader* InHeader, EComponentHeaderLockMode InLockMode , int32 ComponentOffset = 0) : TComponentLockMixin(InHeader, InLockMode) , TRead(InHeader, ComponentOffset) {} }; template struct TComponentLock> : TComponentLockMixin, TReadOptional { TComponentLock() = default; explicit TComponentLock(const FComponentHeader* InHeader, EComponentHeaderLockMode InLockMode, int32 ComponentOffset = 0) { if (InHeader) { *static_cast*>(this) = TComponentLockMixin(InHeader, InLockMode); *static_cast*>(this) = TReadOptional(InHeader, ComponentOffset); } } }; template struct TComponentLock> : TComponentLockMixin, TWrite { explicit TComponentLock(const FComponentHeader* InHeader, EComponentHeaderLockMode InLockMode, FEntityAllocationWriteContext InWriteContext, int32 ComponentOffset = 0) : TComponentLockMixin(InHeader, InLockMode, InWriteContext) , TWrite(InHeader, ComponentOffset) {} }; template struct TComponentLock> : TComponentLockMixin, TWriteOptional { TComponentLock() = default; explicit TComponentLock(const FComponentHeader* InHeader, EComponentHeaderLockMode InLockMode, FEntityAllocationWriteContext InWriteContext, int32 ComponentOffset = 0) { if (InHeader) { *static_cast*>(this) = TComponentLockMixin(InHeader, InLockMode, InWriteContext); *static_cast*>(this) = TWriteOptional(InHeader, ComponentOffset); } } }; using FComponentReader = TComponentLock; using FOptionalComponentReader = TComponentLock; using FComponentWriter = TComponentLock; using FOptionalComponentWriter = TComponentLock; template using TComponentReader = TComponentLock>; template using TOptionalComponentReader = TComponentLock>; template using TComponentWriter = TComponentLock>; template using TOptionalComponentWriter = TComponentLock>; template using TMultiComponentLock = TTuple...>; template struct TMultiComponentData { TMultiComponentData(T... InData) : Data(InData...) {} TMultiComponentData(const TMultiComponentLock& InAggregateLock) { auto Init = [](const auto& InLock, auto& OutData) { if (InLock) { OutData = InLock; } }; VisitTupleElements(Init, InAggregateLock, this->Data); } template auto* Get() const { return Data.template Get().AsPtr(); } template auto GetAsArray(int32 ArraySize) const { auto* ComponentPtr = Data.template Get().AsPtr(); return MakeArrayView(ComponentPtr, ComponentPtr ? ArraySize : 0); } private: TTuple Data; }; template using TMultiReadOptional = TMultiComponentData...>; template using TReadOneOrMoreOf = TMultiComponentData...>; template using TReadOneOf = TMultiComponentData...>; } // namespace UE } // namespace MovieScene