// Copyright Epic Games, Inc. All Rights Reserved. #include "DNAUtils.h" #include "CoreMinimal.h" #include "Misc/FileHelper.h" #include "HAL/LowLevelMemTracker.h" #include "DNACommon.h" #include "DNAAsset.h" #include "DNAReaderAdapter.h" #include "FMemoryResource.h" #include "RigLogicMemoryStream.h" #include "riglogic/RigLogic.h" dna::DataLayer CalculateDNADataLayerBitmask(EDNADataLayer Layer) { dna::DataLayer mask = static_cast(Layer); if ((Layer & EDNADataLayer::RBFBehavior) == EDNADataLayer::RBFBehavior) { mask = mask | dna::DataLayer::JointBehaviorMetadata; mask = mask | dna::DataLayer::TwistSwingBehavior; } return mask; } static TSharedPtr ReadDNAStream(rl4::ScopedPtr DNAStreamReader) { DNAStreamReader->read(); if (!rl4::Status::isOk()) { UE_LOG(LogDNAReader, Error, TEXT("%s"), ANSI_TO_TCHAR(rl4::Status::get().message)); return nullptr; } return MakeShared>(DNAStreamReader.release()); } TSharedPtr ReadDNAFromFile(const FString& Path, EDNADataLayer Layer, uint16_t MaxLOD) { LLM_SCOPE_BYNAME(TEXT("Animation/RigLogic")); auto DNAFileStream = rl4::makeScoped(TCHAR_TO_UTF8(*Path), rl4::MemoryMappedFileStream::AccessMode::Read, FMemoryResource::Instance()); auto DNAStreamReader = rl4::makeScoped(DNAFileStream.get(), CalculateDNADataLayerBitmask(Layer), dna::UnknownLayerPolicy::Preserve, MaxLOD, FMemoryResource::Instance()); return ReadDNAStream(MoveTemp(DNAStreamReader)); } TSharedPtr ReadDNAFromFile(const FString& Path, EDNADataLayer Layer, TArrayView LODs) { LLM_SCOPE_BYNAME(TEXT("Animation/RigLogic")); auto DNAFileStream = rl4::makeScoped(TCHAR_TO_UTF8(*Path), rl4::MemoryMappedFileStream::AccessMode::Read, FMemoryResource::Instance()); auto DNAStreamReader = rl4::makeScoped(DNAFileStream.get(), CalculateDNADataLayerBitmask(Layer), dna::UnknownLayerPolicy::Preserve, LODs.GetData(), static_cast(LODs.Num()), FMemoryResource::Instance()); return ReadDNAStream(MoveTemp(DNAStreamReader)); } TSharedPtr ReadDNAFromBuffer(TArray* DNABuffer, EDNADataLayer Layer, uint16_t MaxLOD) { LLM_SCOPE_BYNAME(TEXT("Animation/RigLogic")); FRigLogicMemoryStream DNAMemoryStream(DNABuffer); auto DNAStreamReader = rl4::makeScoped(&DNAMemoryStream, CalculateDNADataLayerBitmask(Layer), dna::UnknownLayerPolicy::Preserve, MaxLOD, FMemoryResource::Instance()); return ReadDNAStream(MoveTemp(DNAStreamReader)); } TSharedPtr ReadDNAFromBuffer(TArray* DNABuffer, EDNADataLayer Layer, TArrayView LODs) { LLM_SCOPE_BYNAME(TEXT("Animation/RigLogic")); FRigLogicMemoryStream DNAMemoryStream(DNABuffer); auto DNAStreamReader = rl4::makeScoped(&DNAMemoryStream, CalculateDNADataLayerBitmask(Layer), dna::UnknownLayerPolicy::Preserve, LODs.GetData(), static_cast(LODs.Num()), FMemoryResource::Instance()); return ReadDNAStream(MoveTemp(DNAStreamReader)); } TArray ReadStreamFromDNA(const IDNAReader* Reader, EDNADataLayer Layer) { LLM_SCOPE_BYNAME(TEXT("Animation/RigLogic")); TArray DNABuffer; auto DeltaDnaStream = rl4::makeScoped(); auto DNAStreamWriter = rl4::makeScoped(DeltaDnaStream.get(), FMemoryResource::Instance()); DNAStreamWriter->setFrom(Reader->Unwrap(), CalculateDNADataLayerBitmask(Layer), dna::UnknownLayerPolicy::Preserve, FMemoryResource::Instance()); DNAStreamWriter->write(); DNABuffer.AddZeroed(DeltaDnaStream->size()); DeltaDnaStream->read(DNABuffer.GetData(), DeltaDnaStream->size()); return TArray(DNABuffer); } void WriteDNAToFile(const IDNAReader* Reader, EDNADataLayer Layer, const FString& Path) { LLM_SCOPE_BYNAME(TEXT("Animation/RigLogic")); auto DNAFileStream = rl4::makeScoped(TCHAR_TO_UTF8(*Path), rl4::FileStream::AccessMode::Write, rl4::FileStream::OpenMode::Binary, FMemoryResource::Instance()); auto DNAStreamWriter = rl4::makeScoped(DNAFileStream.get(), FMemoryResource::Instance()); DNAStreamWriter->setFrom(Reader->Unwrap(), CalculateDNADataLayerBitmask(Layer), dna::UnknownLayerPolicy::Preserve, FMemoryResource::Instance()); DNAStreamWriter->write(); } TObjectPtr GetDNAAssetFromFile(const FString& InFilePath, UObject* InOuter, EDNADataLayer InLayer) { UDNAAsset* DNAAsset = nullptr; TArray DNADataAsBuffer; if (FFileHelper::LoadFileToArray(DNADataAsBuffer, *InFilePath)) { if (TSharedPtr DNAReader = ReadDNAFromBuffer(&DNADataAsBuffer, InLayer)) { DNAAsset = NewObject(InOuter); DNAAsset->SetBehaviorReader(DNAReader); DNAAsset->SetGeometryReader(DNAReader); } } return DNAAsset; }