Files
UnrealEngine/Engine/Source/Runtime/Datasmith/DirectLink/Private/DirectLinkParameterStore.cpp
2025-05-18 13:04:45 +08:00

171 lines
4.6 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "DirectLinkParameterStore.h"
#include "DirectLinkLog.h"
#include "DirectLinkSceneGraphNode.h"
#include "Serialization/MemoryReader.h"
#include "Serialization/MemoryWriter.h"
#include "Templates/UnrealTemplate.h"
namespace DirectLink
{
// -- ps4 fix --
// Fix for a modular build on PS4 platform, where orbis-ld requires the following symbols to be
// accessible when compiling DatasmithCore as a shared object.
// Generated methods are not enough somehow, so they are explicitely defined here, in the cpp,
// which fixes the visibility issue.
FParameterStore::FParameterStore() = default;
FParameterStore::~FParameterStore() = default;
FParameterStore::FParameterStore(const FParameterStore&) = default;
FParameterStore& FParameterStore::operator=(const FParameterStore&) = default;
FParameterStore::FParameterStore(FParameterStore&&) = default;
FParameterStore& FParameterStore::operator=(FParameterStore&&) = default;
// -- end ps4 fix --
uint32 FParameterStore::GetParameterCount() const
{
return Parameters.Num();
}
int32 FParameterStore::GetParameterIndex(FName Name) const
{
return Parameters.IndexOfByPredicate([&](const FParameterDetails& Parameter) {
return Parameter.Name == Name;
});
}
bool FParameterStore::HasParameterNamed(FName Name) const
{
return GetParameterIndex(Name) != INDEX_NONE;
}
FName FParameterStore::GetParameterName(int32 Index) const
{
check(Parameters.IsValidIndex(Index));
return Parameters[Index].Name;
}
FParameterStoreSnapshot FParameterStore::Snapshot() const
{
FParameterStoreSnapshot Snap;
Snap.ReserveParamCount(GetParameterCount());
for (const FParameterStore::FParameterDetails& ParamDetails : Parameters)
{
Snap.AddParam(
ParamDetails.Name,
ParamDetails.StorageMethod,
ParamDetails.StorageLocation
);
}
return Snap;
}
void FParameterStore::Update(const FParameterStoreSnapshot& NewValues)
{
for (const FParameterStoreSnapshot::FParameterDetails& ParamUpdate : NewValues.Parameters)
{
int32 Index = GetParameterIndex(ParamUpdate.Name);
if (Parameters.IsValidIndex(Index))
{
if (ensure(Reflect::GetStoreType(ParamUpdate.StorageMethod) == Reflect::GetStoreType(Parameters[Index].StorageMethod)))
{
FMemoryReader Ar(ParamUpdate.Buffer);
Reflect::SerialAny(Ar, Parameters[Index].StorageLocation, ParamUpdate.StorageMethod);
}
else
{
UE_LOG(LogDirectLink, Warning, TEXT("Update property issue [%s]: incompatible types."), *ParamUpdate.Name.ToString());
}
}
}
}
struct FTempBacktrack : FNoncopyable
{
FTempBacktrack(FArchive& Ar, int64 TempLocation)
: Ar(Ar)
{
RestoreLocation = Ar.Tell();
Ar.Seek(TempLocation);
}
~FTempBacktrack()
{
Ar.Seek(RestoreLocation);
}
private:
FArchive& Ar;
uint64 RestoreLocation;
};
void FParameterStoreSnapshot::SerializeAll(FArchive& Ar)
{
// Note: Changes to this implementation impacts version handling
// see DirectLink::GetCurrentProtocolVersion and DirectLink::GetMinSupportedProtocolVersion
if (Ar.IsSaving())
{
uint32 ParamCount = Parameters.Num();
Ar.SerializeIntPacked(ParamCount);
for (FParameterStoreSnapshot::FParameterDetails& Parameter : Parameters)
{
Ar << Parameter.Name;
Ar << Parameter.StorageMethod;
uint32 BufferSize = Parameter.Buffer.Num();
Ar.SerializeIntPacked(BufferSize);
Ar.Serialize(Parameter.Buffer.GetData(), BufferSize);
}
}
else
{
uint32 ParamCount = 0;
Ar.SerializeIntPacked(ParamCount);
Parameters.Reserve(ParamCount);
for (uint32 i = 0; i < ParamCount; ++i)
{
FParameterStoreSnapshot::FParameterDetails& Parameter = Parameters.AddDefaulted_GetRef();
Ar << Parameter.Name;
Ar << Parameter.StorageMethod;
uint32 BufferSize = 0;
Ar.SerializeIntPacked(BufferSize);
Parameter.Buffer.SetNumUninitialized(BufferSize);
Ar.Serialize(Parameter.Buffer.GetData(), BufferSize);
}
}
}
void FParameterStoreSnapshot::AddParam(FName Name, Reflect::ESerialMethod StorageMethod, void* StorageLocation)
{
FParameterDetails& SnapParam = Parameters.AddDefaulted_GetRef();
SnapParam.Name = Name;
SnapParam.StorageMethod = StorageMethod;
FMemoryWriter Ar(SnapParam.Buffer);
Reflect::SerialAny(Ar, StorageLocation, StorageMethod);
// #ue_directlink_optim: measures shows a mean alloc size of <20 bytes...
// one buffer per property is clearly an aweful structure perfwise.
// one buffer for the whole store could be a solution
}
FElementHash FParameterStoreSnapshot::Hash() const
{
FElementHash RunningHash = 0;
for (const FParameterDetails& P : Parameters)
{
RunningHash = FCrc::MemCrc32(P.Buffer.GetData(), P.Buffer.Num(), RunningHash);
}
return RunningHash;
}
} // namespace DirectLink