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

477 lines
12 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "EntitySystem/MovieSceneEntitySystemTypes.h"
namespace UE
{
namespace MovieScene
{
/** Facade for any component data type */
template<typename T>
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<TIsConst<T>::Value, typename TCallTraits<T>::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<T> 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<T> 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<typename Accessor> struct TComponentLock;
template<typename LockType> struct TComponentLockMixin;
template<>
struct TComponentLockMixin<FScopedHeaderReadLock>
{
TComponentLockMixin() = default;
explicit TComponentLockMixin(const FComponentHeader* InHeader, EComponentHeaderLockMode InLockMode)
: Lock(InHeader, InLockMode)
{}
private:
FScopedHeaderReadLock Lock;
};
template<>
struct TComponentLockMixin<FScopedHeaderWriteLock>
{
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<typename T>
struct TRead : TComponentPtr<const T>
{
TRead() = default;
explicit TRead(const T* ComponentPtr, int32 ComponentOffset = 0)
: TComponentPtr<const T>(ComponentPtr + ComponentOffset)
{}
explicit TRead(const FComponentHeader* InHeader, int32 ComponentOffset = 0)
: TComponentPtr<const T>(reinterpret_cast<const T*>(InHeader->Components) + ComponentOffset)
{}
};
using FReadEntityIDs = TRead<FMovieSceneEntityID>;
template<typename T>
struct TReadOptional : TComponentPtr<const T>
{
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<const T*>(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<typename T>
struct TWrite : TComponentPtr<T>
{
TWrite() = default;
explicit TWrite(T* InData, int32 ComponentOffset = 0)
: TComponentPtr<T>(InData + ComponentOffset)
{}
explicit TWrite(const FComponentHeader* InHeader, int32 ComponentOffset = 0)
: TComponentPtr<T>(reinterpret_cast<T*>(InHeader->Components) + ComponentOffset)
{}
};
template<typename T>
struct TWriteOptional : TComponentPtr<T>
{
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<T*>(InHeader->Components) + ComponentOffset;
}
}
T* ComponentAtIndex(int32 Index) const
{
return this->ComponentPtr ? &this->ComponentPtr[Index] : nullptr;
}
};
template<typename AccessorType> struct TComponentLock;
template<>
struct TComponentLock<FReadErased> : TComponentLockMixin<FScopedHeaderReadLock>, FReadErased
{
explicit TComponentLock(const FComponentHeader* InHeader, EComponentHeaderLockMode InLockMode, int32 ComponentOffset = 0)
: TComponentLockMixin<FScopedHeaderReadLock>(InHeader, InLockMode)
, FReadErased(InHeader, ComponentOffset)
{}
const void* ComponentAtIndex(int32 Index) const
{
return (*this)[Index];
}
};
template<>
struct TComponentLock<FReadErasedOptional> : TComponentLockMixin<FScopedHeaderReadLock>, FReadErasedOptional
{
TComponentLock() = default;
explicit TComponentLock(const FComponentHeader* InHeader, EComponentHeaderLockMode InLockMode, int32 ComponentOffset = 0)
{
if (InHeader)
{
*static_cast<TComponentLockMixin<FScopedHeaderReadLock>*>(this) = TComponentLockMixin<FScopedHeaderReadLock>(InHeader, InLockMode);
*static_cast<FReadErasedOptional*>(this) = FReadErasedOptional(InHeader, ComponentOffset);
}
}
explicit operator bool() const
{
return this->ComponentPtr != nullptr;
}
};
template<>
struct TComponentLock<FWriteErased> : TComponentLockMixin<FScopedHeaderWriteLock>, FWriteErased
{
explicit TComponentLock(const FComponentHeader* InHeader, EComponentHeaderLockMode InLockMode, FEntityAllocationWriteContext InWriteContext, int32 ComponentOffset = 0)
: TComponentLockMixin<FScopedHeaderWriteLock>(InHeader, InLockMode, InWriteContext)
, FWriteErased(InHeader, ComponentOffset)
{}
};
template<>
struct TComponentLock<FWriteErasedOptional> : TComponentLockMixin<FScopedHeaderWriteLock>, FWriteErasedOptional
{
TComponentLock() = default;
explicit TComponentLock(const FComponentHeader* InHeader, EComponentHeaderLockMode InLockMode, FEntityAllocationWriteContext InWriteContext, int32 ComponentOffset = 0)
{
if (InHeader)
{
*static_cast<TComponentLockMixin<FScopedHeaderWriteLock>*>(this) = TComponentLockMixin<FScopedHeaderWriteLock>(InHeader, InLockMode, InWriteContext);
*static_cast<FWriteErasedOptional*>(this) = FWriteErasedOptional(InHeader, ComponentOffset);
}
}
};
template<typename T>
struct TComponentLock<TRead<T>> : TComponentLockMixin<FScopedHeaderReadLock>, TRead<T>
{
explicit TComponentLock(const FComponentHeader* InHeader, EComponentHeaderLockMode InLockMode , int32 ComponentOffset = 0)
: TComponentLockMixin<FScopedHeaderReadLock>(InHeader, InLockMode)
, TRead<T>(InHeader, ComponentOffset)
{}
};
template<typename T>
struct TComponentLock<TReadOptional<T>> : TComponentLockMixin<FScopedHeaderReadLock>, TReadOptional<T>
{
TComponentLock() = default;
explicit TComponentLock(const FComponentHeader* InHeader, EComponentHeaderLockMode InLockMode, int32 ComponentOffset = 0)
{
if (InHeader)
{
*static_cast<TComponentLockMixin<FScopedHeaderReadLock>*>(this) = TComponentLockMixin<FScopedHeaderReadLock>(InHeader, InLockMode);
*static_cast<TReadOptional<T>*>(this) = TReadOptional<T>(InHeader, ComponentOffset);
}
}
};
template<typename T>
struct TComponentLock<TWrite<T>> : TComponentLockMixin<FScopedHeaderWriteLock>, TWrite<T>
{
explicit TComponentLock(const FComponentHeader* InHeader, EComponentHeaderLockMode InLockMode, FEntityAllocationWriteContext InWriteContext, int32 ComponentOffset = 0)
: TComponentLockMixin<FScopedHeaderWriteLock>(InHeader, InLockMode, InWriteContext)
, TWrite<T>(InHeader, ComponentOffset)
{}
};
template<typename T>
struct TComponentLock<TWriteOptional<T>> : TComponentLockMixin<FScopedHeaderWriteLock>, TWriteOptional<T>
{
TComponentLock() = default;
explicit TComponentLock(const FComponentHeader* InHeader, EComponentHeaderLockMode InLockMode, FEntityAllocationWriteContext InWriteContext, int32 ComponentOffset = 0)
{
if (InHeader)
{
*static_cast<TComponentLockMixin<FScopedHeaderWriteLock>*>(this) = TComponentLockMixin<FScopedHeaderWriteLock>(InHeader, InLockMode, InWriteContext);
*static_cast<TWriteOptional<T>*>(this) = TWriteOptional<T>(InHeader, ComponentOffset);
}
}
};
using FComponentReader = TComponentLock<FReadErased>;
using FOptionalComponentReader = TComponentLock<FReadErasedOptional>;
using FComponentWriter = TComponentLock<FWriteErased>;
using FOptionalComponentWriter = TComponentLock<FWriteErasedOptional>;
template<typename T> using TComponentReader = TComponentLock<TRead<T>>;
template<typename T> using TOptionalComponentReader = TComponentLock<TReadOptional<T>>;
template<typename T> using TComponentWriter = TComponentLock<TWrite<T>>;
template<typename T> using TOptionalComponentWriter = TComponentLock<TWriteOptional<T>>;
template<typename... T> using TMultiComponentLock = TTuple<TComponentLock<T>...>;
template<typename... T>
struct TMultiComponentData
{
TMultiComponentData(T... InData)
: Data(InData...)
{}
TMultiComponentData(const TMultiComponentLock<T...>& InAggregateLock)
{
auto Init = [](const auto& InLock, auto& OutData)
{
if (InLock)
{
OutData = InLock;
}
};
VisitTupleElements(Init, InAggregateLock, this->Data);
}
template<int Index>
auto* Get() const
{
return Data.template Get<Index>().AsPtr();
}
template<int Index>
auto GetAsArray(int32 ArraySize) const
{
auto* ComponentPtr = Data.template Get<Index>().AsPtr();
return MakeArrayView(ComponentPtr, ComponentPtr ? ArraySize : 0);
}
private:
TTuple<T...> Data;
};
template<typename... T> using TMultiReadOptional = TMultiComponentData<TReadOptional<T>...>;
template<typename... T> using TReadOneOrMoreOf = TMultiComponentData<TReadOptional<T>...>;
template<typename... T> using TReadOneOf = TMultiComponentData<TReadOptional<T>...>;
} // namespace UE
} // namespace MovieScene