// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "HAL/Platform.h" #include "MuR/Ptr.h" #include "MuR/RefCounted.h" #include "MuR/MutableMath.h" #include "Curves/RichCurve.h" #include "Math/Vector.h" #include "Math/IntVector.h" #include "Math/Vector4.h" #include "Containers/Array.h" #include "Containers/Map.h" #include "Containers/ContainerAllocationPolicies.h" #include "Templates/SharedPointer.h" #include "UObject/StrongObjectPtr.h" class UTexture; class USkeletalMesh; #define UE_API MUTABLERUNTIME_API namespace mu { class FImage; class FModel; enum class EDataType : uint8; #define MUTABLE_DEFINE_POD_SERIALISABLE(Type) \ void DLLEXPORT operator<<(mu::FOutputArchive& Arch, const Type& T); \ void DLLEXPORT operator>>(mu::FInputArchive& Arch, Type& T); #define MUTABLE_DEFINE_POD_VECTOR_SERIALISABLE(Type) \ template \ void DLLEXPORT operator<<(mu::FOutputArchive& Arch, const TArray& V); \ template \ void DLLEXPORT operator>>(mu::FInputArchive& Arch, TArray& V); #define MUTABLE_DEFINE_ENUM_SERIALISABLE(Type) \ void DLLEXPORT operator<<(mu::FOutputArchive& Arch, const Type& T); \ void DLLEXPORT operator>>(mu::FInputArchive& Arch, Type& T); /** This repesents a handle to Mutable resource. */ template class TResourceProxy : public RefCounted { public: virtual TSharedPtr Get() = 0; }; /** Proxy implementation that always has the resource loaded in memory. */ template class TResourceProxyMemory : public TResourceProxy { private: TSharedPtr Resource; public: TResourceProxyMemory(const TSharedPtr& InResource) { Resource = InResource; } // TResourceProxy interface TSharedPtr Get() override { return Resource; } }; /** */ class FModelReader { public: //----------------------------------------------------------------------------------------- // Life cycle //----------------------------------------------------------------------------------------- //! Ensure virtual destruction. virtual ~FModelReader() {} //----------------------------------------------------------------------------------------- // Reading interface //----------------------------------------------------------------------------------------- //! Identifier of reading data operations sent to this interface. //! Negative values indicate an error. typedef int32 FOperationID; virtual bool DoesBlockExist(const FModel*, uint32 BlockKey) = 0; //! \brief Start a data request operation. //! \param Model. //! \param BlockKey key identifying the model data fragment that is requested. //! This key interpretation depends on the implementation of the ModelStreamer, //! \param Buffer is an already-allocated buffer big enough to receive the expected data. //! \param size is the size of the pBuffer buffer, which must match the size of the data //! requested with the key identifiers. //! \param CompletionCallback Optional callback. Copied inside the called function. Will always be called. //! \return a previously unused identifier, now used for this operation, that can be used in //! calls to the other methods of this interface. If the return value is negative it indicates //! an unrecoverable error. virtual FOperationID BeginReadBlock(const FModel*, uint32 BlockKey, void* Buffer, uint64 Size, EDataType DataType, TFunction* CompletionCallback = nullptr) = 0; //! Check if a data request operation has been completed. //! This is a weak check than *may* return true if the given operation has completed, but //! it is not mandatory. It is used as a hint by the System to optimise its opertaions. //! There is no guarantee that this method will ever be called, and it is safe to always //! return false. virtual bool IsReadCompleted(FOperationID) = 0; /** Complete a data request operation.This method has to block until a data request issued * with BeginReadBlock has been completed. After returning from this call, the ID cannot be used * any more to identify the same operation and becomes free. * \return true if the data was loaded successfully. */ virtual bool EndRead(FOperationID) = 0; }; /** */ class FModelWriter { public: //----------------------------------------------------------------------------------------- // Life cycle //----------------------------------------------------------------------------------------- //! Ensure virtual destruction. virtual ~FModelWriter() {} //----------------------------------------------------------------------------------------- // Writing interface //----------------------------------------------------------------------------------------- /** */ virtual void OpenWriteFile(uint32 BlockKey, bool bIsStreamable) = 0; /** */ virtual void Write(const void* Buffer, uint64 Size) = 0; //! \brief Close the file open for writing in a previous call to OpenWriteFile in this //! object. virtual void CloseWriteFile() = 0; }; /** Interface for any input stream to be use with InputArchives. */ class FInputStream { public: /** Ensure virtual destruction. */ virtual ~FInputStream() {} /** Read a byte buffer * \param pData destination buffer, must have at least size bytes allocated. * \param size amount of bytes to read from the stream. */ virtual void Read( void* Data, uint64 Size ) = 0; }; /** Interface for any output stream to be used with OutputArchives. */ class FOutputStream { public: /** Ensure virtual destruction. */ virtual ~FOutputStream() {} /** Write a byte buffer * \param pData source buffer where data will be read from. * \param size amount of data to write to the stream. */ virtual void Write( const void* Data, uint64 Size ) = 0; }; /** Archive containing data to be deserialised. */ class FInputArchive { public: /** Construct form an input stream.The stream will not be owned by the archive and the * caller must make sure it is not modified or destroyed while serialisation is happening. */ UE_API FInputArchive( FInputStream* ); /** Ensure virtual destruction. */ virtual ~FInputArchive() {} // UE_API virtual Ptr> NewImageProxy(); /** Not owned. */ FInputStream* Stream = nullptr; /** Already read pointers. */ TArray< TSharedPtr > History; }; /** Archive where data can be serialised to. */ class FOutputArchive { public: /** Construct form an output stream.The stream will not be owned by the archive and the * caller must make sure it is not modified or destroyed while serialisation is happening. */ UE_API FOutputArchive( FOutputStream* ); /** Not owned. */ FOutputStream* Stream = nullptr; /** Already written pointers and their ids. */ TMap< const void*, int32 > History; }; //! class FOutputMemoryStream : public FOutputStream { public: /** Create the stream with an optional buffer size in bytes. * The internal buffer will be enlarged as much as necessary. */ UE_API FOutputMemoryStream( uint64 Reserve = 0 ); // FOutputStream interface UE_API virtual void Write( const void* Data, uint64 Size ) override; // Own interface /** Get the serialised data buffer pointer. This pointer invalidates after a Write * operation has been done, and you need to get it again. */ UE_API const uint8* GetBuffer() const; /** Get the amount of data in the stream, in bytes. */ UE_API int32 GetBufferSize() const; /** Clear the internal buffer. */ UE_API void Reset(); private: TArray64 Buffer; }; /** This stream doesn't store any data: it just counts the amount of data serialised. */ class FOutputSizeStream : public FOutputStream { public: // FOutputStream interface UE_API void Write(const void* Data, uint64 Size) override; // Own interface /** Get the amount of data serialised, in bytes. */ UE_API uint64 GetBufferSize() const; private: uint64 WrittenBytes = 0; }; /** This stream doesn't store any data: it just calculates of a hash of the data as it receives it. */ class FOutputHashStream : public FOutputStream { public: // FOutputStream interface UE_API void Write(const void* Data, uint64 Size) override; // Own interface /** Return the hash of the data written so far. */ UE_API uint64 GetHash() const; private: uint64 Hash = 0; }; template void operator<<(FOutputArchive& Arch, const Type& Value) { Value.Serialise(Arch); } template void operator>>(FInputArchive& Arch, Type& Value) { Value.Unserialise(Arch); } MUTABLE_DEFINE_POD_SERIALISABLE(float); MUTABLE_DEFINE_POD_SERIALISABLE(double); MUTABLE_DEFINE_POD_SERIALISABLE(int8); MUTABLE_DEFINE_POD_SERIALISABLE(int16); MUTABLE_DEFINE_POD_SERIALISABLE(int32); MUTABLE_DEFINE_POD_SERIALISABLE(int64); MUTABLE_DEFINE_POD_SERIALISABLE(uint8); MUTABLE_DEFINE_POD_SERIALISABLE(uint16); MUTABLE_DEFINE_POD_SERIALISABLE(uint32); MUTABLE_DEFINE_POD_SERIALISABLE(uint64); MUTABLE_DEFINE_POD_SERIALISABLE(FUintVector2); MUTABLE_DEFINE_POD_SERIALISABLE(FIntVector2); MUTABLE_DEFINE_POD_SERIALISABLE(UE::Math::TIntVector2); MUTABLE_DEFINE_POD_SERIALISABLE(UE::Math::TIntVector2); MUTABLE_DEFINE_POD_SERIALISABLE(FVector2f); MUTABLE_DEFINE_POD_SERIALISABLE(FVector4f); MUTABLE_DEFINE_POD_SERIALISABLE(FMatrix44f); MUTABLE_DEFINE_POD_SERIALISABLE(FRichCurveKey); MUTABLE_DEFINE_POD_SERIALISABLE(FGuid); MUTABLE_DEFINE_POD_VECTOR_SERIALISABLE(float); MUTABLE_DEFINE_POD_VECTOR_SERIALISABLE(double); MUTABLE_DEFINE_POD_VECTOR_SERIALISABLE(uint8); MUTABLE_DEFINE_POD_VECTOR_SERIALISABLE(uint16); MUTABLE_DEFINE_POD_VECTOR_SERIALISABLE(uint32); MUTABLE_DEFINE_POD_VECTOR_SERIALISABLE(uint64); MUTABLE_DEFINE_POD_VECTOR_SERIALISABLE(int8); MUTABLE_DEFINE_POD_VECTOR_SERIALISABLE(int16); MUTABLE_DEFINE_POD_VECTOR_SERIALISABLE(int32); MUTABLE_DEFINE_POD_VECTOR_SERIALISABLE(int64); MUTABLE_DEFINE_POD_VECTOR_SERIALISABLE(FVector2f); MUTABLE_DEFINE_POD_VECTOR_SERIALISABLE(FMatrix44f); MUTABLE_DEFINE_POD_VECTOR_SERIALISABLE(FIntVector2); MUTABLE_DEFINE_POD_VECTOR_SERIALISABLE(TCHAR); MUTABLE_DEFINE_POD_VECTOR_SERIALISABLE(FRichCurveKey); MUTABLE_DEFINE_POD_VECTOR_SERIALISABLE(FUintVector2); MUTABLE_DEFINE_POD_VECTOR_SERIALISABLE(UE::Math::TIntVector2); MUTABLE_DEFINE_POD_VECTOR_SERIALISABLE(UE::Math::TIntVector2); MUTABLE_DEFINE_POD_VECTOR_SERIALISABLE(FVector4f); //--------------------------------------------------------------------------------------------- MUTABLERUNTIME_API void operator<<(FOutputArchive&, const FString&); MUTABLERUNTIME_API void operator>>(FInputArchive&, FString&); //--------------------------------------------------------------------------------------------- MUTABLERUNTIME_API void operator<<(FOutputArchive&, const FRichCurve&); MUTABLERUNTIME_API void operator>>(FInputArchive&, FRichCurve&); //--------------------------------------------------------------------------------------------- MUTABLERUNTIME_API void operator<<(FOutputArchive&, const FName&); MUTABLERUNTIME_API void operator>>(FInputArchive&, FName&); //--------------------------------------------------------------------------------------------- template void operator<<(FOutputArchive& Arch, const TArray& V) { const uint32 Num = (uint32)V.Num(); Arch << Num; for (SIZE_T Index = 0; Index < Num; ++Index) { Arch << V[Index]; } } template void operator>>(FInputArchive& Arch, TArray& V) { uint32 Num; Arch >> Num; V.SetNum(Num); for (SIZE_T Index = 0; Index < Num; ++Index) { Arch >> V[Index]; } } // Bool size is not a standard MUTABLERUNTIME_API void operator<<(FOutputArchive&, const bool&); MUTABLERUNTIME_API void operator>>(FInputArchive&, bool&); // Do not serialize pointers to UObjects. template void operator<<(FOutputArchive& Arch, const TStrongObjectPtr& V) { // Do Nothing. UObjects values are saved in the CO. } template void operator>>(FInputArchive& Arch, TStrongObjectPtr& V) { // Do Nothing. UObjects values are saved in the CO. } } #undef UE_API