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

170 lines
7.4 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "Containers/Array.h"
#include "CoreTypes.h"
#include "Math/Quat.h"
#include "Math/Transform.h"
#include "Math/Vector.h"
#include "Misc/SecureHash.h"
#include "Serialization/Archive.h"
namespace Reflect
{
// clang-format off
enum EStoreType : uint8
{
_bool = 1,
_i8, _i16, _i32, _i64,
_u8, _u16, _u32, _u64,
_f32, _f64,
_str,
_vector, _vector4, _quat,
_linearcolor,
_md5hash,
_transform,
_storeTypeLast
};
enum ESerialModifier : uint8
{
_default = 0 << 5,
_array = 1 << 5,
_alt1 = 2 << 5,
};
static constexpr uint8 _storeTypeMask = 0b0001'1111u;
static constexpr uint8 _modifierMask = 0b1110'0000u;
static_assert((_storeTypeLast & _modifierMask) == 0, "enum overlap");
enum class ESerialMethod : uint8
{
None = 0,
Bool_Default = _bool | _default,
Uint8_Default = _u8 | _default,
Int32_Default = _i32 | _default,
Int32_Array = _i32 | _array,
Uint32_Default = _u32 | _default,
Uint64_Default = _u64 | _default,
Uint32_Packed = _u32 | _alt1,
String_Default = _str | _default,
String_Array = _str | _array,
Float_Default = _f32 | _default,
Float_Array = _f32 | _array,
Double_Default = _f64 | _default,
Vector_f32 = _vector | _default, // FVector serialized as FVector3f
Vector_f64 = _vector | _alt1, // FVector serialized as FVector3d (native since 5.0)
Quat_f32 = _quat | _default, // FQuat serialized as FQuat4f
Quat_f64 = _quat | _alt1, // FQuat serialized as FQuat4d (native since 5.0)
LinearColor_Default= _linearcolor| _default,
MD5Hash_Default = _md5hash | _default,
Transform_Default = _transform | _default, // Added in 5.0, uses LWC.
Transform_Array = _transform | _array, // Added in 5.0, uses LWC.
_NotImplementedYet = 0xff
};
static constexpr EStoreType GetStoreType(ESerialMethod Method) { return EStoreType(uint8(Method) & _storeTypeMask); }
// This list maps which serialization method should be used for each Type reflected by directlink
template<typename T> struct TDefaultSerialMethod { constexpr static ESerialMethod Value = ESerialMethod::_NotImplementedYet; };
template<> struct TDefaultSerialMethod<bool> { constexpr static ESerialMethod Value = ESerialMethod::Uint8_Default; };
template<> struct TDefaultSerialMethod<uint8> { constexpr static ESerialMethod Value = ESerialMethod::Uint8_Default; };
template<> struct TDefaultSerialMethod<int32> { constexpr static ESerialMethod Value = ESerialMethod::Int32_Default; };
template<> struct TDefaultSerialMethod<uint32> { constexpr static ESerialMethod Value = ESerialMethod::Uint32_Default; };
template<> struct TDefaultSerialMethod<uint64> { constexpr static ESerialMethod Value = ESerialMethod::Uint64_Default; };
template<> struct TDefaultSerialMethod<FString> { constexpr static ESerialMethod Value = ESerialMethod::String_Default; };
template<> struct TDefaultSerialMethod<float> { constexpr static ESerialMethod Value = ESerialMethod::Float_Default; };
template<> struct TDefaultSerialMethod<double> { constexpr static ESerialMethod Value = ESerialMethod::Double_Default; };
template<> struct TDefaultSerialMethod<TArray<int32>> { constexpr static ESerialMethod Value = ESerialMethod::Int32_Array; };
template<> struct TDefaultSerialMethod<TArray<FString>> { constexpr static ESerialMethod Value = ESerialMethod::String_Array; };
template<> struct TDefaultSerialMethod<TArray<float>> { constexpr static ESerialMethod Value = ESerialMethod::Float_Array; };
template<> struct TDefaultSerialMethod<FLinearColor> { constexpr static ESerialMethod Value = ESerialMethod::LinearColor_Default;};
template<> struct TDefaultSerialMethod<FMD5Hash> { constexpr static ESerialMethod Value = ESerialMethod::MD5Hash_Default; };
template<> struct TDefaultSerialMethod<FTransform> { constexpr static ESerialMethod Value = ESerialMethod::Transform_Default; };
template<> struct TDefaultSerialMethod<TArray<FTransform>> { constexpr static ESerialMethod Value = ESerialMethod::Transform_Array; };
template<> struct TDefaultSerialMethod<FVector> { constexpr static ESerialMethod Value = ESerialMethod::Vector_f64; };
template<> struct TDefaultSerialMethod<FQuat> { constexpr static ESerialMethod Value = ESerialMethod::Quat_f64; };
template<typename T> EStoreType GetStoreTypeForType() { return GetStoreType(TDefaultSerialMethod<T>::Value); }
template<typename T> bool CanSerializeWithMethod(ESerialMethod Method) { return GetStoreTypeForType<T>() == GetStoreType(Method); }
// Serialization implementations
template<ESerialMethod Code, typename T>
void Serial(FArchive& Ar, T* Param) { Ar << *Param; }
template<> inline void Serial<ESerialMethod::Uint32_Packed>(FArchive& Ar, uint32* ValuePtr) { Ar.SerializeIntPacked(*ValuePtr); }
template<> inline void Serial<ESerialMethod::Vector_f32>(FArchive& Ar, FVector* ValuePtr)
{
if (Ar.IsLoading())
{
FVector3f Tmp;
Ar << Tmp;
*ValuePtr = FVector(Tmp);
}
else if (Ar.IsSaving())
{
FVector3f Tmp(*ValuePtr);
Ar << Tmp;
}
}
template<> inline void Serial<ESerialMethod::Quat_f32>(FArchive& Ar, FQuat* ValuePtr)
{
if (Ar.IsLoading())
{
FQuat4f Tmp;
Ar << Tmp;
*ValuePtr = FQuat(Tmp);
}
else if (Ar.IsSaving())
{
FQuat4f Tmp(*ValuePtr);
Ar << Tmp;
}
}
inline bool SerialAny(FArchive& Ar, void* data, ESerialMethod Method)
{
#define SerialAny_Case(enumvalue, casttype) case enumvalue: Serial<enumvalue>(Ar, (casttype*)data); return true;
switch (Method)
{
SerialAny_Case(ESerialMethod::Bool_Default , bool );
SerialAny_Case(ESerialMethod::Uint8_Default , uint8 );
SerialAny_Case(ESerialMethod::Int32_Default , int32 );
SerialAny_Case(ESerialMethod::Uint32_Default , uint32 );
SerialAny_Case(ESerialMethod::Uint64_Default , uint64 );
SerialAny_Case(ESerialMethod::Uint32_Packed , uint32 );
SerialAny_Case(ESerialMethod::String_Default , FString );
SerialAny_Case(ESerialMethod::Double_Default , double );
SerialAny_Case(ESerialMethod::Float_Default , float );
SerialAny_Case(ESerialMethod::Int32_Array , TArray<int32> );
SerialAny_Case(ESerialMethod::String_Array , TArray<FString> );
SerialAny_Case(ESerialMethod::Float_Array , TArray<float> );
SerialAny_Case(ESerialMethod::Vector_f32 , FVector );
SerialAny_Case(ESerialMethod::Vector_f64 , FVector );
SerialAny_Case(ESerialMethod::Quat_f32 , FQuat );
SerialAny_Case(ESerialMethod::Quat_f64 , FQuat );
SerialAny_Case(ESerialMethod::LinearColor_Default, FLinearColor );
SerialAny_Case(ESerialMethod::MD5Hash_Default , FMD5Hash );
SerialAny_Case(ESerialMethod::Transform_Default , FTransform );
SerialAny_Case(ESerialMethod::Transform_Array , TArray<FTransform>);
case ESerialMethod::None: return true;
case ESerialMethod::_NotImplementedYet:
default: ensure(false);
}
return false;
#undef SerialAny_Case
}
} // namespace Reflect