bool FPipeHandle::ReadToArray(TArray<uint8> & Output) { int BytesAvailable = 0; if (ioctl(PipeDesc, FIONREAD, &BytesAvailable) == 0) { if (BytesAvailable > 0) { Output.SetNumUninitialized(BytesAvailable); int BytesRead = read(PipeDesc, Output.GetData(), BytesAvailable); if (BytesRead > 0) { if (BytesRead < BytesAvailable) { Output.SetNum(BytesRead); } return true; } else { Output.Empty(); } } } return false; }
void UGameplayTagReponseTable::RegisterResponseForEvents(UAbilitySystemComponent* ASC) { if (RegisteredASCs.Contains(ASC)) { return; } TArray<FGameplayTagResponseAppliedInfo> AppliedInfoList; AppliedInfoList.SetNum(Entries.Num()); RegisteredASCs.Add(ASC, AppliedInfoList ); for (int32 idx=0; idx < Entries.Num(); ++idx) { const FGameplayTagResponseTableEntry& Entry = Entries[idx]; if (Entry.Positive.Tag.IsValid()) { ASC->RegisterGameplayTagEvent( Entry.Positive.Tag, EGameplayTagEventType::AnyCountChange ).AddUObject(this, &UGameplayTagReponseTable::TagResponseEvent, ASC, idx); } if (Entry.Negative.Tag.IsValid()) { ASC->RegisterGameplayTagEvent( Entry.Negative.Tag, EGameplayTagEventType::AnyCountChange ).AddUObject(this, &UGameplayTagReponseTable::TagResponseEvent, ASC, idx); } } }
TArray<uint8> UMasterServerFunctions::CompressBytes(FString UncompressedString) { TArray<uint8> UncompressedBinaryArray = FStringToBinaryArray(UncompressedString); TArray<uint8> CompressedBinaryArray; CompressedBinaryArray.SetNum(UncompressedBinaryArray.Num() * 1023, true); //int ret; z_stream strm; strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; strm.avail_in = UncompressedBinaryArray.Num(); strm.next_in = (Bytef *)UncompressedBinaryArray.GetData(); strm.avail_out = CompressedBinaryArray.Num(); strm.next_out = (Bytef *)CompressedBinaryArray.GetData(); // the actual compression work. deflateInit(&strm, Z_BEST_COMPRESSION); deflate(&strm, Z_FINISH); deflateEnd(&strm); // Shrink the array to minimum size CompressedBinaryArray.RemoveAt(strm.total_out, CompressedBinaryArray.Num() - strm.total_out, true); return CompressedBinaryArray; }
void FStreamableManager::RequestAsyncLoad(const TArray<FStringAssetReference>& TargetsToStream, FStreamableDelegate DelegateToCall) { // Schedule a new callback, this will get called when all related async loads are completed TSharedRef<FStreamableRequest> NewRequest = MakeShareable(new FStreamableRequest()); NewRequest->CompletionDelegate = DelegateToCall; TArray<FStreamable *> ExistingStreamables; ExistingStreamables.SetNum(TargetsToStream.Num()); for (int32 i = 0; i < TargetsToStream.Num(); i++) { FStreamable* Existing = StreamInternal(TargetsToStream[i]); ExistingStreamables[i] = Existing; if (Existing) { Existing->AddRelatedRequest(NewRequest); } } // Go through and complete loading anything that's already in memory, this may call the callback right away for (int32 i = 0; i < TargetsToStream.Num(); i++) { FStreamable* Existing = ExistingStreamables[i]; if (Existing && Existing->Target) { CheckCompletedRequests(TargetsToStream[i], Existing); } } }
void URuntimeMeshLibrary::CalculateTangentsForMesh(const TArray<FVector>& Vertices, const TArray<int32>& Triangles, TArray<FVector>& Normals, const TArray<FVector2D>& UVs, TArray<FRuntimeMeshTangent>& Tangents, bool bCreateSmoothNormals) { Normals.SetNum(Vertices.Num()); Tangents.SetNum(Vertices.Num()); CalculateTangentsForMesh( [&Triangles](int32 Index) -> int32 { return Triangles[Index]; }, [&Vertices](int32 Index) -> FVector { return Vertices[Index]; }, [&UVs](int32 Index) -> FVector2D { return UVs[Index]; }, [&Normals, &Tangents](int32 Index, FVector TangentX, FVector TangentY, FVector TangentZ) { Normals[Index] = TangentZ; Tangents[Index].TangentX = TangentX; Tangents[Index].bFlipTangentY = GetBasisDeterminantSign(TangentX, TangentY, TangentZ) < 0; }, Vertices.Num(), UVs.Num(), Triangles.Num(), bCreateSmoothNormals); }
bool FBuildPatchAppManifest::SaveToFile(const FString& Filename, bool bUseBinary) { bool bSuccess = false; FArchive* FileOut = IFileManager::Get().CreateFileWriter(*Filename); if (FileOut) { if (bUseBinary) { Data->ManifestFileVersion = EBuildPatchAppManifestVersion::GetLatestVersion(); FManifestWriter ManifestData; Serialize(ManifestData); ManifestData.Finalize(); if (!ManifestData.IsError()) { int32 DataSize = ManifestData.TotalSize(); TArray<uint8> TempCompressed; TempCompressed.AddUninitialized(DataSize); int32 CompressedSize = DataSize; bool bDataIsCompressed = FCompression::CompressMemory( static_cast<ECompressionFlags>(COMPRESS_ZLIB | COMPRESS_BiasMemory), TempCompressed.GetData(), CompressedSize, ManifestData.GetBytes().GetData(), DataSize); TempCompressed.SetNum(CompressedSize); TArray<uint8>& FileData = bDataIsCompressed ? TempCompressed : ManifestData.GetBytes(); FManifestFileHeader Header; *FileOut << Header; Header.HeaderSize = FileOut->Tell(); Header.StoredAs = bDataIsCompressed ? EManifestFileHeader::STORED_COMPRESSED : EManifestFileHeader::STORED_RAW; Header.DataSize = DataSize; Header.CompressedSize = bDataIsCompressed ? CompressedSize : 0; FSHA1::HashBuffer(FileData.GetData(), FileData.Num(), Header.SHAHash.Hash); FileOut->Seek(0); *FileOut << Header; FileOut->Serialize(FileData.GetData(), FileData.Num()); bSuccess = !FileOut->IsError(); } } else { Data->ManifestFileVersion = EBuildPatchAppManifestVersion::GetLatestJsonVersion(); FString JSONOutput; SerializeToJSON(JSONOutput); FTCHARToUTF8 JsonUTF8(*JSONOutput); FileOut->Serialize((UTF8CHAR*)JsonUTF8.Get(), JsonUTF8.Length() * sizeof(UTF8CHAR)); } FileOut->Close(); delete FileOut; FileOut = nullptr; } return bSuccess; }
TArray<int32> URuntimeMeshLibrary::GenerateTessellationIndexBuffer(const TArray<FVector>& Vertices, const TArray<int32>& Triangles, TArray<FVector>& Normals, const TArray<FVector2D>& UVs, TArray<FRuntimeMeshTangent>& Tangents) { TArray<int32> TessellationTriangles; FTessellationUtilities::CalculateTessellationIndices(Vertices.Num(), Triangles.Num(), [&Vertices](int32 Index) -> FVector { return Vertices[Index]; }, [&UVs](int32 Index) -> FVector2D { return UVs.Num() > Index ? UVs[Index] : FVector2D::ZeroVector; }, [&Triangles](int32 Index) -> int32 { return Triangles[Index]; }, [&TessellationTriangles](int32 NewSize) { TessellationTriangles.SetNum(NewSize); }, [&TessellationTriangles]() -> int32 { return TessellationTriangles.Num(); }, [&TessellationTriangles](int32 Index, int32 NewValue) { TessellationTriangles[Index] = NewValue; }, [&TessellationTriangles](int32 Index) -> int32 { return TessellationTriangles[Index]; }); return TessellationTriangles; }
TArray<int32> URuntimeMeshLibrary::GenerateTessellationIndexBufferPacked(const TArray<FRuntimeMeshBlueprintVertexSimple>& Vertices, const TArray<int32>& Triangles) { TArray<int32> TessellationTriangles; FTessellationUtilities::CalculateTessellationIndices(Vertices.Num(), Triangles.Num(), [&Vertices](int32 Index) -> FVector { return Vertices[Index].Position; }, [&Vertices](int32 Index) -> FVector2D { return Vertices[Index].UV0; }, [&Triangles](int32 Index) -> int32 { return Triangles[Index]; }, [&TessellationTriangles](int32 NewSize) { TessellationTriangles.SetNum(NewSize); }, [&TessellationTriangles]() -> int32 { return TessellationTriangles.Num(); }, [&TessellationTriangles](int32 Index, int32 NewValue) { TessellationTriangles[Index] = NewValue; }, [&TessellationTriangles](int32 Index) -> int32 { return TessellationTriangles[Index]; }); return TessellationTriangles; }
TArray<int32> URuntimeMeshLibrary::GenerateTessellationIndexBuffer(const TSharedPtr<FRuntimeMeshAccessor>& MeshAccessor) { TArray<int32> TessellationTriangles; FTessellationUtilities::CalculateTessellationIndices(MeshAccessor->NumVertices(), MeshAccessor->NumIndices(), [&MeshAccessor](int32 Index) -> FVector { return MeshAccessor->GetPosition(Index); }, [&MeshAccessor](int32 Index) -> FVector2D { return MeshAccessor->GetUV(Index); }, [&MeshAccessor](int32 Index) -> int32 { return MeshAccessor->GetIndex(Index); }, [&TessellationTriangles](int32 NewSize) { TessellationTriangles.SetNum(NewSize); }, [&TessellationTriangles]() -> int32 { return TessellationTriangles.Num(); }, [&TessellationTriangles](int32 Index, int32 NewValue) { TessellationTriangles[Index] = NewValue; }, [&TessellationTriangles](int32 Index) -> int32 { return TessellationTriangles[Index]; }); return TessellationTriangles; }
FString FHttpResponseWinInet::QueryHeaderString(uint32 HttpQueryInfoLevel, const FString& HeaderName) const { // try to use stack allocation where possible. ::DWORD HeaderSize = 0; TCHAR HeaderValue[128]; TArray<TCHAR> HeaderValueLong; TCHAR* HeaderValueReal = HeaderValue; if (!HttpQueryInfo(Request.RequestHandle, HttpQueryInfoLevel, const_cast<TCHAR*>(*HeaderName), &HeaderSize, NULL)) { uint32 ErrorCode = GetLastError(); if (ErrorCode == ERROR_HTTP_HEADER_NOT_FOUND) { return FString(); } else if (ErrorCode == ERROR_INSUFFICIENT_BUFFER) { // make sure we have enough room to supply the HeaderName and Value. If not, dynamically allocate. uint32 HeaderSizeChars = HeaderSize / sizeof(TCHAR) + 1; uint32 HeaderNameChars = HeaderName.Len() == 0 ? 0 : HeaderName.Len() + 1; if (HeaderSizeChars > ARRAYSIZE(HeaderValue) || HeaderNameChars > ARRAYSIZE(HeaderValue)) { // we have to create a dynamic allocation to hold the result. UE_LOG(LogHttp, Verbose, TEXT("Having to resize default buffer for retrieving header %s. Name length: %u. Value length: %u. %p"), *HeaderName, HeaderNameChars, HeaderSizeChars, &Request); uint32 NewBufferSizeChars = FMath::Max(HeaderSizeChars, HeaderNameChars); // Have to copy the HeaderName into the buffer as well for the API to work. if (HeaderName.Len() > 0) { HeaderValueLong = HeaderName.GetCharArray(); } // Set the size of the array to hold the entire value. HeaderValueLong.SetNum(NewBufferSizeChars); HeaderSize = NewBufferSizeChars * sizeof(TCHAR); HeaderValueReal = HeaderValueLong.GetData(); } else { // Use the stack allocated space if we have the room. FMemory::Memcpy(HeaderValue, *HeaderName, HeaderName.Len()*sizeof(TCHAR)); HeaderValue[HeaderName.Len()] = 0; } if (!HttpQueryInfo(Request.RequestHandle, HttpQueryInfoLevel, HeaderValueReal, &HeaderSize, NULL)) { UE_LOG(LogHttp, Warning, TEXT("HttpQueryInfo failed trying to get Header Value for Name %s: %s. %p"), *HeaderName, *InternetTranslateError(GetLastError()), &Request); return FString(); } } } return FString(HeaderValueReal); }
void SSpineWidget::Flush(int32 LayerId, FSlateWindowElementList& OutDrawElements, const FGeometry& AllottedGeometry, int &Idx, TArray<FVector> &Vertices, TArray<int32> &Indices, TArray<FVector2D> &Uvs, TArray<FColor> &Colors, TArray<FVector>& Colors2, UMaterialInstanceDynamic* Material) { if (Vertices.Num() == 0) return; SSpineWidget* self = (SSpineWidget*)this; self->renderData.IndexData.SetNumUninitialized(Indices.Num()); uint32* indexData = (uint32*)renderData.IndexData.GetData(); memcpy(indexData, Indices.GetData(), sizeof(uint32) * Indices.Num()); self->renderData.VertexData.SetNumUninitialized(Vertices.Num()); FSlateVertex* vertexData = (FSlateVertex*)renderData.VertexData.GetData(); FVector2D offset = AllottedGeometry.AbsolutePosition; FColor white = FColor(0xffffffff); float width = AllottedGeometry.GetAbsoluteSize().X; float height = AllottedGeometry.GetAbsoluteSize().Y; for (size_t i = 0; i < (size_t)Vertices.Num(); i++) { setVertex(&vertexData[i], Vertices[i].X, Vertices[i].Y, Uvs[i].X, Uvs[i].Y, Colors[i], offset); } /*FSlateBrush brush; brush.SetResourceObject(Material); brush = widget->Brush; FSlateShaderResourceProxy* shaderResource = FSlateDataPayload::ResourceManager->GetShaderResource(brush); if (shaderResource) { FSlateResourceHandle resourceHandle = FSlateApplication::Get().GetRenderer()->GetResourceHandle(brush); FSlateDrawElement::MakeCustomVerts(OutDrawElements, LayerId, resourceHandle, renderData.VertexData, renderData.IndexData, nullptr, 0, 0); }*/ Vertices.SetNum(0); Indices.SetNum(0); Uvs.SetNum(0); Colors.SetNum(0); Colors2.SetNum(0); Idx++; }
void URuntimeMeshLibrary::GetStaticMeshSection(UStaticMesh* InMesh, int32 LODIndex, int32 SectionIndex, TArray<FVector>& Vertices, TArray<int32>& Triangles, TArray<FVector>& Normals, TArray<FVector2D>& UVs, TArray<FColor>& Colors, TArray<FRuntimeMeshTangent>& Tangents) { Vertices.Empty(); Triangles.Empty(); Normals.Empty(); UVs.Empty(); Colors.Empty(); Tangents.Empty(); GetStaticMeshSection(InMesh, LODIndex, SectionIndex, 1, [&Vertices, &Normals, &Tangents](FVector Position, FVector TangentX, FVector TangentY, FVector TangentZ) -> int32 { int32 NewIndex = Vertices.Add(Position); Normals.Add(TangentZ); Tangents.Add(FRuntimeMeshTangent(TangentX, GetBasisDeterminantSign(TangentX, TangentY, TangentZ) < 0)); return NewIndex; }, [&UVs](int32 Index, int32 UVIndex, FVector2D UV) { check(UVIndex == 0); UVs.SetNum(Index + 1); UVs[Index] = UV; }, [&Colors](int32 Index, FColor Color) { Colors.SetNum(Index + 1); Colors[Index] = Color; }, [&Triangles](int32 Index) { Triangles.Add(Index); }, [](int32 Index) { }); }
void URuntimeMeshLibrary::CopyStaticMeshToRuntimeMesh(UStaticMeshComponent* StaticMeshComponent, int32 LODIndex, URuntimeMesh* RuntimeMesh, bool bCreateCollision) { SCOPE_CYCLE_COUNTER(STAT_RuntimeMeshLibrary_CopyStaticMeshToRuntimeMesh); if (StaticMeshComponent != nullptr && StaticMeshComponent->GetStaticMesh() != nullptr && RuntimeMesh != nullptr) { UStaticMesh* StaticMesh = StaticMeshComponent->GetStaticMesh(); RuntimeMesh->ClearAllMeshSections(); //// MESH DATA int32 NumSections = StaticMesh->GetNumSections(LODIndex); for (int32 SectionIndex = 0; SectionIndex < NumSections; SectionIndex++) { // Buffers for copying geom data TSharedPtr<FRuntimeMeshBuilder> MeshData = MakeRuntimeMeshBuilder<FRuntimeMeshTangents, FVector2DHalf, uint32>(); TArray<uint8> AdjacencyTrianglesData; TSharedPtr<FRuntimeMeshIndicesAccessor> AdjacencyTrianglesAccessor = MakeShared<FRuntimeMeshIndicesAccessor>(true, &AdjacencyTrianglesData); TArray<uint32> AdjacencyTriangles; AdjacencyTriangles.SetNum(AdjacencyTrianglesData.Num() / 4); FMemory::Memcpy(AdjacencyTriangles.GetData(), AdjacencyTrianglesData.GetData(), AdjacencyTrianglesData.Num()); // TODO: Make this smarter to setup a mesh section to match the static mesh vertex configuration // This will let it pick up the additional UVs or high pri normals/tangents/uvs // Get geom data from static mesh GetStaticMeshSection(StaticMesh, LODIndex, SectionIndex, MeshData, AdjacencyTrianglesAccessor); // Create RuntimeMesh RuntimeMesh->CreateMeshSection(SectionIndex, MeshData, bCreateCollision); RuntimeMesh->SetSectionTessellationTriangles(SectionIndex, AdjacencyTriangles); } //// SIMPLE COLLISION CopyCollisionFromStaticMesh(StaticMesh, RuntimeMesh); //// MATERIALS for (int32 MatIndex = 0; MatIndex < StaticMeshComponent->GetNumMaterials(); MatIndex++) { RuntimeMesh->SetSectionMaterial(MatIndex, StaticMeshComponent->GetMaterial(MatIndex)); } } }
bool ResamplePCM(uint32 NumChannels, const TArray<uint8>& InBuffer, uint32 InSampleRate, TArray<uint8>& OutBuffer, uint32 OutSampleRate) const { // Initialize resampler to convert to desired rate for Opus int32 err = 0; SpeexResamplerState* resampler = speex_resampler_init(NumChannels, InSampleRate, OutSampleRate, SPEEX_RESAMPLER_QUALITY_DESKTOP, &err); if (err != RESAMPLER_ERR_SUCCESS) { speex_resampler_destroy(resampler); return false; } // Calculate extra space required for sample rate const uint32 SampleStride = SAMPLE_SIZE * NumChannels; const float Duration = (float)InBuffer.Num() / (InSampleRate * SampleStride); const int32 SafeCopySize = (Duration + 1) * OutSampleRate * SampleStride; OutBuffer.Empty(SafeCopySize); OutBuffer.AddUninitialized(SafeCopySize); uint32 InSamples = InBuffer.Num() / SampleStride; uint32 OutSamples = OutBuffer.Num() / SampleStride; // Do resampling and check results if (NumChannels == 1) { err = speex_resampler_process_int(resampler, 0, (const short*)(InBuffer.GetData()), &InSamples, (short*)(OutBuffer.GetData()), &OutSamples); } else { err = speex_resampler_process_interleaved_int(resampler, (const short*)(InBuffer.GetData()), &InSamples, (short*)(OutBuffer.GetData()), &OutSamples); } speex_resampler_destroy(resampler); if (err != RESAMPLER_ERR_SUCCESS) { return false; } // reduce the size of Out Buffer if more space than necessary was allocated const int32 WrittenBytes = (int32)(OutSamples * SampleStride); if (WrittenBytes < OutBuffer.Num()) { OutBuffer.SetNum(WrittenBytes, true); } return true; }
FConstructorStatics() { VisemeNames.SetNum(ovrLipSyncViseme::VisemesCount); VisemeNames[ovrLipSyncViseme::sil] = "sil"; VisemeNames[ovrLipSyncViseme::PP] = "PP"; VisemeNames[ovrLipSyncViseme::FF] = "FF"; VisemeNames[ovrLipSyncViseme::TH] = "TH"; VisemeNames[ovrLipSyncViseme::DD] = "DD"; VisemeNames[ovrLipSyncViseme::kk] = "kk"; VisemeNames[ovrLipSyncViseme::CH] = "CH"; VisemeNames[ovrLipSyncViseme::SS] = "SS"; VisemeNames[ovrLipSyncViseme::nn] = "nn"; VisemeNames[ovrLipSyncViseme::RR] = "RR"; VisemeNames[ovrLipSyncViseme::aa] = "aa"; VisemeNames[ovrLipSyncViseme::E] = "E"; VisemeNames[ovrLipSyncViseme::ih] = "ih"; VisemeNames[ovrLipSyncViseme::oh] = "oh"; VisemeNames[ovrLipSyncViseme::ou] = "ou"; }
TArray<float> UTensorFlowBlueprintLibrary::Conv_Texture2DToFloatArray(UTexture2D* InTexture) { TArray<float> FloatArray; FloatArray.SetNum(InTexture->GetSizeX()* InTexture->GetSizeY()); // Lock the texture so it can be read uint8* MipData = static_cast<uint8*>(InTexture->PlatformData->Mips[0].BulkData.Lock(LOCK_READ_ONLY)); for (int i = 0; i < FloatArray.Num(); i++) { int MipPointer = i * 4; float GreyscaleValue = (MipData[MipPointer] + MipData[MipPointer + 1] + MipData[MipPointer + 2]) / 3.f; FloatArray[i] = 1 - (GreyscaleValue / 255.f); //inverse and normalize it } // Unlock the texture InTexture->PlatformData->Mips[0].BulkData.Unlock(); //InTexture->UpdateResource(); return FloatArray; }
FString UMasterServerFunctions::DecompressBytes(TArray<uint8> CompressedBinaryArray) { TArray<uint8> UncompressedBinaryArray; UncompressedBinaryArray.SetNum(CompressedBinaryArray.Num() * 1032); //int ret; z_stream strm; strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; strm.avail_in = CompressedBinaryArray.Num(); strm.next_in = (Bytef *)CompressedBinaryArray.GetData(); strm.avail_out = UncompressedBinaryArray.Num(); strm.next_out = (Bytef *)UncompressedBinaryArray.GetData(); // the actual DE-compression work. inflateInit(&strm); inflate(&strm, Z_FINISH); inflateEnd(&strm); return BinaryArrayToFString(UncompressedBinaryArray); }
bool FWindowsPlatformProcess::ReadPipeToArray(void* ReadPipe, TArray<uint8> & Output) { uint32 BytesAvailable = 0; if (::PeekNamedPipe(ReadPipe, NULL, 0, NULL, (::DWORD*)&BytesAvailable, NULL) && (BytesAvailable > 0)) { Output.SetNumUninitialized(BytesAvailable); uint32 BytesRead = 0; if (::ReadFile(ReadPipe, Output.GetData(), BytesAvailable, (::DWORD*)&BytesRead, NULL)) { if (BytesRead < BytesAvailable) { Output.SetNum(BytesRead); } return true; } else { Output.Empty(); } } return false; }
void FTextLocalizationManager::RegenerateResources( const FString& ConfigFilePath, IInternationalizationArchiveSerializer& ArchiveSerializer, IInternationalizationManifestSerializer& ManifestSerializer ) { // Add one to the revision index, so all FText's refresh. ++HeadCultureRevisionIndex; FInternationalization& I18N = FInternationalization::Get(); FString SectionName = TEXT("RegenerateResources"); // Get source path. FString SourcePath; if( !( GConfig->GetString( *SectionName, TEXT("SourcePath"), SourcePath, ConfigFilePath ) ) ) { UE_LOG(LogTextLocalizationManager, Error, TEXT("No source path specified.")); return; } // Get destination path. FString DestinationPath; if( !( GConfig->GetString( *SectionName, TEXT("DestinationPath"), DestinationPath, ConfigFilePath ) ) ) { UE_LOG(LogTextLocalizationManager, Error, TEXT("No destination path specified.")); return; } // Get manifest name. FString ManifestName; if( !( GConfig->GetString( *SectionName, TEXT("ManifestName"), ManifestName, ConfigFilePath ) ) ) { UE_LOG(LogTextLocalizationManager, Error, TEXT("No manifest name specified.")); return; } // Get resource name. FString ResourceName; if( !( GConfig->GetString( *SectionName, TEXT("ResourceName"), ResourceName, ConfigFilePath ) ) ) { UE_LOG(LogTextLocalizationManager, Error, TEXT("No resource name specified.")); return; } TArray<FString> LocaleNames; { const FString CultureName = I18N.GetCurrentCulture()->GetName(); LocaleNames.Add(CultureName); const FString BaseLanguageName = I18N.GetCurrentCulture()->GetTwoLetterISOLanguageName(); if(BaseLanguageName != CultureName) { LocaleNames.Add(BaseLanguageName); } } // Source path needs to be relative to Engine or Game directory FString ConfigFullPath = FPaths::ConvertRelativePathToFull(ConfigFilePath); FString EngineFullPath = FPaths::ConvertRelativePathToFull(FPaths::EngineConfigDir()); bool IsEngineManifest = false; if (ConfigFullPath.StartsWith(EngineFullPath)) { IsEngineManifest = true; } if (IsEngineManifest) { SourcePath = FPaths::Combine(*(FPaths::EngineDir()), *SourcePath); DestinationPath = FPaths::Combine(*(FPaths::EngineDir()), *DestinationPath); } else { SourcePath = FPaths::Combine(*(FPaths::GameDir()), *SourcePath); DestinationPath = FPaths::Combine(*(FPaths::GameDir()), *DestinationPath); } TArray<TArray<uint8>> BackingBuffers; BackingBuffers.SetNum(LocaleNames.Num()); for(int32 i = 0; i < BackingBuffers.Num(); ++i) { TArray<uint8>& BackingBuffer = BackingBuffers[i]; FMemoryWriter MemoryWriter(BackingBuffer, true); // Read the manifest file from the source path. FString ManifestFilePath = (SourcePath / ManifestName); ManifestFilePath = FPaths::ConvertRelativePathToFull(ManifestFilePath); TSharedRef<FInternationalizationManifest> InternationalizationManifest = MakeShareable(new FInternationalizationManifest); #if 0 // @todo Json: Serializing from FArchive is currently broken FArchive* ManifestFile = IFileManager::Get().CreateFileReader(*ManifestFilePath); if (ManifestFile == nullptr) { UE_LOG(LogTextLocalizationManager, Error, TEXT("No manifest found at %s."), *ManifestFilePath); return; } ManifestSerializer.DeserializeManifest(*ManifestFile, InternationalizationManifest); #else FString ManifestContent; if (!FFileHelper::LoadFileToString(ManifestContent, *ManifestFilePath)) { UE_LOG(LogTextLocalizationManager, Error, TEXT("Failed to load file %s."), *ManifestFilePath); continue; } ManifestSerializer.DeserializeManifest(ManifestContent, InternationalizationManifest); #endif // Write resource. FTextLocalizationResourceGenerator::Generate(SourcePath, InternationalizationManifest, LocaleNames[i], &(MemoryWriter), ArchiveSerializer); MemoryWriter.Close(); } // Prioritized array of localization entry trackers. TArray<FLocalizationEntryTracker> LocalizationEntryTrackers; for(int32 i = 0; i < BackingBuffers.Num(); ++i) { TArray<uint8>& BackingBuffer = BackingBuffers[i]; FMemoryReader MemoryReader(BackingBuffer, true); const FString CulturePath = DestinationPath / LocaleNames[i]; const FString ResourceFilePath = FPaths::ConvertRelativePathToFull(CulturePath / ResourceName); FLocalizationEntryTracker& CultureTracker = LocalizationEntryTrackers[LocalizationEntryTrackers.Add(FLocalizationEntryTracker())]; CultureTracker.ReadFromArchive(MemoryReader, ResourceFilePath); CultureTracker.ReportCollisions(); MemoryReader.Close(); } // Don't filter updates by table name, or we can't live preview strings that had no translation originally UpdateLiveTable(LocalizationEntryTrackers); }
void UKUIInterfaceElement::SendEvent( FKUIInterfaceEvent& stEventInfo ) { if ( IsTemplate() ) return; static TArray<std::function<void( UKUIInterfaceElement*, FKUIInterfaceEvent& )>> arDispatchers; if ( arDispatchers.Num() == 0 ) { arDispatchers.SetNum( KUI_BASE_EVENT_LAST - KUI_BASE_EVENT_FIRST + 1 ); // Can't use UStruct pointers... so this. #pragma warning( disable : 4946 ) arDispatchers[ EKUIInterfaceElementEventList::E_Initialize - KUI_BASE_EVENT_FIRST ] = [] ( UKUIInterfaceElement* oElement, FKUIInterfaceEvent& stEventInfo ) { oElement->OnInitialize( *reinterpret_cast< FKUIInterfaceElementContainerEvent* >( &stEventInfo ) ); oElement->OnInitializeBP( *reinterpret_cast< FKUIInterfaceElementContainerEvent* >( &stEventInfo ) ); }; arDispatchers[ EKUIInterfaceElementEventList::E_AddedToContainer - KUI_BASE_EVENT_FIRST ] = [] ( UKUIInterfaceElement* oElement, FKUIInterfaceEvent& stEventInfo ) { oElement->OnAddedToContainer( *reinterpret_cast<FKUIInterfaceElementContainerEvent*>( &stEventInfo ) ); oElement->OnAddedToContainerBP( *reinterpret_cast<FKUIInterfaceElementContainerEvent*>( &stEventInfo ) ); }; arDispatchers[ EKUIInterfaceElementEventList::E_RemovedFromContainer - KUI_BASE_EVENT_FIRST ] = [] ( UKUIInterfaceElement* oElement, FKUIInterfaceEvent& stEventInfo ) { oElement->OnRemovedFromContainer( *reinterpret_cast<FKUIInterfaceElementContainerEvent*>( &stEventInfo ) ); oElement->OnRemovedFromContainerBP( *reinterpret_cast<FKUIInterfaceElementContainerEvent*>( &stEventInfo ) ); }; arDispatchers[ EKUIInterfaceElementEventList::E_Render - KUI_BASE_EVENT_FIRST ] = [] ( UKUIInterfaceElement* oElement, FKUIInterfaceEvent& stEventInfo ) { oElement->OnRender( *reinterpret_cast<FKUIInterfaceElementRenderEvent*>( &stEventInfo ) ); oElement->OnRenderBP( *reinterpret_cast<FKUIInterfaceElementRenderEvent*>( &stEventInfo ) ); }; arDispatchers[ EKUIInterfaceElementEventList::E_AlignLocationCalculated - KUI_BASE_EVENT_FIRST ] = [] ( UKUIInterfaceElement* oElement, FKUIInterfaceEvent& stEventInfo ) { oElement->OnAlignmentLocationCalculated( stEventInfo ); oElement->OnAlignmentLocationCalculatedBP( stEventInfo ); }; arDispatchers[ EKUIInterfaceElementEventList::E_AlignLocationInvalidated - KUI_BASE_EVENT_FIRST ] = [] ( UKUIInterfaceElement* oElement, FKUIInterfaceEvent& stEventInfo ) { oElement->OnAlignLocationInvalidated( stEventInfo ); oElement->OnAlignLocationInvalidatedBP( stEventInfo ); }; arDispatchers[ EKUIInterfaceElementEventList::E_LocationChange - KUI_BASE_EVENT_FIRST ] = [] ( UKUIInterfaceElement* oElement, FKUIInterfaceEvent& stEventInfo ) { oElement->OnLocationChange( *reinterpret_cast<FKUIInterfaceContainerLocationChangeEvent*>( &stEventInfo ) ); oElement->OnLocationChangeBP( *reinterpret_cast<FKUIInterfaceContainerLocationChangeEvent*>( &stEventInfo ) ); }; arDispatchers[ EKUIInterfaceElementEventList::E_SizeChange - KUI_BASE_EVENT_FIRST ] = [] ( UKUIInterfaceElement* oElement, FKUIInterfaceEvent& stEventInfo ) { oElement->OnSizeChange( *reinterpret_cast<FKUIInterfaceContainerSizeChangeEvent*>( &stEventInfo ) ); oElement->OnSizeChangeBP( *reinterpret_cast<FKUIInterfaceContainerSizeChangeEvent*>( &stEventInfo ) ); }; #pragma warning( default : 4946 ) } if ( stEventInfo.iEventID >= KUI_BASE_EVENT_FIRST && stEventInfo.iEventID <= KUI_BASE_EVENT_LAST ) arDispatchers[ stEventInfo.iEventID - KUI_BASE_EVENT_FIRST ]( this, stEventInfo ); }
ERet FxUtil_LoadShaderLibrary( AStreamReader& stream, Clump &clump, const Resolution& screen ) { FxLibraryHeader_d libraryHeader; mxDO(stream.Get(libraryHeader)); // Load shader library structures. #if mxUSE_BINARY_EFFECT_FILE_FORMAT UNDONE; //mxTRY(Serialization::LoadClumpImage(stream, clump)); #else ByteBuffer32 buffer; buffer.SetNum(libraryHeader.runtimeSize); stream.Read(buffer.ToPtr(), buffer.Num()); SON::Parser parser; parser.buffer = (char*)buffer.ToPtr(); parser.length = libraryHeader.runtimeSize; parser.line = 1; parser.file = ""; SON::Allocator allocator; SON::Node* root = SON::ParseBuffer(parser, allocator); chkRET_X_IF_NIL(root, ERR_FAILED_TO_PARSE_DATA); mxTRY(SON::LoadClump( root, clump )); #endif // Initialization order: // 1) Render targets // 2) State objects // 3) Shaders // 4) Input layouts // 5) Everything else // render targets should be sorted by size // shader resources should be sorted by size // constant buffers should be sorted by size CreateRenderTargets(screen, clump, false); // Ideally, render states should be sorted by state deltas (so that changes between adjacent states are minimized). { TObjectIterator< FxSamplerState > samplerStateIt( clump ); while( samplerStateIt.IsValid() ) { FxSamplerState& samplerState = samplerStateIt.Value(); samplerState.handle = llgl::CreateSamplerState( samplerState ); samplerStateIt.MoveToNext(); } } { TObjectIterator< FxDepthStencilState > depthStencilStateIt( clump ); while( depthStencilStateIt.IsValid() ) { FxDepthStencilState& depthStencilState = depthStencilStateIt.Value(); depthStencilState.handle = llgl::CreateDepthStencilState( depthStencilState ); depthStencilStateIt.MoveToNext(); } } { TObjectIterator< FxRasterizerState > rasterizerStateIt( clump ); while( rasterizerStateIt.IsValid() ) { FxRasterizerState& rasterizerState = rasterizerStateIt.Value(); rasterizerState.handle = llgl::CreateRasterizerState( rasterizerState ); rasterizerStateIt.MoveToNext(); } } { TObjectIterator< FxBlendState > blendStateIt( clump ); while( blendStateIt.IsValid() ) { FxBlendState& blendState = blendStateIt.Value(); blendState.handle = llgl::CreateBlendState( blendState ); blendStateIt.MoveToNext(); } } FxRenderResources* renderStates = FindSingleInstance<FxRenderResources>(clump); if(renderStates) { for( UINT32 iStateBlock = 0; iStateBlock < renderStates->state_blocks.Num(); iStateBlock++ ) { FxStateBlock* stateBlock = renderStates->state_blocks[ iStateBlock ]; stateBlock->blendState = renderStates->blend_states[ stateBlock->blendState.id ]->handle; stateBlock->rasterizerState = renderStates->rasterizer_states[ stateBlock->rasterizerState.id ]->handle; stateBlock->depthStencilState= renderStates->depth_stencil_states[ stateBlock->depthStencilState.id ]->handle; } } // Create constant buffers and shader resources. { TObjectIterator< FxCBuffer > cbufferIt( clump ); while( cbufferIt.IsValid() ) { FxCBuffer& ubo = cbufferIt.Value(); ubo.handle = llgl::CreateBuffer( Buffer_Uniform, ubo.size, NULL ); cbufferIt.MoveToNext(); } } CacheHeader_d cacheHeader; mxDO(stream.Get(cacheHeader)); // Create shaders. FxShaderHandles shaders; ScopedStackAlloc tempAlloc( gCore.frameAlloc ); for( UINT32 shaderType = 0; shaderType < ShaderTypeCount; shaderType++ ) { const UINT32 shaderCount = cacheHeader.numShaders[shaderType]; if( shaderCount ) { HShader* shaderHandlesStorage = tempAlloc.AllocMany< HShader >( shaderCount ); shaders.handles[shaderType].SetExternalStorage( shaderHandlesStorage, shaderCount ); shaders.handles[shaderType].SetNum( shaderCount ); } } mxDO(ShaderCache_d::CreateShaders( cacheHeader, stream, shaders )); // Create programs. TArray< HProgram > programHandles; { const UINT32 programsCount = cacheHeader.numPrograms; HProgram* programHandlesStorage = tempAlloc.AllocMany< HProgram >( programsCount ); programHandles.SetExternalStorage( programHandlesStorage, programsCount ); programHandles.SetNum( programsCount ); ScopedStackAlloc programAlloc( gCore.frameAlloc ); char * tempBuffer = programAlloc.Alloc( cacheHeader.bufferSize ); ByteArrayT programBlob( tempBuffer, cacheHeader.bufferSize ); for( UINT32 programIndex = 0; programIndex < programsCount; programIndex++ ) { stream >> programBlob; CachedProgram_d * program; mxDO(Serialization::LoadInPlace( programBlob.ToPtr(), programBlob.Num(), program )); HShader* shaderIds = program->pd.shaders; for( UINT32 shaderType = 0; shaderType < ShaderTypeCount; shaderType++ ) { const UINT16 shaderIndex = shaderIds[shaderType].id; if( shaderIndex != (UINT16)~0 ) { shaderIds[shaderType] = shaders.handles[shaderType][shaderIndex]; } } const HProgram programHandle = llgl::CreateProgram( program->pd ); programHandles[programIndex] = programHandle; } } { TObjectIterator< FxShader > shaderIt( clump ); while( shaderIt.IsValid() ) { FxShader& shader = shaderIt.Value(); for( UINT32 i = 0; i < shader.programs.Num(); i++ ) { int programIndex = shader.programs[i].id; shader.programs[i] = programHandles[programIndex]; } shaderIt.MoveToNext(); } } return ALL_OK; }
UFlareSaveGame* UFlareSaveGameSystem::LoadGame(const FString SaveName) { FLOGV("UFlareSaveGameSystem::LoadGame SaveName=%s", *SaveName); UFlareSaveGame *SaveGame = NULL; // Read the saveto a string FString SaveString; bool SaveStringLoaded = false; TArray<uint8> Data; auto LoadCompressedFileToString = [&](FString& Result, const TCHAR* Filename) { TArray<uint8> DataCompressed; if(!FFileHelper::LoadFileToArray(DataCompressed, Filename)) { FLOGV("Fail to read save '%s'", Filename); return false; } int b4 = DataCompressed[DataCompressed.Num()- 4]; int b3 = DataCompressed[DataCompressed.Num()- 3]; int b2 = DataCompressed[DataCompressed.Num()- 2]; int b1 = DataCompressed[DataCompressed.Num()- 1]; int UncompressedSize = (b1 << 24) | (b2 << 16) + (b3 << 8) + b4; Data.SetNum(UncompressedSize + 1); if(!FCompression::UncompressMemory((ECompressionFlags)(COMPRESS_ZLIB), Data.GetData(), UncompressedSize, DataCompressed.GetData(), DataCompressed.Num(), false, 31)) { FLOGV("Fail to uncompress save '%s' with compressed size %d and uncompressed size %d", Filename, DataCompressed.Num(), UncompressedSize); return false; } Data[UncompressedSize] = 0; // end string Result = UTF8_TO_TCHAR(Data.GetData()); return true; }; if(LoadCompressedFileToString(SaveString, *GetSaveGamePath(SaveName, true))) { FLOGV("Save '%s' read", *GetSaveGamePath(SaveName, true)); SaveStringLoaded = true; } else if(FFileHelper::LoadFileToString(SaveString, *GetSaveGamePath(SaveName, false))) { FLOGV("Save '%s' read", *GetSaveGamePath(SaveName, false)); SaveStringLoaded = true; } if(SaveStringLoaded) { // Deserialize a JSON object from the string TSharedPtr< FJsonObject > Object; TSharedRef< TJsonReader<> > Reader = TJsonReaderFactory<>::Create(SaveString); if(FJsonSerializer::Deserialize(Reader, Object) && Object.IsValid()) { UFlareSaveReaderV1* SaveReader = NewObject<UFlareSaveReaderV1>(this, UFlareSaveReaderV1::StaticClass()); SaveGame = SaveReader->LoadGame(Object); } else { FLOGV("Fail to deserialize save '%s' (len: %d)", *GetSaveGamePath(SaveName, false), SaveString.Len()); } } else { FLOGV("Fail to read save '%s' or '%s'", *GetSaveGamePath(SaveName, true), *GetSaveGamePath(SaveName, false)); } return SaveGame; }
void UEnvQueryTest_PathfindingBatch::RunTest(FEnvQueryInstance& QueryInstance) const { UObject* QueryOwner = QueryInstance.Owner.Get(); BoolValue.BindData(QueryOwner, QueryInstance.QueryID); PathFromContext.BindData(QueryOwner, QueryInstance.QueryID); SkipUnreachable.BindData(QueryOwner, QueryInstance.QueryID); FloatValueMin.BindData(QueryOwner, QueryInstance.QueryID); FloatValueMax.BindData(QueryOwner, QueryInstance.QueryID); ScanRangeMultiplier.BindData(QueryOwner, QueryInstance.QueryID); bool bWantsPath = BoolValue.GetValue(); bool bPathToItem = PathFromContext.GetValue(); bool bDiscardFailed = SkipUnreachable.GetValue(); float MinThresholdValue = FloatValueMin.GetValue(); float MaxThresholdValue = FloatValueMax.GetValue(); float RangeMultiplierValue = ScanRangeMultiplier.GetValue(); UNavigationSystem* NavSys = QueryInstance.World->GetNavigationSystem(); if (NavSys == nullptr) { return; } ANavigationData* NavData = FindNavigationData(*NavSys, QueryOwner); ARecastNavMesh* NavMeshData = Cast<ARecastNavMesh>(NavData); if (NavMeshData == nullptr) { return; } TArray<FVector> ContextLocations; if (!QueryInstance.PrepareContext(Context, ContextLocations)) { return; } TArray<FNavigationProjectionWork> TestPoints; TArray<float> CollectDistanceSq; CollectDistanceSq.Init(0.0f, ContextLocations.Num()); FSharedNavQueryFilter NavigationFilter = FilterClass != nullptr ? UNavigationQueryFilter::GetQueryFilter(*NavMeshData, FilterClass)->GetCopy() : NavMeshData->GetDefaultQueryFilter()->GetCopy(); NavigationFilter->SetBacktrackingEnabled(!bPathToItem); const dtQueryFilter* NavQueryFilter = ((const FRecastQueryFilter*)NavigationFilter->GetImplementation())->GetAsDetourQueryFilter(); { // scope for perf timers // can't use FEnvQueryInstance::ItemIterator yet, since it has built in scoring functionality for (int32 ItemIdx = 0; ItemIdx < QueryInstance.Items.Num(); ItemIdx++) { if (QueryInstance.Items[ItemIdx].IsValid()) { const FVector ItemLocation = GetItemLocation(QueryInstance, ItemIdx); TestPoints.Add(FNavigationProjectionWork(ItemLocation)); for (int32 ContextIdx = 0; ContextIdx < ContextLocations.Num(); ContextIdx++) { const float TestDistanceSq = FVector::DistSquared(ItemLocation, ContextLocations[ContextIdx]); CollectDistanceSq[ContextIdx] = FMath::Max(CollectDistanceSq[ContextIdx], TestDistanceSq); } } } NavMeshData->BatchProjectPoints(TestPoints, NavMeshData->GetDefaultQueryExtent(), NavigationFilter); } TArray<FRecastDebugPathfindingData> NodePoolData; NodePoolData.SetNum(ContextLocations.Num()); { // scope for perf timer TArray<NavNodeRef> Polys; for (int32 ContextIdx = 0; ContextIdx < ContextLocations.Num(); ContextIdx++) { const float MaxPathDistance = FMath::Sqrt(CollectDistanceSq[ContextIdx]) * RangeMultiplierValue; Polys.Reset(); NodePoolData[ContextIdx].Flags = ERecastDebugPathfindingFlags::PathLength; NavMeshData->GetPolysWithinPathingDistance(ContextLocations[ContextIdx], MaxPathDistance, Polys, NavigationFilter, nullptr, &NodePoolData[ContextIdx]); } } int32 ProjectedItemIdx = 0; if (GetWorkOnFloatValues()) { NodePoolHelpers::PathParamFunc Func[] = { nullptr, NodePoolHelpers::GetPathCost, NodePoolHelpers::GetPathLength }; FEnvQueryInstance::ItemIterator It(this, QueryInstance); for (It.IgnoreTimeLimit(); It; ++It, ProjectedItemIdx++) { for (int32 ContextIndex = 0; ContextIndex < ContextLocations.Num(); ContextIndex++) { const float PathValue = Func[TestMode](NodePoolData[ContextIndex], TestPoints[ProjectedItemIdx], NavQueryFilter); It.SetScore(TestPurpose, FilterType, PathValue, MinThresholdValue, MaxThresholdValue); if (bDiscardFailed && PathValue >= BIG_NUMBER) { It.ForceItemState(EEnvItemStatus::Failed); } } } } else { FEnvQueryInstance::ItemIterator It(this, QueryInstance); for (It.IgnoreTimeLimit(); It; ++It, ProjectedItemIdx++) { for (int32 ContextIndex = 0; ContextIndex < ContextLocations.Num(); ContextIndex++) { const bool bFoundPath = NodePoolHelpers::HasPath(NodePoolData[ContextIndex], TestPoints[ProjectedItemIdx]); It.SetScore(TestPurpose, FilterType, bFoundPath, bWantsPath); } } } }
int32 FProceduralTerrainWorker::PolygonizeToTriangles( UTerrainGrid *TerrainGrid, float p_fSurfaceCrossValue, FIntVector ChunkStartSize, FIntVector ChunkEndSize, FVector &ChunkLocation, FVector &ChunkScale, FTransform &TerrainTransform, TArray<FVector> &Vertices, TArray<int32> &Indices, TArray<FVector> &Normals, TArray<FVector2D> &UVs, TArray<FColor> &VertexColors, TArray<FProcMeshTangent> &Tangents ) { // TODO? float PosX = ChunkLocation.X; float PosY = ChunkLocation.Y; float PosZ = ChunkLocation.Z; TArray<FVector> Positions; int NumTriangles = 0; for (int32 x = ChunkStartSize.X; x < ChunkEndSize.X; ++x) { for (int32 y = ChunkStartSize.Y; y < ChunkEndSize.Y; ++y) { for (int32 z = ChunkStartSize.Z; z < ChunkEndSize.Z; ++z) { // Get each points of a cube. float p0 = TerrainGrid->GetVoxel(x, y, z); float p1 = TerrainGrid->GetVoxel(x + 1, y, z); float p2 = TerrainGrid->GetVoxel(x, y + 1, z); float p3 = TerrainGrid->GetVoxel(x + 1, y + 1, z); float p4 = TerrainGrid->GetVoxel(x, y, z + 1); float p5 = TerrainGrid->GetVoxel(x + 1, y, z + 1); float p6 = TerrainGrid->GetVoxel(x, y + 1, z + 1); float p7 = TerrainGrid->GetVoxel(x + 1, y + 1, z + 1); /* Determine the index into the edge table which tells us which vertices are inside of the surface */ int crossBitMap = 0; if (p0 < p_fSurfaceCrossValue) crossBitMap |= 1; if (p1 < p_fSurfaceCrossValue) crossBitMap |= 2; if (p2 < p_fSurfaceCrossValue) crossBitMap |= 8; if (p3 < p_fSurfaceCrossValue) crossBitMap |= 4; if (p4 < p_fSurfaceCrossValue) crossBitMap |= 16; if (p5 < p_fSurfaceCrossValue) crossBitMap |= 32; if (p6 < p_fSurfaceCrossValue) crossBitMap |= 128; if (p7 < p_fSurfaceCrossValue) crossBitMap |= 64; /* Cube is entirely in/out of the surface */ int edgeBits = edgeTable[crossBitMap]; if (edgeBits == 0) continue; float interpolatedCrossingPoint = 0.0f; FVector interpolatedValues[12]; if ((edgeBits & 1) > 0) { interpolatedCrossingPoint = (p_fSurfaceCrossValue - p0) / (p1 - p0); interpolatedValues[0] = FMath::Lerp(FVector(PosX + x, PosY + y, PosZ + z), FVector(PosX + x + 1, PosY + y, PosZ + z), interpolatedCrossingPoint); } if ((edgeBits & 2) > 0) { interpolatedCrossingPoint = (p_fSurfaceCrossValue - p1) / (p3 - p1); interpolatedValues[1] = FMath::Lerp(FVector(PosX + x + 1, PosY + y, PosZ + z), FVector(PosX + x + 1, PosY + y + 1, PosZ + z), interpolatedCrossingPoint); } if ((edgeBits & 4) > 0) { interpolatedCrossingPoint = (p_fSurfaceCrossValue - p2) / (p3 - p2); interpolatedValues[2] = FMath::Lerp(FVector(PosX + x, PosY + y + 1, PosZ + z), FVector(PosX + x + 1, PosY + y + 1, PosZ + z), interpolatedCrossingPoint); } if ((edgeBits & 8) > 0) { interpolatedCrossingPoint = (p_fSurfaceCrossValue - p0) / (p2 - p0); interpolatedValues[3] = FMath::Lerp(FVector(PosX + x, PosY + y, PosZ + z), FVector(PosX + x, PosY + y + 1, PosZ + z), interpolatedCrossingPoint); } //Top four edges if ((edgeBits & 16) > 0) { interpolatedCrossingPoint = (p_fSurfaceCrossValue - p4) / (p5 - p4); interpolatedValues[4] = FMath::Lerp(FVector(PosX + x, PosY + y, PosZ + z + 1), FVector(PosX + x + 1, PosY + y, PosZ + z + 1), interpolatedCrossingPoint); } if ((edgeBits & 32) > 0) { interpolatedCrossingPoint = (p_fSurfaceCrossValue - p5) / (p7 - p5); interpolatedValues[5] = FMath::Lerp(FVector(PosX + x + 1, PosY + y, PosZ + z + 1), FVector(PosX + x + 1, PosY + y + 1, PosZ + z + 1), interpolatedCrossingPoint); } if ((edgeBits & 64) > 0) { interpolatedCrossingPoint = (p_fSurfaceCrossValue - p6) / (p7 - p6); interpolatedValues[6] = FMath::Lerp(FVector(PosX + x, PosY + y + 1, PosZ + z + 1), FVector(PosX + x + 1, PosY + y + 1, PosZ + z + 1), interpolatedCrossingPoint); } if ((edgeBits & 128) > 0) { interpolatedCrossingPoint = (p_fSurfaceCrossValue - p4) / (p6 - p4); interpolatedValues[7] = FMath::Lerp(FVector(PosX + x, PosY + y, PosZ + z + 1), FVector(PosX + x, PosY + y + 1, PosZ + z + 1), interpolatedCrossingPoint); } //Side four edges if ((edgeBits & 256) > 0) { interpolatedCrossingPoint = (p_fSurfaceCrossValue - p0) / (p4 - p0); interpolatedValues[8] = FMath::Lerp(FVector(PosX + x, PosY + y, PosZ + z), FVector(PosX + x, PosY + y, PosZ + z + 1), interpolatedCrossingPoint); } if ((edgeBits & 512) > 0) { interpolatedCrossingPoint = (p_fSurfaceCrossValue - p1) / (p5 - p1); interpolatedValues[9] = FMath::Lerp(FVector(PosX + x + 1, PosY + y, PosZ + z), FVector(PosX + x + 1, PosY + y, PosZ + z + 1), interpolatedCrossingPoint); } if ((edgeBits & 1024) > 0) { interpolatedCrossingPoint = (p_fSurfaceCrossValue - p3) / (p7 - p3); interpolatedValues[10] = FMath::Lerp(FVector(PosX + x + 1, PosY + y + 1, PosZ + z), FVector(PosX + x + 1, PosY + y + 1, PosZ + z + 1), interpolatedCrossingPoint); } if ((edgeBits & 2048) > 0) { interpolatedCrossingPoint = (p_fSurfaceCrossValue - p2) / (p6 - p2); interpolatedValues[11] = FMath::Lerp(FVector(PosX + x, PosY + y + 1, PosZ + z), FVector(PosX + x, PosY + y + 1, PosZ + z + 1), interpolatedCrossingPoint); } crossBitMap <<= 4; int triangleIndex = 0; while (triTable[crossBitMap + triangleIndex] != -1) { // For each triangle in the look up table, create a triangle and add it to the list. int index1 = triTable[crossBitMap + triangleIndex]; int index2 = triTable[crossBitMap + triangleIndex + 1]; int index3 = triTable[crossBitMap + triangleIndex + 2]; FDynamicMeshVertex Vertex0; Vertex0.Position = TerrainTransform.TransformVector(ChunkScale * interpolatedValues[index1]); FDynamicMeshVertex Vertex1; Vertex1.Position = TerrainTransform.TransformVector(ChunkScale * interpolatedValues[index2]); FDynamicMeshVertex Vertex2; Vertex2.Position = TerrainTransform.TransformVector(ChunkScale * interpolatedValues[index3]); Vertex0.TextureCoordinate.X = Vertex0.Position.X / 100.0f; Vertex0.TextureCoordinate.Y = Vertex0.Position.Y / 100.0f; Vertex1.TextureCoordinate.X = Vertex1.Position.X / 100.0f; Vertex1.TextureCoordinate.Y = Vertex1.Position.Y / 100.0f; Vertex2.TextureCoordinate.X = Vertex2.Position.X / 100.0f; Vertex2.TextureCoordinate.Y = Vertex2.Position.Y / 100.0f; // Fill Index buffer And Vertex buffer with the generated vertices. int32 VIndex0 = Positions.Find(Vertex0.Position); if (VIndex0 < 0) { VIndex0 = Positions.Add(Vertex0.Position); Indices.Add(VIndex0); Vertices.Add(Vertex0.Position); UVs.Add(FVector2D(Vertex0.TextureCoordinate)); } else { Indices.Add(VIndex0); } int32 VIndex1 = Positions.Find(Vertex1.Position); if (VIndex1 < 0) { VIndex1 = Positions.Add(Vertex1.Position); Indices.Add(VIndex1); Vertices.Add(Vertex1.Position); UVs.Add(FVector2D(Vertex1.TextureCoordinate)); } else { Indices.Add(VIndex1); } int32 VIndex2 = Positions.Find(Vertex2.Position); if (VIndex2 < 0) { VIndex2 = Positions.Add(Vertex2.Position); Indices.Add(VIndex2); Vertices.Add(Vertex2.Position); UVs.Add(FVector2D(Vertex2.TextureCoordinate)); } else { Indices.Add(VIndex2); } ++NumTriangles; triangleIndex += 3; } } } } VertexColors.SetNum(Vertices.Num(), false); Normals.SetNum(Vertices.Num(), false); Tangents.SetNum(Vertices.Num(), false); for (int32 Index = 0; Index < Indices.Num(); Index += 3) { const FVector Edge21 = Vertices[Indices[Index + 1]] - Vertices[Indices[Index + 2]]; const FVector Edge20 = Vertices[Indices[Index + 0]] - Vertices[Indices[Index + 2]]; FVector TriNormal = (Edge21 ^ Edge20).GetSafeNormal(); FVector FaceTangentX = Edge20.GetSafeNormal(); FVector FaceTangentY = (FaceTangentX ^ TriNormal).GetSafeNormal(); FVector FaceTangentZ = TriNormal; // Use Gram-Schmidt orthogonalization to make sure X is orth with Z FaceTangentX -= FaceTangentZ * (FaceTangentZ | FaceTangentX); FaceTangentX.Normalize(); // See if we need to flip TangentY when generating from cross product const bool bFlipBitangent = ((FaceTangentZ ^ FaceTangentX) | FaceTangentY) < 0.f; TriNormal.Normalize(); FaceTangentX.Normalize(); FProcMeshTangent tangent = FProcMeshTangent(FaceTangentX, bFlipBitangent); for (int32 i = 0; i < 3; i++) { Normals[Indices[Index + i]] = TriNormal; Tangents[Indices[Index + i]] = tangent; VertexColors[Indices[Index + i]] = FColor(1, 1, 1, 1); } } //UE_LOG(LogTemp, Warning, TEXT("NumTriangles: %d => %d,%d -> %d,%d"), NumTriangles, ChunkStartSize.X, ChunkStartSize.Y, ChunkEndSize.X, ChunkEndSize.Y); return NumTriangles; }
int32 UGatherTextFromAssetsCommandlet::Main(const FString& Params) { // Parse command line. TArray<FString> Tokens; TArray<FString> Switches; TMap<FString, FString> ParamVals; UCommandlet::ParseCommandLine(*Params, Tokens, Switches, ParamVals); //Set config file const FString* ParamVal = ParamVals.Find(FString(TEXT("Config"))); FString GatherTextConfigPath; if ( ParamVal ) { GatherTextConfigPath = *ParamVal; } else { UE_LOG(LogGatherTextFromAssetsCommandlet, Error, TEXT("No config specified.")); return -1; } //Set config section ParamVal = ParamVals.Find(FString(TEXT("Section"))); FString SectionName; if ( ParamVal ) { SectionName = *ParamVal; } else { UE_LOG(LogGatherTextFromAssetsCommandlet, Error, TEXT("No config section specified.")); return -1; } //Modules to Preload TArray<FString> ModulesToPreload; GetStringArrayFromConfig(*SectionName, TEXT("ModulesToPreload"), ModulesToPreload, GatherTextConfigPath); for (const FString& ModuleName : ModulesToPreload) { FModuleManager::Get().LoadModule(*ModuleName); } // IncludePathFilters TArray<FString> IncludePathFilters; GetPathArrayFromConfig(*SectionName, TEXT("IncludePathFilters"), IncludePathFilters, GatherTextConfigPath); // IncludePaths (DEPRECATED) { TArray<FString> IncludePaths; GetPathArrayFromConfig(*SectionName, TEXT("IncludePaths"), IncludePaths, GatherTextConfigPath); if (IncludePaths.Num()) { IncludePathFilters.Append(IncludePaths); UE_LOG(LogGatherTextFromAssetsCommandlet, Warning, TEXT("IncludePaths detected in section %s. IncludePaths is deprecated, please use IncludePathFilters."), *SectionName); } } if (IncludePathFilters.Num() == 0) { UE_LOG(LogGatherTextFromAssetsCommandlet, Error, TEXT("No include path filters in section %s."), *SectionName); return -1; } // ExcludePathFilters TArray<FString> ExcludePathFilters; GetPathArrayFromConfig(*SectionName, TEXT("ExcludePathFilters"), ExcludePathFilters, GatherTextConfigPath); // ExcludePaths (DEPRECATED) { TArray<FString> ExcludePaths; GetPathArrayFromConfig(*SectionName, TEXT("ExcludePaths"), ExcludePaths, GatherTextConfigPath); if (ExcludePaths.Num()) { ExcludePathFilters.Append(ExcludePaths); UE_LOG(LogGatherTextFromAssetsCommandlet, Warning, TEXT("ExcludePaths detected in section %s. ExcludePaths is deprecated, please use ExcludePathFilters."), *SectionName); } } // PackageNameFilters TArray<FString> PackageFileNameFilters; GetStringArrayFromConfig(*SectionName, TEXT("PackageFileNameFilters"), PackageFileNameFilters, GatherTextConfigPath); // PackageExtensions (DEPRECATED) { TArray<FString> PackageExtensions; GetStringArrayFromConfig(*SectionName, TEXT("PackageExtensions"), PackageExtensions, GatherTextConfigPath); if (PackageExtensions.Num()) { PackageFileNameFilters.Append(PackageExtensions); UE_LOG(LogGatherTextFromAssetsCommandlet, Warning, TEXT("PackageExtensions detected in section %s. PackageExtensions is deprecated, please use PackageFileNameFilters."), *SectionName); } } if (PackageFileNameFilters.Num() == 0) { UE_LOG(LogGatherTextFromAssetsCommandlet, Error, TEXT("No package file name filters in section %s."), *SectionName); return -1; } //asset class exclude TArray<FString> ExcludeClasses; GetStringArrayFromConfig(*SectionName, TEXT("ExcludeClasses"), ExcludeClasses, GatherTextConfigPath); FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(TEXT("AssetRegistry")); AssetRegistryModule.Get().SearchAllAssets( true ); FARFilter Filter; for(const auto& ExcludeClass : ExcludeClasses) { UClass* FilterClass = FindObject<UClass>(ANY_PACKAGE, *ExcludeClass); if(FilterClass) { Filter.ClassNames.Add( FilterClass->GetFName() ); } else { UE_LOG(LogGatherTextFromAssetsCommandlet, Warning, TEXT("Invalid exclude class %s"), *ExcludeClass); } } TArray<FAssetData> AssetDataArray; AssetRegistryModule.Get().GetAssets(Filter, AssetDataArray); FString UAssetPackageExtension = FPackageName::GetAssetPackageExtension(); TSet< FString > LongPackageNamesToExclude; for (int Index = 0; Index < AssetDataArray.Num(); Index++) { LongPackageNamesToExclude.Add( FPackageName::LongPackageNameToFilename( AssetDataArray[Index].PackageName.ToString(), UAssetPackageExtension ) ); } //Get whether we should fix broken properties that we find. if (!GetBoolFromConfig(*SectionName, TEXT("bFixBroken"), bFixBroken, GatherTextConfigPath)) { bFixBroken = false; } // Get whether we should gather editor-only data. Typically only useful for the localization of UE4 itself. if (!GetBoolFromConfig(*SectionName, TEXT("ShouldGatherFromEditorOnlyData"), ShouldGatherFromEditorOnlyData, GatherTextConfigPath)) { ShouldGatherFromEditorOnlyData = false; } // Add any manifest dependencies if they were provided TArray<FString> ManifestDependenciesList; GetPathArrayFromConfig(*SectionName, TEXT("ManifestDependencies"), ManifestDependenciesList, GatherTextConfigPath); if( !ManifestInfo->AddManifestDependencies( ManifestDependenciesList ) ) { UE_LOG(LogGatherTextFromAssetsCommandlet, Error, TEXT("The GatherTextFromAssets commandlet couldn't find all the specified manifest dependencies.")); return -1; } //The main array of files to work from. TArray< FString > PackageFileNamesToProcess; TArray<FString> PackageFilesNotInIncludePath; TArray<FString> PackageFilesInExcludePath; TArray<FString> PackageFilesExcludedByClass; //Fill the list of packages to work from. uint8 PackageFilter = NORMALIZE_DefaultFlags; TArray<FString> Unused; for ( int32 PackageFilenameWildcardIdx = 0; PackageFilenameWildcardIdx < PackageFileNameFilters.Num(); PackageFilenameWildcardIdx++ ) { const bool IsAssetPackage = PackageFileNameFilters[PackageFilenameWildcardIdx] == ( FString( TEXT("*") )+ FPackageName::GetAssetPackageExtension() ); TArray<FString> PackageFiles; if ( !NormalizePackageNames( Unused, PackageFiles, PackageFileNameFilters[PackageFilenameWildcardIdx], PackageFilter) ) { UE_LOG(LogGatherTextFromAssetsCommandlet, Display, TEXT("No packages found with extension %i: '%s'"), PackageFilenameWildcardIdx, *PackageFileNameFilters[PackageFilenameWildcardIdx]); continue; } else { UE_LOG(LogGatherTextFromAssetsCommandlet, Display, TEXT("Found %i packages with extension %i: '%s'"), PackageFiles.Num(), PackageFilenameWildcardIdx, *PackageFileNameFilters[PackageFilenameWildcardIdx]); } //Run through all the files found and add any that pass the include, exclude and filter constraints to OrderedPackageFilesToLoad for (FString& PackageFile : PackageFiles) { PackageFile = FPaths::ConvertRelativePathToFull(PackageFile); bool bExclude = false; //Ensure it matches the include paths if there are some. for (FString& IncludePath : IncludePathFilters) { bExclude = true; if( PackageFile.MatchesWildcard(IncludePath) ) { bExclude = false; break; } } if ( bExclude ) { PackageFilesNotInIncludePath.Add(PackageFile); } //Ensure it does not match the exclude paths if there are some. for (const FString& ExcludePath : ExcludePathFilters) { if (PackageFile.MatchesWildcard(ExcludePath)) { bExclude = true; PackageFilesInExcludePath.Add(PackageFile); break; } } //Check that this is not on the list of packages that we don't care about e.g. textures. if ( !bExclude && IsAssetPackage && LongPackageNamesToExclude.Contains( PackageFile ) ) { bExclude = true; PackageFilesExcludedByClass.Add(PackageFile); } //If we haven't failed one of the above checks, add it to the array of packages to process. if(!bExclude) { PackageFileNamesToProcess.Add(PackageFile); } } } if ( PackageFileNamesToProcess.Num() == 0 ) { UE_LOG(LogGatherTextFromAssetsCommandlet, Warning, TEXT("No files found or none passed the include/exclude criteria.")); } bool bSkipGatherCache = FParse::Param(FCommandLine::Get(), TEXT("SkipGatherCache")); if (!bSkipGatherCache) { GetBoolFromConfig(*SectionName, TEXT("SkipGatherCache"), bSkipGatherCache, GatherTextConfigPath); } UE_LOG(LogGatherTextFromAssetsCommandlet, Log, TEXT("SkipGatherCache: %s"), bSkipGatherCache ? TEXT("true") : TEXT("false")); TArray< FString > PackageFileNamesToLoad; for (FString& PackageFile : PackageFileNamesToProcess) { TScopedPointer< FArchive > FileReader( IFileManager::Get().CreateFileReader( *PackageFile ) ); if( FileReader ) { // Read package file summary from the file FPackageFileSummary PackageFileSummary; (*FileReader) << PackageFileSummary; bool MustLoadForGather = false; // Have we been asked to skip the cache of text that exists in the header of newer packages? if (bSkipGatherCache && PackageFileSummary.GetFileVersionUE4() >= VER_UE4_SERIALIZE_TEXT_IN_PACKAGES) { // Fallback on the old package flag check. if (PackageFileSummary.PackageFlags & PKG_RequiresLocalizationGather) { MustLoadForGather = true; } } const FCustomVersion* const EditorVersion = PackageFileSummary.GetCustomVersionContainer().GetVersion(FEditorObjectVersion::GUID); // Packages not resaved since localization gathering flagging was added to packages must be loaded. if (PackageFileSummary.GetFileVersionUE4() < VER_UE4_PACKAGE_REQUIRES_LOCALIZATION_GATHER_FLAGGING) { MustLoadForGather = true; } // Package not resaved since gatherable text data was added to package headers must be loaded, since their package header won't contain pregathered text data. else if (PackageFileSummary.GetFileVersionUE4() < VER_UE4_SERIALIZE_TEXT_IN_PACKAGES) { // Fallback on the old package flag check. if (PackageFileSummary.PackageFlags & PKG_RequiresLocalizationGather) { MustLoadForGather = true; } } else if (PackageFileSummary.GetFileVersionUE4() < VER_UE4_DIALOGUE_WAVE_NAMESPACE_AND_CONTEXT_CHANGES) { IAssetRegistry& AssetRegistry = AssetRegistryModule.Get(); TArray<FAssetData> AssetDataInPackage; AssetRegistry.GetAssetsByPackageName(*FPackageName::FilenameToLongPackageName(PackageFile), AssetDataInPackage); for (const FAssetData& AssetData : AssetDataInPackage) { if (AssetData.AssetClass == UDialogueWave::StaticClass()->GetFName()) { MustLoadForGather = true; } } } // Add package to list of packages to load fully and process. if (MustLoadForGather) { PackageFileNamesToLoad.Add(PackageFile); } // Process immediately packages that don't require loading to process. else if (PackageFileSummary.GatherableTextDataOffset > 0) { FileReader->Seek(PackageFileSummary.GatherableTextDataOffset); TArray<FGatherableTextData> GatherableTextDataArray; GatherableTextDataArray.SetNum(PackageFileSummary.GatherableTextDataCount); for (int32 GatherableTextDataIndex = 0; GatherableTextDataIndex < PackageFileSummary.GatherableTextDataCount; ++GatherableTextDataIndex) { (*FileReader) << GatherableTextDataArray[GatherableTextDataIndex]; } ProcessGatherableTextDataArray(PackageFile, GatherableTextDataArray); } } } CollectGarbage(RF_NoFlags); //Now go through the remaining packages in the main array and process them in batches. int32 PackagesPerBatchCount = 100; TArray< UPackage* > LoadedPackages; TArray< FString > LoadedPackageFileNames; TArray< FString > FailedPackageFileNames; TArray< UPackage* > LoadedPackagesToProcess; const int32 PackageCount = PackageFileNamesToLoad.Num(); const int32 BatchCount = PackageCount / PackagesPerBatchCount + (PackageCount % PackagesPerBatchCount > 0 ? 1 : 0); // Add an extra batch for any remainder if necessary if(PackageCount > 0) { UE_LOG(LogGatherTextFromAssetsCommandlet, Log, TEXT("Loading %i packages in %i batches of %i."), PackageCount, BatchCount, PackagesPerBatchCount); } FLoadPackageLogOutputRedirector LogOutputRedirector; //Load the packages in batches int32 PackageIndex = 0; for( int32 BatchIndex = 0; BatchIndex < BatchCount; ++BatchIndex ) { int32 PackagesInThisBatch = 0; int32 FailuresInThisBatch = 0; for( ; PackageIndex < PackageCount && PackagesInThisBatch < PackagesPerBatchCount; ++PackageIndex ) { FString PackageFileName = PackageFileNamesToLoad[PackageIndex]; UE_LOG(LogGatherTextFromAssetsCommandlet, Verbose, TEXT("Loading package: '%s'."), *PackageFileName); UPackage *Package = nullptr; { FString LongPackageName; if (!FPackageName::TryConvertFilenameToLongPackageName(PackageFileName, LongPackageName)) { LongPackageName = FPaths::GetCleanFilename(PackageFileName); } FLoadPackageLogOutputRedirector::FScopedCapture ScopedCapture(&LogOutputRedirector, LongPackageName); Package = LoadPackage( NULL, *PackageFileName, LOAD_NoWarn | LOAD_Quiet ); } if( Package ) { LoadedPackages.Add(Package); LoadedPackageFileNames.Add(PackageFileName); // Because packages may not have been resaved after this flagging was implemented, we may have added packages to load that weren't flagged - potential false positives. // The loading process should have reflagged said packages so that only true positives will have this flag. if( Package->RequiresLocalizationGather() ) { LoadedPackagesToProcess.Add( Package ); } } else { FailedPackageFileNames.Add( PackageFileName ); ++FailuresInThisBatch; continue; } ++PackagesInThisBatch; } UE_LOG(LogGatherTextFromAssetsCommandlet, Log, TEXT("Loaded %i packages in batch %i of %i. %i failed."), PackagesInThisBatch, BatchIndex + 1, BatchCount, FailuresInThisBatch); ProcessPackages(LoadedPackagesToProcess); LoadedPackagesToProcess.Empty(PackagesPerBatchCount); if( bFixBroken ) { for( int32 LoadedPackageIndex=0; LoadedPackageIndex < LoadedPackages.Num() ; ++LoadedPackageIndex ) { UPackage *Package = LoadedPackages[LoadedPackageIndex]; const FString PackageName = LoadedPackageFileNames[LoadedPackageIndex]; //Todo - link with source control. if( Package ) { if( Package->IsDirty() ) { if( SavePackageHelper( Package, *PackageName ) ) { UE_LOG(LogGatherTextFromAssetsCommandlet, Log, TEXT("Saved Package %s."),*PackageName); } else { //TODO - Work out how to integrate with source control. The code from the source gatherer doesn't work. UE_LOG(LogGatherTextFromAssetsCommandlet, Log, TEXT("Could not save package %s. Probably due to source control. "),*PackageName); } } } else { UE_LOG(LogGatherTextFromAssetsCommandlet, Warning, TEXT("Failed to find one of the loaded packages.")); } } } CollectGarbage(RF_NoFlags); LoadedPackages.Empty(PackagesPerBatchCount); LoadedPackageFileNames.Empty(PackagesPerBatchCount); } return 0; }
void UGameplayDebuggingComponent::CollectEQSData() { #if USE_EQS_DEBUGGER if (!ShouldReplicateData(EAIDebugDrawDataView::EQS)) { return; } UWorld* World = GetWorld(); UEnvQueryManager* QueryManager = World ? UEnvQueryManager::GetCurrent(World) : NULL; const AActor* Owner = GetSelectedActor(); AGameplayDebuggingReplicator* Replicator = Cast<AGameplayDebuggingReplicator>(GetOwner()); if (QueryManager == NULL || Owner == NULL) { return; } auto AllQueries = QueryManager->GetDebugger().GetAllQueriesForOwner(Owner); const class APawn* OwnerAsPawn = Cast<class APawn>(Owner); if (OwnerAsPawn != NULL && OwnerAsPawn->GetController()) { const auto& AllControllerQueries = QueryManager->GetDebugger().GetAllQueriesForOwner(OwnerAsPawn->GetController()); AllQueries.Append(AllControllerQueries); } struct FEnvQueryInfoSort { FORCEINLINE bool operator()(const FEQSDebugger::FEnvQueryInfo& A, const FEQSDebugger::FEnvQueryInfo& B) const { return (A.Timestamp < B.Timestamp); } }; TArray<FEQSDebugger::FEnvQueryInfo> QueriesToSort = AllQueries; QueriesToSort.Sort(FEnvQueryInfoSort()); //sort queries by timestamp QueriesToSort.SetNum(FMath::Min<int32>(Replicator->MaxEQSQueries, AllQueries.Num())); for (int32 Index = AllQueries.Num() - 1; Index >= 0; --Index) { auto &CurrentQuery = AllQueries[Index]; if (QueriesToSort.Find(CurrentQuery) == INDEX_NONE) { AllQueries.RemoveAt(Index); } } EQSLocalData.Reset(); for (int32 Index = 0; Index < FMath::Min<int32>(Replicator->MaxEQSQueries, AllQueries.Num()); ++Index) { EQSDebug::FQueryData* CurrentLocalData = NULL; CachedQueryInstance = AllQueries[Index].Instance; const float CachedTimestamp = AllQueries[Index].Timestamp; if (!CurrentLocalData) { EQSLocalData.AddZeroed(); CurrentLocalData = &EQSLocalData[EQSLocalData.Num()-1]; } UEnvQueryDebugHelpers::QueryToDebugData(CachedQueryInstance.Get(), *CurrentLocalData); CurrentLocalData->Timestamp = AllQueries[Index].Timestamp; } TArray<uint8> UncompressedBuffer; FMemoryWriter ArWriter(UncompressedBuffer); ArWriter << EQSLocalData; const int32 UncompressedSize = UncompressedBuffer.Num(); const int32 HeaderSize = sizeof(int32); EQSRepData.Init(0, HeaderSize + FMath::TruncToInt(1.1f * UncompressedSize)); int32 CompressedSize = EQSRepData.Num() - HeaderSize; uint8* DestBuffer = EQSRepData.GetData(); FMemory::Memcpy(DestBuffer, &UncompressedSize, HeaderSize); DestBuffer += HeaderSize; FCompression::CompressMemory((ECompressionFlags)(COMPRESS_ZLIB | COMPRESS_BiasMemory), (void*)DestBuffer, CompressedSize, (void*)UncompressedBuffer.GetData(), UncompressedSize); EQSRepData.SetNum(CompressedSize + HeaderSize, false); if (World && World->GetNetMode() != NM_DedicatedServer) { OnRep_UpdateEQS(); } #endif }