// 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 struct TDefaultSerialMethod { constexpr static ESerialMethod Value = ESerialMethod::_NotImplementedYet; }; template<> struct TDefaultSerialMethod { constexpr static ESerialMethod Value = ESerialMethod::Uint8_Default; }; template<> struct TDefaultSerialMethod { constexpr static ESerialMethod Value = ESerialMethod::Uint8_Default; }; template<> struct TDefaultSerialMethod { constexpr static ESerialMethod Value = ESerialMethod::Int32_Default; }; template<> struct TDefaultSerialMethod { constexpr static ESerialMethod Value = ESerialMethod::Uint32_Default; }; template<> struct TDefaultSerialMethod { constexpr static ESerialMethod Value = ESerialMethod::Uint64_Default; }; template<> struct TDefaultSerialMethod { constexpr static ESerialMethod Value = ESerialMethod::String_Default; }; template<> struct TDefaultSerialMethod { constexpr static ESerialMethod Value = ESerialMethod::Float_Default; }; template<> struct TDefaultSerialMethod { constexpr static ESerialMethod Value = ESerialMethod::Double_Default; }; template<> struct TDefaultSerialMethod> { constexpr static ESerialMethod Value = ESerialMethod::Int32_Array; }; template<> struct TDefaultSerialMethod> { constexpr static ESerialMethod Value = ESerialMethod::String_Array; }; template<> struct TDefaultSerialMethod> { constexpr static ESerialMethod Value = ESerialMethod::Float_Array; }; template<> struct TDefaultSerialMethod { constexpr static ESerialMethod Value = ESerialMethod::LinearColor_Default;}; template<> struct TDefaultSerialMethod { constexpr static ESerialMethod Value = ESerialMethod::MD5Hash_Default; }; template<> struct TDefaultSerialMethod { constexpr static ESerialMethod Value = ESerialMethod::Transform_Default; }; template<> struct TDefaultSerialMethod> { constexpr static ESerialMethod Value = ESerialMethod::Transform_Array; }; template<> struct TDefaultSerialMethod { constexpr static ESerialMethod Value = ESerialMethod::Vector_f64; }; template<> struct TDefaultSerialMethod { constexpr static ESerialMethod Value = ESerialMethod::Quat_f64; }; template EStoreType GetStoreTypeForType() { return GetStoreType(TDefaultSerialMethod::Value); } template bool CanSerializeWithMethod(ESerialMethod Method) { return GetStoreTypeForType() == GetStoreType(Method); } // Serialization implementations template void Serial(FArchive& Ar, T* Param) { Ar << *Param; } template<> inline void Serial(FArchive& Ar, uint32* ValuePtr) { Ar.SerializeIntPacked(*ValuePtr); } template<> inline void Serial(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(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(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 ); SerialAny_Case(ESerialMethod::String_Array , TArray ); SerialAny_Case(ESerialMethod::Float_Array , TArray ); 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); case ESerialMethod::None: return true; case ESerialMethod::_NotImplementedYet: default: ensure(false); } return false; #undef SerialAny_Case } } // namespace Reflect