From 7c942a9a8c885c8d76543953c1547401a09739b7 Mon Sep 17 00:00:00 2001 From: Charles Pritchard Date: Mon, 3 Oct 2022 11:28:15 -0700 Subject: [PATCH 1/2] UE4-27-0 Blueprint tests with Json, WebSocket, Http and Media Output submodules --- UE4-27-0/Config/DefaultEngine.ini | 6 + UE4-27-0/Content/Main.umap | Bin 0 -> 245065 bytes UE4-27-0/Content/SimpleWebSocket.uasset | Bin 0 -> 210372 bytes .../Tests/JsonTest/FTEST_JsonTest.uasset | Bin 0 -> 417734 bytes .../FTEST_JsonTestBooleanStruct.uasset | Bin 0 -> 3564 bytes .../FTEST_JsonTestComplexStruct.uasset | Bin 0 -> 13305 bytes .../Content/Tests/NewLevelSequence.uasset | Bin 0 -> 39272 bytes UE4-27-0/Content/Tests/UnrealHelperTest.umap | Bin 0 -> 171958 bytes .../WebSocketTest/FTEST_WebSocketTest.uasset | Bin 0 -> 116186 bytes .../UnrealHelper/Private/UnrealHelper.cpp | 22 + .../Private/UnrealHelperBPLibrary.cpp | 180 +++ .../Source/UnrealHelper/Public/UnrealHelper.h | 14 + .../Public/UnrealHelperBPLibrary.h | 45 + .../Source/UnrealHelper/UnrealHelper.Build.cs | 30 + .../Source/UnrealHttp/Private/UnrealHttp.cpp | 24 + .../Private/UnrealHttpBPLibrary.cpp | 176 +++ .../Source/UnrealHttp/Public/UnrealHttp.h | 15 + .../UnrealHttp/Public/UnrealHttpBPLibrary.h | 25 + .../Source/UnrealHttp/UnrealHttp.Build.cs | 29 + .../Source/UnrealJson/Private/UnrealJson.cpp | 15 + .../Private/UnrealJsonBPLibrary.cpp | 496 ++++++++ .../Source/UnrealJson/Public/UnrealJson.h | 12 + .../UnrealJson/Public/UnrealJsonBPLibrary.h | 205 ++++ .../Source/UnrealJson/UnrealJson.Build.cs | 30 + .../Private/SocketMediaCapture.cpp | 1038 +++++++++++++++++ .../Private/SocketMediaOutput.cpp | 167 +++ .../Private/UnrealMediaOutputSocket.cpp | 20 + .../Public/SocketMediaCapture.h | 64 + .../Public/SocketMediaOutput.h | 103 ++ .../Public/UnrealMediaOutputSocket.h | 13 + .../UnrealMediaOutputSocket.Build.cs | 28 + .../Private/UnrealWebSocket.cpp | 112 ++ .../Private/UnrealWebSockets.cpp | 24 + .../Private/UnrealWebSocketsBPLibrary.cpp | 14 + .../UnrealWebSockets/Public/UnrealWebSocket.h | 77 ++ .../Public/UnrealWebSockets.h | 15 + .../Public/UnrealWebSocketsBPLibrary.h | 17 + .../UnrealWebSockets.Build.cs | 34 + .../Plugins/UnrealHelper/UnrealHelper.uplugin | 54 + UE4-27-0/README.md | 11 + UE4-27-0/UnrealHelper.uproject | 16 + 41 files changed, 3131 insertions(+) create mode 100644 UE4-27-0/Config/DefaultEngine.ini create mode 100644 UE4-27-0/Content/Main.umap create mode 100644 UE4-27-0/Content/SimpleWebSocket.uasset create mode 100644 UE4-27-0/Content/Tests/JsonTest/FTEST_JsonTest.uasset create mode 100644 UE4-27-0/Content/Tests/JsonTest/FTEST_JsonTestBooleanStruct.uasset create mode 100644 UE4-27-0/Content/Tests/JsonTest/FTEST_JsonTestComplexStruct.uasset create mode 100644 UE4-27-0/Content/Tests/NewLevelSequence.uasset create mode 100644 UE4-27-0/Content/Tests/UnrealHelperTest.umap create mode 100644 UE4-27-0/Content/Tests/WebSocketTest/FTEST_WebSocketTest.uasset create mode 100644 UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/Private/UnrealHelper.cpp create mode 100644 UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/Private/UnrealHelperBPLibrary.cpp create mode 100644 UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/Public/UnrealHelper.h create mode 100644 UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/Public/UnrealHelperBPLibrary.h create mode 100644 UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/UnrealHelper.Build.cs create mode 100644 UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/Private/UnrealHttp.cpp create mode 100644 UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/Private/UnrealHttpBPLibrary.cpp create mode 100644 UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/Public/UnrealHttp.h create mode 100644 UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/Public/UnrealHttpBPLibrary.h create mode 100644 UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/UnrealHttp.Build.cs create mode 100644 UE4-27-0/Plugins/UnrealHelper/Source/UnrealJson/Private/UnrealJson.cpp create mode 100644 UE4-27-0/Plugins/UnrealHelper/Source/UnrealJson/Private/UnrealJsonBPLibrary.cpp create mode 100644 UE4-27-0/Plugins/UnrealHelper/Source/UnrealJson/Public/UnrealJson.h create mode 100644 UE4-27-0/Plugins/UnrealHelper/Source/UnrealJson/Public/UnrealJsonBPLibrary.h create mode 100644 UE4-27-0/Plugins/UnrealHelper/Source/UnrealJson/UnrealJson.Build.cs create mode 100644 UE4-27-0/Plugins/UnrealHelper/Source/UnrealMediaOutputSocket/Private/SocketMediaCapture.cpp create mode 100644 UE4-27-0/Plugins/UnrealHelper/Source/UnrealMediaOutputSocket/Private/SocketMediaOutput.cpp create mode 100644 UE4-27-0/Plugins/UnrealHelper/Source/UnrealMediaOutputSocket/Private/UnrealMediaOutputSocket.cpp create mode 100644 UE4-27-0/Plugins/UnrealHelper/Source/UnrealMediaOutputSocket/Public/SocketMediaCapture.h create mode 100644 UE4-27-0/Plugins/UnrealHelper/Source/UnrealMediaOutputSocket/Public/SocketMediaOutput.h create mode 100644 UE4-27-0/Plugins/UnrealHelper/Source/UnrealMediaOutputSocket/Public/UnrealMediaOutputSocket.h create mode 100644 UE4-27-0/Plugins/UnrealHelper/Source/UnrealMediaOutputSocket/UnrealMediaOutputSocket.Build.cs create mode 100644 UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/Private/UnrealWebSocket.cpp create mode 100644 UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/Private/UnrealWebSockets.cpp create mode 100644 UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/Private/UnrealWebSocketsBPLibrary.cpp create mode 100644 UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/Public/UnrealWebSocket.h create mode 100644 UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/Public/UnrealWebSockets.h create mode 100644 UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/Public/UnrealWebSocketsBPLibrary.h create mode 100644 UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/UnrealWebSockets.Build.cs create mode 100644 UE4-27-0/Plugins/UnrealHelper/UnrealHelper.uplugin create mode 100644 UE4-27-0/README.md create mode 100644 UE4-27-0/UnrealHelper.uproject diff --git a/UE4-27-0/Config/DefaultEngine.ini b/UE4-27-0/Config/DefaultEngine.ini new file mode 100644 index 0000000..4f3b445 --- /dev/null +++ b/UE4-27-0/Config/DefaultEngine.ini @@ -0,0 +1,6 @@ + + +[/Script/EngineSettings.GameMapsSettings] +GameDefaultMap=/Game/Main.Main +EditorStartupMap=/Game/Main.Main + diff --git a/UE4-27-0/Content/Main.umap b/UE4-27-0/Content/Main.umap new file mode 100644 index 0000000000000000000000000000000000000000..a691757cd161fee63490270074506baf6e794246 GIT binary patch literal 245065 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 literal 0 HcmV?d00001 diff --git a/UE4-27-0/Content/Tests/JsonTest/FTEST_JsonTest.uasset b/UE4-27-0/Content/Tests/JsonTest/FTEST_JsonTest.uasset new file mode 100644 index 0000000000000000000000000000000000000000..bca93925e6bb27ab141a16c7deae59fe6e4eff09 GIT binary patch literal 417734 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 G+5ZE&IHl15 literal 0 HcmV?d00001 diff --git a/UE4-27-0/Content/Tests/JsonTest/FTEST_JsonTestBooleanStruct.uasset b/UE4-27-0/Content/Tests/JsonTest/FTEST_JsonTestBooleanStruct.uasset new file mode 100644 index 0000000000000000000000000000000000000000..06a7af00f70ed71bc9d4827c5a53108f4940db1c GIT binary patch literal 3564 zcma)9du$X%7$0nbVgZ2`@C5?m16umHyV4dC;O_RWT%}O#9S}8?z24BSTz8M%J*6n7 z3L;jCDOAuPBqb!opwa~Si$tsu6O0BmQKATF1cHskM+hnw>ilMRmTT{z{L<|=^S$Pq zZ|0ks>)tqX&%b?reXFtv8F~ld0GV(0o@kZ2{Acsqw;NL?O?;5?E;V(X`_4Md0_v6s>!FDwBA?Q7~Bp6W|Ijd zi&S^6A$hDi$JY2^<;xd&h2>PNGxR5x2l zsOuMHJmW?sO*I2C#nhIlA=NNtwSkh3&UquoKp0TvXq>uZ%avFoHOVK>tsKpbEPhQg zZYqn|;9N-_TiLRE}B$ml6W)f|>#uu?4bIfO#-6NTS zq!@{~+_IQ0Bw7FF1s|LQVpY1FXcBSr0Xm=YXt`X*QmRX`DU**E?*AII4yegyXVyzk z?p`ns%vwe5A7b!iR>j?!By;BQx@nKR_9ff}b%m<2xD`^?vCnhw2lE!2sx7%=GnS$% zsl z{G=QGMOuR#SJum>qN(t0BxJTN$C)i#uq|yPCyL#L`zWGdspKok7vhyEOTR#U*J-QG z0fRsJ*aug!rmWbUfaZ4V(-EgtfDXHaywiKH!)9qxP!JL|cwMsS$f}&9=ee_F)Y*w& zT{>8X#jU%+vx~PUZ}0oq>|)P2CevPg;w<)*5Tuxrh2K223qfR%*>1OAIG>AjhFM{m zN`f5j>7$|_=KbLxVRn&_YPwy{?9LQcR3mW_Rau*)NOUMhste= z0E!p*j~%3UT1}EkhKPWHva8Gvhc7TthD*$4i5%G!yALAt1x=ON_nxDZDr5H|$2I2P zZgO&u-NDJQ&u-&w{e9UD(pRi5kLFYa&8PJ}_TkLKX$+P=6Bd`HdeOeqst`8Vn z_(m?a*-HMDao|h%6FvsgOyl&Xj01bD5h(UZo}JupQ^sNJn?j7AX&l6jX9Vc203Vra zVX(vYJPR4tgXv}VF6J!i88PB?03NUikDoU&5gZS|!xkYpCIP{>dMW>Bgh#&~k4kxO z?P*=R^`Q1Uo@c2*1pTt}(~aGgz5v2nPb@}VtZuTcL?QU9J!fU}`3Wc^p zS}}o-QyNI$=OX-ci5MBTEP!V+AeI()AO~KwfGCZ0SNL56q)Ucbf(#N-?-`e|$TrI; N6oCs0-EQ_f?|&)xgdP9@ literal 0 HcmV?d00001 diff --git a/UE4-27-0/Content/Tests/JsonTest/FTEST_JsonTestComplexStruct.uasset b/UE4-27-0/Content/Tests/JsonTest/FTEST_JsonTestComplexStruct.uasset new file mode 100644 index 0000000000000000000000000000000000000000..ea565f69a4316ab3cfda83e6d1fa409b9c6f68cf GIT binary patch literal 13305 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 literal 0 HcmV?d00001 diff --git a/UE4-27-0/Content/Tests/NewLevelSequence.uasset b/UE4-27-0/Content/Tests/NewLevelSequence.uasset new file mode 100644 index 0000000000000000000000000000000000000000..9206fbb7481e90698fc08c4d1693e04bc77fba6b GIT binary patch literal 39272 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 RmNVRyNoC33Tzt#V{vTyRZwCMX literal 0 HcmV?d00001 diff --git a/UE4-27-0/Content/Tests/UnrealHelperTest.umap b/UE4-27-0/Content/Tests/UnrealHelperTest.umap new file mode 100644 index 0000000000000000000000000000000000000000..699b21b2a68d7645eb798dfae7e159e9d411b81a GIT binary patch literal 171958 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 literal 0 HcmV?d00001 diff --git a/UE4-27-0/Content/Tests/WebSocketTest/FTEST_WebSocketTest.uasset b/UE4-27-0/Content/Tests/WebSocketTest/FTEST_WebSocketTest.uasset new file mode 100644 index 0000000000000000000000000000000000000000..63791eb036873a3ae0197b6be31e654429759dea GIT binary patch literal 116186 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 + *Section, + *Key, + String, + GGameIni + ); +} + +void UUnrealHelperBPLibrary::GetProjectVersion(FString& ProjectVersion) +{ + GConfig->GetString( + TEXT("/Script/EngineSettings.GeneralProjectSettings"), + TEXT("ProjectVersion"), + ProjectVersion, + GGameIni + ); +} + +void UUnrealHelperBPLibrary::GetFloatAsStringWithPrecision(float InFloat, FString& ReturnValue, int32 Precision, bool IncludeLeadingZero) +{ + FNumberFormattingOptions NumberFormat; + NumberFormat.MinimumIntegralDigits = (IncludeLeadingZero) ? 1 : 0; + NumberFormat.MaximumIntegralDigits = 10000; + NumberFormat.MinimumFractionalDigits = Precision; + NumberFormat.MaximumFractionalDigits = Precision; + ReturnValue = FText::AsNumber(InFloat, &NumberFormat).ToString(); +} + +FString UUnrealHelperBPLibrary::RunCommand(FString Cmd, FString Args, FString& StdErr) +{ + FString Result; + int32 ExitCode; + // example (on mac) + // FPlatformProcess::ExecProcess(TEXT("/usr/bin/curl"), TEXT("-XPOST localhost:4443"), &ExitCode, &Result, &StdErr); + // this may be poorly implemented in windows, running sleep instead of blocking on read. + FPlatformProcess::ExecProcess(*Cmd, *Args, &ExitCode, &Result, &StdErr); + return Result; +} + +void UUnrealHelperBPLibrary::ListFiles(FString Directory, FString FileExtension, TArray& Files) +{ + IFileManager& FileManager = IFileManager::Get(); + FPaths::NormalizeDirectoryName(Directory); + FileManager.FindFiles(Files, *Directory, *FileExtension); +} + +void UUnrealHelperBPLibrary::ExportRenderTargetAsBuffer(UTextureRenderTarget2D* RenderTarget, bool& bSuccess, TArray& Buffer) +{ + // From FImageUtils + bSuccess = false; + + if(RenderTarget->GetFormat() != PF_B8G8R8A8) + { + return; + } + + check(RenderTarget != nullptr); + + FRenderTarget* SafeRenderTarget = RenderTarget->GameThread_GetRenderTargetResource(); + + FIntPoint Size = SafeRenderTarget->GetSizeXY(); + + TArray RawData; + EPixelFormat Format = RenderTarget->GetFormat(); + int32 ImageBytes = 32 * Size.X * Size.Y; // CalculateImageBytes(Size.X, Size.Y, 0, Format); + RawData.AddUninitialized(ImageBytes); + bSuccess = SafeRenderTarget->ReadPixelsPtr((FColor*) RawData.GetData()); + + IImageWrapperModule& ImageWrapperModule = FModuleManager::Get().LoadModuleChecked(TEXT("ImageWrapper")); + + TSharedPtr PNGImageWrapper = ImageWrapperModule.CreateImageWrapper(EImageFormat::PNG); + + PNGImageWrapper->SetRaw(RawData.GetData(), RawData.GetAllocatedSize(), Size.X, Size.Y, ERGBFormat::BGRA, 8); + + Buffer = PNGImageWrapper->GetCompressed(100); + + bSuccess = true; + +} + +void UUnrealHelperBPLibrary::GetClipboardAsString(FString& String) +{ + FPlatformApplicationMisc::ClipboardPaste(String); +} + +void UUnrealHelperBPLibrary::MountPak(const FString PakFilename, const FString ProjectFolder, const FString ContentFolder) +{ + // Asset Registry + FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked("AssetRegistry"); + IAssetRegistry& AssetRegistry = AssetRegistryModule.Get(); + + // Virtual Filesystem + const TCHAR* PakTypeName = FPakPlatformFile::GetTypeName(); + + FPlatformFileManager* PlatformFileManager = &FPlatformFileManager::Get(); + IPlatformFile* PlatformFile = PlatformFileManager->FindPlatformFile(PakTypeName); + + FPakPlatformFile* PakPlatformFile = static_cast(PlatformFile); + if (PakPlatformFile == nullptr) + { + PakPlatformFile = static_cast(PlatformFileManager->GetPlatformFile(PakTypeName)); // new FPakPlatformFile(); + PakPlatformFile->Initialize(&PlatformFileManager->GetPlatformFile(), PakTypeName); + PakPlatformFile->InitializeNewAsyncIO(); + PlatformFileManager->SetPlatformFile(*PakPlatformFile); + } + + // Mount Pak at /GRACE// then link appropriately to /Game// + // if(PakFile->GetIsMounted()) UnRegisterMountPoint + + FString StandardFilename(PakFilename); + FPaths::MakeStandardFilename(StandardFilename); + FString BaseFilename = FPaths::GetBaseFilename(StandardFilename); + FString MountPoint = FString::Format(TEXT("/GRACE/{0}/"), {BaseFilename}); + FString IgnoreEngine = FString::Format(TEXT("{0}Engine/"), {MountPoint}); + FString OptionalProjectFolder = ProjectFolder.IsEmpty() ? ProjectFolder : FString::Format(TEXT("{0}/"), {ProjectFolder}); + FString PakContentFolder = FString::Format(TEXT("/{0}Content/{1}/"), {OptionalProjectFolder, ContentFolder}); + FString GraceContentMount = FString::Format(TEXT("{0}{1}Content/{2}/"), {MountPoint, OptionalProjectFolder, ContentFolder}); + FString GameContentFolder = FString::Format(TEXT("/Game/{0}/"), {ContentFolder}); + + if (!FPaths::FileExists(*StandardFilename)) + { + UE_LOG(LogTemp, Warning, TEXT("Could not find pak file: %s"), *StandardFilename); + return; + } + + FPakFile* PakFile = new FPakFile(PakPlatformFile, *StandardFilename, false); + if (!PakFile->IsValid()) + { + UE_LOG(LogTemp, Warning, TEXT("Invalid pak file: %s"), *StandardFilename); + return; + } + + PakFile->SetMountPoint(*MountPoint); + + if(!PakFile->DirectoryExistsInPruned(*GraceContentMount)) + { + UE_LOG(LogTemp, Warning, TEXT("Content folder not found in Pak File: %s"), *GraceContentMount); + return; + } + + if (!PakPlatformFile->Mount(*PakFilename, 0, *MountPoint)) + { + UE_LOG(LogTemp, Warning, TEXT("Failed to mount: %s"), *MountPoint); + return; + } + + FPackageName::RegisterMountPoint(GameContentFolder, GraceContentMount); + TArray< FString > ContentPaths; + ContentPaths.Add(GameContentFolder); + AssetRegistry.ScanPathsSynchronous(ContentPaths); +} \ No newline at end of file diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/Public/UnrealHelper.h b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/Public/UnrealHelper.h new file mode 100644 index 0000000..da10856 --- /dev/null +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/Public/UnrealHelper.h @@ -0,0 +1,14 @@ +// Copyright 2020 Disney Direct-to-Consumer and International. All Rights Reserved. + +#pragma once + +#include "Modules/ModuleManager.h" + +class FUnrealHelperModule : public IModuleInterface +{ +public: + + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; +}; diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/Public/UnrealHelperBPLibrary.h b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/Public/UnrealHelperBPLibrary.h new file mode 100644 index 0000000..0c0216a --- /dev/null +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/Public/UnrealHelperBPLibrary.h @@ -0,0 +1,45 @@ +// Copyright 2020 Disney Direct-to-Consumer and International. All Rights Reserved. + +#pragma once + +#include "Kismet/BlueprintFunctionLibrary.h" +#include "Runtime/Core/Public/Misc/ConfigCacheIni.h" +#include "Engine/TextureRenderTarget2D.h" +#include "IImageWrapper.h" +#include "HAL/PlatformApplicationMisc.h" +#include "HAL/FileManager.h" +#include "UnrealHelperBPLibrary.generated.h" + +// class UTextureRenderTarget2D; + +UCLASS() +class UUnrealHelperBPLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_UCLASS_BODY() + + UFUNCTION(BlueprintPure, meta = (DisplayName = "Get String from Game Config", Keywords = "Config"), Category = "Unreal Helper BP Library") + static void GetStringFromGameConfig(const FString Section, const FString Key, bool& Succeeded, FString& String); + + UFUNCTION(BlueprintPure, meta = (DisplayName = "Get Project Version from Game Config", Keywords = "Config"), Category = "Unreal Helper BP Library") + static void GetProjectVersion(FString& ProjectVersion); + + UFUNCTION(BlueprintPure, meta = (DisplayName = "Get Float as String Rounded to Precision", Keywords = "Math"), Category = "Unreal Helper BP Library") + static void GetFloatAsStringWithPrecision(float InFloat, FString& ReturnValue, int32 Precision = 2, bool IncludeLeadingZero = true); + + // Intended to block execution of rendering while it waits. + UFUNCTION(BlueprintCallable, meta = (DisplayName = "Blocking External Command", Keywords = "Shell"), Category = "Unreal Helper BP Library") + static FString RunCommand(FString Cmd, FString Params, FString& StdErr); + + UFUNCTION(BlueprintCallable, meta = (DisplayName = "List Files", Keywords = "File System"), Category = "Unreal Helper BP Library") + static void ListFiles(FString Directory, FString FileExtension, TArray& Files); + + UFUNCTION(BlueprintCallable, meta = (DisplayName = "Export Render Target as Buffer", Keywords = "Media"), Category = "Unreal Helper BP Library") + static void ExportRenderTargetAsBuffer(UTextureRenderTarget2D* RenderTarget, bool& bSuccess, TArray& Buffer); + + UFUNCTION(BlueprintCallable, meta = (DisplayName = "Get Clipboard as String", Keywords = "Clipboard"), Category = "Unreal Helper BP Library") + static void GetClipboardAsString(FString& String); + + UFUNCTION(BlueprintCallable, meta = (DisplayName = "Mount Pak", Keywords = "File System"), Category = "Unreal Helper BP Library") + static void MountPak(const FString PakFilename, const FString ProjectFolder, const FString ContentFolder); + +}; diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/UnrealHelper.Build.cs b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/UnrealHelper.Build.cs new file mode 100644 index 0000000..844ea7e --- /dev/null +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/UnrealHelper.Build.cs @@ -0,0 +1,30 @@ +// Copyright 2020 Disney Direct-to-Consumer and International. All Rights Reserved. + +using UnrealBuildTool; + +public class UnrealHelper : ModuleRules +{ + public UnrealHelper(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + } + ); + + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "ApplicationCore", + "CoreUObject", + "Engine", + "PakFile" + } + ); + + } +} diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/Private/UnrealHttp.cpp b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/Private/UnrealHttp.cpp new file mode 100644 index 0000000..cbe0149 --- /dev/null +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/Private/UnrealHttp.cpp @@ -0,0 +1,24 @@ +// Copyright 2020 Disney Direct-to-Consumer and International. All Rights Reserved. + +#include "UnrealHttp.h" + +#define LOCTEXT_NAMESPACE "FUnrealHttpModule" + +void FUnrealHttpModule::StartupModule() +{ + // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module + +} + +void FUnrealHttpModule::ShutdownModule() +{ + // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, + // we call this function before unloading the module. + //UE_LOG("") + //FModuleManager::UnloadModule("WebSockets"); + +} + +#undef LOCTEXT_NAMESPACE + +IMPLEMENT_MODULE(FUnrealHttpModule, UnrealHttp) \ No newline at end of file diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/Private/UnrealHttpBPLibrary.cpp b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/Private/UnrealHttpBPLibrary.cpp new file mode 100644 index 0000000..d8965df --- /dev/null +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/Private/UnrealHttpBPLibrary.cpp @@ -0,0 +1,176 @@ +#include "UnrealHttpBPLibrary.h" +#include "UnrealHttp.h" +#include "Runtime/Online/HTTP/Public/Http.h" +#include "HAL/IPlatformFileModule.h" + +UUnrealHttpBPLibrary::UUnrealHttpBPLibrary(const FObjectInitializer& ObjectInitializer) +: Super(ObjectInitializer) +{ +} + +void UUnrealHttpBPLibrary::GetHttpFile(const FString Url, const FString Filename, const FHttpOnErrorSignature& OnError, const bool ResumeIfExisting, const int64 ChunkSizeBytes) +{ + FHttpModule& HttpModule = FModuleManager::LoadModuleChecked("HTTP"); + TSharedRef Request = HttpModule.Get().CreateRequest(); + + FString StandardFilename(Filename); + FPaths::MakeStandardFilename(StandardFilename); + + FString Directory = FPaths::GetPath(StandardFilename); + IFileManager* FileManager = &IFileManager::Get(); + + if (FileManager->DirectoryExists(*Directory) == false) + { + UE_LOG(LogTemp, Warning, TEXT("Folder does not exist: %s"), *Directory); + return; + } + + int64 StartRangeAt = 0; + if (ResumeIfExisting && FileManager->FileExists(*StandardFilename) != false) + { + int64 CurrentFileSize = FileManager->FileSize(*StandardFilename); + if(CurrentFileSize > 0) StartRangeAt = CurrentFileSize; + } + + FString BytesRangeString = FString::Printf(TEXT("%lld"), StartRangeAt); + FString ChunkSizeString = ChunkSizeBytes > 0 ? FString::Printf(TEXT("%lld"), StartRangeAt + ChunkSizeBytes - 1) : FString(""); + FString RequestRange = FString::Format(TEXT("bytes={0}-{1}"), {BytesRangeString, ChunkSizeString}); + FString ExpectRange = FString::Format(TEXT("bytes {0}-"), {BytesRangeString, ChunkSizeString}); + + Request->SetURL(Url); + Request->SetVerb("GET"); + + /* + * HTTP Range Requests are a work-around to limit memory use as stream to file is unsupported in FHttpModule. + * The Unreal curl implementation adds "Accept-Encoding: "deflate, gzip" and will transparently decompresses the buffer. + * Servers which support such headers will ignore the Range header. + */ + if(StartRangeAt > 0 || ChunkSizeBytes > 0) + { + Request->SetHeader(TEXT("Range"), RequestRange); + } + bool bAppend = StartRangeAt > 0; + bool bAllowRead = false; + + // progress indicator does not do much for us + if(false) + Request->OnRequestProgress().BindLambda([](FHttpRequestPtr HttpRequest, int32 BytesSent, int32 BytesReceived) { + FHttpResponsePtr HttpResponse = HttpRequest->GetResponse(); + if(!HttpResponse.IsValid()) { + UE_LOG(LogTemp, Warning, TEXT("Invalid HTTP Request")); + return; + } + UE_LOG(LogTemp, Warning, TEXT("Progressing: %d"), BytesReceived); + /* + * The main HTTP client implementation is hard coded to expand its write buffer to the full size of the result: + * FCurlHttpRequest::ReceiveResponseBodyCallback uses FMemory::Memcpy with TotalBytesRead to offset the write location. + * + * We can start writing the file to disk but we can not safely clear its memory buffer. + */ + // TArray Content = HttpResponse->GetContent(); + // + // bool bSuccess = OutputFile->Write(&Content[0], Content.Num()); + // UE_LOG(LogTemp, Warning, TEXT("Current position Request: %d"), Content.Num()); + // We can't clear the buffer as it is marked private + // HttpResponse.TotalBytesRead.SetValue(0); Content.Reset(); + }); + + Request->OnProcessRequestComplete().BindLambda( + [StandardFilename, bAppend, StartRangeAt, ChunkSizeBytes, ExpectRange, Url, Filename, OnError] + (FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded) + { + int32 HttpCode = HttpResponse->GetResponseCode(); + UE_LOG(LogTemp, Warning, TEXT("Final HTTP Status: %d"), HttpCode); + if(!EHttpResponseCodes::IsOk(HttpCode)) { + OnError.ExecuteIfBound(); + return; + } + + FString ContentRange = HttpResponse->GetHeader("Content-Range"); + int64 FullContentLength = 0; + // Assume HttpCode 206 + if(!ContentRange.IsEmpty()) + { + int32 MaxRangeSeparator = 0; + if(ContentRange.FindChar(TEXT('/'), MaxRangeSeparator) && ContentRange.StartsWith(ExpectRange, ESearchCase::CaseSensitive)) { + FString MaxRangePart = ContentRange.RightChop(MaxRangeSeparator+1); + if(MaxRangePart.IsNumeric()) + { + FullContentLength = FCString::Atoi64(*MaxRangePart); + } + else { + OnError.ExecuteIfBound(); + return; + } + } + else { + OnError.ExecuteIfBound(); + return; + } + } + + bool bAllowRead = false; + IFileHandle *OutputFile = IPlatformFile::GetPlatformPhysical().OpenWrite(*StandardFilename, bAppend, bAllowRead); + TArray Content = HttpResponse->GetContent(); + int64 CurrentPosition = StartRangeAt + Content.Num(); + bool bWriteSuccess = OutputFile->Write(&Content[0], Content.Num()); + OutputFile->Flush(true); + delete OutputFile; + + if(!bWriteSuccess) + { + OnError.ExecuteIfBound(); + return; + } + + if(Content.Num() > ChunkSizeBytes) + { + UE_LOG(LogTemp, Warning, TEXT("Range request ignored for chunk size: %d"), ChunkSizeBytes); + } + else if(HttpCode == 206 && FullContentLength > CurrentPosition) + { + bool ContinueWritingOutput = true; + UE_LOG(LogTemp, Warning, TEXT("Ready for Sub-Request: Range %d-%d/%d"), CurrentPosition, FullContentLength); + GetHttpFile(Url, Filename, OnError, ContinueWritingOutput, ChunkSizeBytes); + } + UE_LOG(LogTemp, Warning, TEXT("Finished Request: %d"), Content.Num()); + }); + Request->ProcessRequest(); + // IFileHandler *OutputFile = IPlatformFile::GetPlatformPhysical().DeleteFile(*StandardFilename); +} + +void UUnrealHttpBPLibrary::PutHttpFile(const FString Url, const FString Filename, const FHttpOnErrorSignature& OnError) +{ + FHttpModule& HttpModule = FModuleManager::LoadModuleChecked("HTTP"); + TSharedRef Request = HttpModule.Get().CreateRequest(); + + FString StandardFilename(Filename); + FPaths::MakeStandardFilename(StandardFilename); + + FString Directory = FPaths::GetPath(StandardFilename); + IFileManager* FileManager = &IFileManager::Get(); + + if (FileManager->FileExists(*StandardFilename) == false) + { + UE_LOG(LogTemp, Warning, TEXT("File does not exist: %s"), *Filename); + return; + } + + Request->SetURL(Url); + Request->SetVerb("PUT"); + Request->SetContentAsStreamedFile(StandardFilename); + Request->OnProcessRequestComplete().BindLambda([OnError](FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded) { + if (!HttpResponse.IsValid()) + { + OnError.ExecuteIfBound(); + return; + } + if (!EHttpResponseCodes::IsOk(HttpResponse->GetResponseCode())) { + UE_LOG(LogTemp, Warning, TEXT("Http returned error code: %d"), HttpResponse->GetResponseCode()); + OnError.ExecuteIfBound(); + return; + } + UE_LOG(LogTemp, Warning, TEXT("Finished Request")); + }); + Request->ProcessRequest(); +} diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/Public/UnrealHttp.h b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/Public/UnrealHttp.h new file mode 100644 index 0000000..e8fbcbe --- /dev/null +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/Public/UnrealHttp.h @@ -0,0 +1,15 @@ +// Copyright 2020 Disney Direct-to-Consumer and International. All Rights Reserved. + +#pragma once + +#include "Modules/ModuleManager.h" +// + +class FUnrealHttpModule : public IModuleInterface +{ +public: + + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; +}; diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/Public/UnrealHttpBPLibrary.h b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/Public/UnrealHttpBPLibrary.h new file mode 100644 index 0000000..fe55ec5 --- /dev/null +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/Public/UnrealHttpBPLibrary.h @@ -0,0 +1,25 @@ +// Copyright 2020 Disney Direct-to-Consumer and International. All Rights Reserved. + +#pragma once + +#include "Kismet/BlueprintFunctionLibrary.h" +#include "HAL/PlatformApplicationMisc.h" +#include "HAL/FileManager.h" +#include "UnrealHttp.h" +#include "UnrealHttpBPLibrary.generated.h" + +DECLARE_DYNAMIC_DELEGATE(FHttpOnCompleteSignature); +DECLARE_DYNAMIC_DELEGATE(FHttpOnErrorSignature); + +UCLASS() +class UUnrealHttpBPLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_UCLASS_BODY() + + UFUNCTION(BlueprintCallable, meta = (DisplayName = "Get Url as File", Keywords = "Http Url", AutoCreateRefTerm = "OnError"), Category = "Unreal HTTP") + static void GetHttpFile(const FString Url, const FString Filename, const FHttpOnErrorSignature& OnError, const bool Resumable = false, int64 ChunkSizeBytes = 0); + + UFUNCTION(BlueprintCallable, meta = (DisplayName = "Put File as Url", Keywords = "Http Url", AutoCreateRefTerm = "OnError"), Category = "Unreal HTTP") + static void PutHttpFile(const FString Url, const FString Filename, const FHttpOnErrorSignature& OnError); + +}; \ No newline at end of file diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/UnrealHttp.Build.cs b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/UnrealHttp.Build.cs new file mode 100644 index 0000000..9e96991 --- /dev/null +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/UnrealHttp.Build.cs @@ -0,0 +1,29 @@ +// Copyright 2020 Disney Direct-to-Consumer and International. All Rights Reserved. + +using UnrealBuildTool; + +public class UnrealHttp : ModuleRules +{ + public UnrealHttp(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + } + ); + + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "ApplicationCore", + "CoreUObject", + "Engine", + "HTTP" + } + ); + } +} diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealJson/Private/UnrealJson.cpp b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealJson/Private/UnrealJson.cpp new file mode 100644 index 0000000..b0e692b --- /dev/null +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealJson/Private/UnrealJson.cpp @@ -0,0 +1,15 @@ +#include "UnrealJson.h" + +#define LOCTEXT_NAMESPACE "FUnrealJsonModule" + +void FUnrealJsonModule::StartupModule() +{ +} + +void FUnrealJsonModule::ShutdownModule() +{ +} + +#undef LOCTEXT_NAMESPACE + +IMPLEMENT_MODULE(FUnrealJsonModule, UnrealJson) diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealJson/Private/UnrealJsonBPLibrary.cpp b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealJson/Private/UnrealJsonBPLibrary.cpp new file mode 100644 index 0000000..ae7c1d6 --- /dev/null +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealJson/Private/UnrealJsonBPLibrary.cpp @@ -0,0 +1,496 @@ +#include "UnrealJsonBPLibrary.h" +#include "UnrealJson.h" +#include "JsonObjectConverter.h" +#include "JsonObjectWrapper.h" +#include "Serialization/JsonTypes.h" + +UUnrealJsonBPLibrary::UUnrealJsonBPLibrary(const FObjectInitializer& ObjectInitializer) +: Super(ObjectInitializer) +{ + +} + +FString UUnrealJsonBPLibrary::ToJson( + UPARAM(ref) TFieldPath& Wildcard) +{ + check(0); + return FString(TEXT("undefined")); +} + +FString UUnrealJsonBPLibrary::ToJsonSchema( + UPARAM(ref) TFieldPath& Wildcard) +{ + check(0); + return FString(TEXT("undefined")); +} + +bool UUnrealJsonBPLibrary::FromJson( + UPARAM(ref) TFieldPath& Wildcard, + UPARAM(ref) FString& JsonString) +{ + check(0); + return false; +} +void UUnrealJsonBPLibrary::JsonObjectWrapper_ToObject(struct FJsonObjectWrapper JsonWrapper, + UPARAM(ref) TFieldPath& Wildcard +) +{ + check(0); + return; +} + +FString PropertyGetAuthoredName( + FProperty* Property +) +{ + return Property->GetAuthoredName(); +} + +// Serialize a UProperty to a JSON String maintaining key names for structures +void UUnrealJsonBPLibrary::PropertyPtrAsJsonString( + FProperty* Property, + void* Ptr, FString& JsonString, const bool AsSchema) +{ + TSharedRef< TJsonWriter< TCHAR, TCondensedJsonPrintPolicy > > Writer = TJsonWriterFactory >::Create(&JsonString); + + if(FObjectProperty* ObjectProperty = CastField(Property) ) + { + // TODO: PropertyClass may be a result of Cast being called in the blueprint; we want to keep the cast if it's not just a blank UClass. + // UE_LOG(LogTemp, Warning, TEXT("Reflected class %s"), *ObjectProperty->PropertyClass->GetClass()->GetName()); + // This is the blueprint function where the variable is set. + // UE_LOG(LogTemp, Warning, TEXT("Reflected class %s"), *((UObject *) Property)->GetClass()->GetName()); + if(false && !ObjectProperty->HasAnyPropertyFlags(EPropertyFlags::CPF_PersistentInstance)) { + // Return an object reference as a string + TSharedPtr JsonValue = FJsonObjectConverter::UPropertyToJsonValue(ObjectProperty, Ptr, 0, 0, nullptr); + FJsonSerializer::Serialize(JsonValue, FString(), Writer); + } + else + { + FJsonObject JsonObject = FJsonObject(); + // Struct Serialize does not have a flag to maintain authored key names + ObjectAsJsonObject(JsonObject, ObjectProperty, Ptr, AsSchema); + if(AsSchema) + { + FJsonObject TypedJsonObject = FJsonObject(); + FString RefId = FString::Format(TEXT("/GRACE/{0}"), {ObjectProperty->PropertyClass->GetName() }); + TypedJsonObject.SetStringField("$id", RefId); + TypedJsonObject.SetStringField("type", "object"); + TypedJsonObject.SetObjectField("properties", MakeShared(JsonObject)); + FJsonSerializer::Serialize(MakeShared(TypedJsonObject), Writer); + } + else + { + FJsonSerializer::Serialize(MakeShared(JsonObject), Writer); + } + } + } + + else if(FStructProperty* StructProperty = CastField(Property)) + { + FJsonObject JsonObject = FJsonObject(); + StructAsJsonObject(JsonObject, StructProperty, Ptr, AsSchema); + // Struct Serialize does not have a flag to maintain authored key names + if(AsSchema) + { + FJsonObject TypedJsonObject = FJsonObject(); + FString RefId = FString::Format(TEXT("/GRACE/{0}"), {StructProperty->Struct->GetClass()->GetName()}); + TypedJsonObject.SetStringField("$id", RefId); + TypedJsonObject.SetStringField("type", "object"); + TypedJsonObject.SetObjectField("properties", MakeShared(JsonObject)); + FJsonSerializer::Serialize(MakeShared(TypedJsonObject), Writer); + } + else + { + FJsonSerializer::Serialize(MakeShared(JsonObject), Writer); + } + } + else + { + TSharedPtr JsonValue = FJsonObjectConverter::UPropertyToJsonValue(Property, Ptr, 0, 0, nullptr); + FJsonSerializer::Serialize(JsonValue, FString(), Writer); + // WriteCommaIfNeeded does not check for PreviousTokenWritten != EJsonToken::None in WriteValue from JsonWriter.h + JsonString.RemoveFromStart(FString(","), ESearchCase::IgnoreCase); + } +} + +FString UUnrealJsonBPLibrary::GetJsonTypeString(EJson& JsonType) { + switch (JsonType) + { + case EJson::String: return "string"; + case EJson::Number: return "number"; + case EJson::Boolean: return "boolean"; + case EJson::Array: return "string"; + case EJson::Object: return "object"; + // None and Null + default: return "object"; + } +} + +// Convert a structure to JSON +void UUnrealJsonBPLibrary::PropertyAsJsonObject(FJsonObject& JsonObject, + FProperty* Property, + void* ValuePtr, const bool AsSchema) { + FString VariableName = PropertyGetAuthoredName(Property); + if(FArrayProperty *ArrayProperty = CastField(Property)) + { + FScriptArrayHelper Helper(ArrayProperty, ValuePtr); + int32 Len = Helper.Num(); + TArray> ValueJsonArray; + FJsonObject ValueJsonObject = FJsonObject(); + for(int32 Idx = 0; Idx < Len; ++Idx) + { + PropertyAsJsonObject(ValueJsonObject, ArrayProperty->Inner, Helper.GetRawPtr(Idx), AsSchema); + for(auto It = ValueJsonObject.Values.CreateConstIterator(); It; ++It) + { + ValueJsonArray.Add(It.Value()); + } + } + JsonObject.SetArrayField(VariableName, ValueJsonArray); + } + else if(FObjectProperty *ObjectProperty = CastField(Property)) + { + FJsonObject ValueJsonObject = FJsonObject(); + // Soft path references as string + if(false && !ObjectProperty->HasAnyPropertyFlags(EPropertyFlags::CPF_PersistentInstance)) { + TSharedPtr JsonValue = FJsonObjectConverter::UPropertyToJsonValue(ObjectProperty, ValuePtr, 0, 0, nullptr); + JsonObject.Values.Add(VariableName, JsonValue); + return; + } + ObjectAsJsonObject(ValueJsonObject, ObjectProperty, ValuePtr, AsSchema); + if(AsSchema) + { + FJsonObject TypedJsonObject = FJsonObject(); + FString RefId = FString::Format(TEXT("/GRACE/{0}//{1}"), {ObjectProperty->PropertyClass->GetFName().ToString(), ObjectProperty->GetNameCPP()}); + TypedJsonObject.SetStringField("$id", RefId); + TypedJsonObject.SetStringField("type", "object"); + TypedJsonObject.SetObjectField("properties", MakeShared(ValueJsonObject)); + JsonObject.SetObjectField(VariableName, MakeShared(TypedJsonObject)); + } + else + { + JsonObject.SetObjectField(VariableName, MakeShared(ValueJsonObject)); + } + } + else if(FStructProperty *SubProperty = CastField(Property)) + { + FJsonObject ValueJsonObject = FJsonObject(); + StructAsJsonObject(ValueJsonObject, SubProperty, ValuePtr, AsSchema); + if(AsSchema) + { + FJsonObject TypedJsonObject = FJsonObject(); + FString RefId = FString::Format(TEXT("/GRACE/{0}"), {SubProperty->Struct->GetName()}); + TypedJsonObject.SetStringField("$id", RefId); + TypedJsonObject.SetStringField("type", "object"); + TypedJsonObject.SetObjectField("properties", MakeShared(ValueJsonObject)); + JsonObject.SetObjectField(VariableName, MakeShared(TypedJsonObject)); + } + else + { + JsonObject.SetObjectField(VariableName, MakeShared(ValueJsonObject)); + } + } + else // if(CastField(Property) || CastField(Property) || CastField(Property) || CastField(Property) || CastField(Property)) + { + TSharedPtr JsonValue = FJsonObjectConverter::UPropertyToJsonValue(Property, ValuePtr, 0, 0, nullptr); + if (JsonValue.IsValid()) + { + if(AsSchema) + { + FJsonObject TypedJsonObject = FJsonObject(); + TypedJsonObject.SetStringField("type", GetJsonTypeString(JsonValue->Type)); + TypedJsonObject.SetField("example", JsonValue); + FString RefId = FString::Format(TEXT("/Unreal/{0}"), {Property->GetClass()->GetName()}); + TypedJsonObject.SetStringField("$id", RefId); + // Also FNumericProperty->IsEnum() + if(FByteProperty *EnumProperty = CastField(Property)) + { + UEnum* Enum = EnumProperty->GetIntPropertyEnum(); + TArray> ValueJsonArray; + for(int32 EnumIndex = 0; EnumIndex < Enum->NumEnums() - 1; ++EnumIndex) { + ValueJsonArray.Add(MakeShared(Enum->GetAuthoredNameStringByIndex(EnumIndex))); + } + TypedJsonObject.SetArrayField("enum", ValueJsonArray); + // FindObject is an interesting walk + TypedJsonObject.SetField("example", MakeShared(Enum->GetAuthoredNameStringByValue(EnumProperty->GetSignedIntPropertyValue(ValuePtr)))); + TypedJsonObject.SetStringField("$id", FString::Format(TEXT("/GRACE/{0}"), {Enum->GetName()})); + } + if(FEnumProperty *EnumProperty = CastField(Property)) + { + UEnum* Enum = EnumProperty->GetEnum(); + // this may just be for enums with more than 255 elements. + } + JsonObject.SetObjectField(VariableName, MakeShared(TypedJsonObject)); + } + else + { + JsonObject.Values.Add(VariableName, JsonValue); + } + } + } +/* + else + { + UE_LOG(LogTemp, Warning, TEXT("Unserialized JSON reflected class %s"), *Property->GetClass()->GetName()); + UE_LOG(LogTemp, Warning, TEXT("Unserialized JSON reflected name %s"), *Property->GetFName().GetPlainNameString()); + } +*/ + +} + +void UUnrealJsonBPLibrary::ObjectAsJsonObject(FJsonObject& JsonObject, + FObjectProperty* ObjectProperty, + void* ObjectPtr, const bool AsSchema) { + UObject* Object = ObjectProperty->GetObjectPropertyValue(ObjectPtr); + UClass* PropertyClass = Object->GetClass(); + for (TFieldIterator It(PropertyClass); It; ++It) + { + FProperty* Property = *It; + FString VariableName = PropertyGetAuthoredName(Property); + for(int32 Idx = 0; Idx < Property->ArrayDim; Idx++) + { + void* ValuePtr = Property->ContainerPtrToValuePtr((void*) Object, Idx); + PropertyAsJsonObject(JsonObject, Property, ValuePtr, AsSchema); + } + } +} + +void UUnrealJsonBPLibrary::StructAsJsonObject(FJsonObject& JsonObject, + FStructProperty* StructProperty, + void* StructPtr, const bool AsSchema) { + for (TFieldIterator It(StructProperty->Struct); It; ++It) + { + FProperty* Property = *It; + FString VariableName = PropertyGetAuthoredName(Property); + for(int32 Idx = 0; Idx < Property->ArrayDim; Idx++) + { + void* ValuePtr = Property->ContainerPtrToValuePtr(StructPtr, Idx); + PropertyAsJsonObject(JsonObject, Property, ValuePtr, AsSchema); + } + } +} + +// Convert JSON string into a structure +void UUnrealJsonBPLibrary::JsonAsProperty(TSharedPtr JsonObject, + FProperty* Property, + void* ValuePtr) { + FString VariableName = PropertyGetAuthoredName(Property); + if(FArrayProperty *ArrayProperty = CastField(Property)) + { + TArray> ValueJsonArray = JsonObject->Values[VariableName].Get()->AsArray(); + FScriptArrayHelper ValueArray(ArrayProperty, ValuePtr); + ValueArray.Resize(ValueJsonArray.Num()); + FJsonObject ValueJsonObject = FJsonObject(); + for(int32 Idx = 0; Idx < ValueJsonArray.Num(); ++Idx) + { + ValueJsonObject.Values.Add(VariableName, ValueJsonArray[Idx]); + void* SubValuePtr = ValueArray.GetRawPtr(Idx); + JsonAsProperty(MakeShared(ValueJsonObject), ArrayProperty->Inner, SubValuePtr); + } + } + else if(FObjectProperty *ObjectProperty = CastField(Property)) + { + // Allow soft reference strings + if(JsonObject->Values[VariableName].Get()->Type == EJson::String) + { + // The internal code does run: + // if(!ObjectProperty->HasAnyPropertyFlags(EPropertyFlags::CPF_PersistentInstance)) + // ObjectProperty->ImportText(*JsonObject->Values[VariableName].Get()->AsString(), ValuePtr, 0, NULL); + FJsonObjectConverter::JsonValueToUProperty(JsonObject->Values[VariableName], Property, ValuePtr, 0, 0); + } + else + { + TSharedPtr SubObject = JsonObject->Values[VariableName].Get()->AsObject(); + JsonAsObject(SubObject, ObjectProperty, ValuePtr); + } + } + else if(FStructProperty *SubProperty = CastField(Property)) + { + TSharedPtr SubObject = JsonObject->Values[VariableName].Get()->AsObject(); + JsonAsStruct(SubObject, SubProperty, ValuePtr); + } + else + { + FJsonObjectConverter::JsonValueToUProperty(JsonObject->Values[VariableName], Property, ValuePtr, 0, 0); + } +} + +void UUnrealJsonBPLibrary::JsonAsObject(TSharedPtr JsonObject, + FObjectProperty* ObjectProperty, + void* ObjectPtr) { + + UObject* Object = ObjectProperty->GetObjectPropertyValue(ObjectPtr); + // This could be an access violation + UClass* PropertyClass = Object->GetClass(); + + for (TFieldIterator It(PropertyClass); It; ++It) + { + FProperty* Property = *It; + if(!JsonObject->HasField(PropertyGetAuthoredName(Property))) continue; + for(int32 Idx = 0; Idx < Property->ArrayDim; Idx++) + { + void* ValuePtr = Property->ContainerPtrToValuePtr((void*) Object, Idx); + JsonAsProperty(JsonObject, Property, ValuePtr); + } + } +} + +void UUnrealJsonBPLibrary::JsonAsStruct(TSharedPtr JsonObject, + FStructProperty* StructProperty, + void* StructPtr) { + for (TFieldIterator It(StructProperty->Struct); It; ++It) + { + FProperty* Property = *It; + if(!JsonObject->HasField(PropertyGetAuthoredName(Property))) continue; + for(int32 Idx = 0; Idx < Property->ArrayDim; Idx++) + { + void* ValuePtr = Property->ContainerPtrToValuePtr(StructPtr, Idx); + JsonAsProperty(JsonObject, Property, ValuePtr); + } + } +} + +void UUnrealJsonBPLibrary::FromJson_Object(TSharedPtr JsonObject, + FProperty* WildcardProperty, + void* PropertyPtr) { + FObjectProperty* ObjectProperty = CastField(WildcardProperty); + FStructProperty* StructProperty = CastField(WildcardProperty); + if(ObjectProperty) + { + JsonAsObject(JsonObject, ObjectProperty, PropertyPtr); + } + else if(StructProperty) + { + JsonAsStruct(JsonObject, StructProperty, PropertyPtr); + } + else + { + JsonAsProperty(JsonObject, WildcardProperty, PropertyPtr); + } +} + +bool UUnrealJsonBPLibrary::FromJson_Generic( + FProperty* WildcardProperty, + void* PropertyPtr, FString& JsonString) +{ + FObjectProperty* ObjectProperty = CastField(WildcardProperty); + FStructProperty* StructProperty = CastField(WildcardProperty); + FString JsonObjectString = StructProperty || ObjectProperty ? JsonString : FString::Printf(TEXT("{\"%s\": %s}"), *PropertyGetAuthoredName(WildcardProperty), *JsonString); + TSharedRef> Reader = TJsonReaderFactory<>::Create(JsonObjectString); + TSharedPtr JsonObject; + if (FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid()) + { +/* + if(StructProperty && StructProperty->Struct == FJsonObjectWrapper::StaticStruct()) + { + UScriptStruct* Struct = StructProperty->Struct; + UE_LOG(LogTemp, Warning, TEXT("Reflection on %s not implemented"), *Struct->GetStructCPPName()); + return false; + } +*/ + FromJson_Object(JsonObject, WildcardProperty, PropertyPtr); + return true; + } + return false; +} + +FString UUnrealJsonBPLibrary::JsonObjectWrapper_ToString(struct FJsonObjectWrapper JsonWrapper, const bool PrettyPrint) +{ + if(!JsonWrapper.JsonObject.IsValid()) + { + return FString(); + } + FString JsonString; + TSharedRef< TJsonWriter< TCHAR, TCondensedJsonPrintPolicy > > Writer = TJsonWriterFactory >::Create(&JsonString); + FJsonSerializer::Serialize(JsonWrapper.JsonObject.ToSharedRef(), Writer); + return JsonString; +} + +bool UUnrealJsonBPLibrary::JsonObject_WithFieldPath(FJsonObject& JsonObject, const FString& WithFieldPath) { + TArray PathParts; + int32 PathLength = WithFieldPath.ParseIntoArray(PathParts, *FString("."), true); + if(PathLength == 0) + { + return true; + } + if(!JsonObject.HasField(PathParts[0])) + { + return false; + } + const TSharedPtr JsonPtr = MakeShared(JsonObject); + const TSharedPtr* CurrentPointer = &JsonPtr; + for(int32 Idx = 0; Idx < PathLength; Idx++) + { + if(!(*CurrentPointer)->TryGetObjectField(PathParts[Idx], CurrentPointer)) + { + // Allow the ending field to be any field type + if((Idx == PathLength - 1) && (*CurrentPointer)->HasField(PathParts[Idx])) + { + break; + } + else + { + return false; + } + } + } + JsonObject = *(*CurrentPointer).Get(); + return true; +} + +void UUnrealJsonBPLibrary::JsonWrapper_FromString(UPARAM(ref) FString& JsonString, const FString WithFieldPath, EJsonFieldExistsEnum& FieldExists, FJsonObjectWrapper& JsonWrapper) { + TSharedPtr JsonObject(new FJsonObject()); + JsonWrapper.JsonObject = JsonObject; + if(JsonString.Len() > 0) + { + TSharedRef> Reader = TJsonReaderFactory<>::Create(JsonString); + if(FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid()) { + if(WithFieldPath.Len() > 0) + { + FJsonObject Root = *JsonObject.Get(); + if(JsonObject_WithFieldPath(Root, WithFieldPath)) + { + (&JsonWrapper)->JsonObject = MakeShared(Root); + FieldExists = EJsonFieldExistsEnum::Changed; + } + else + { + FieldExists = EJsonFieldExistsEnum::NotChanged; + return; + } + } + else + { + (&JsonWrapper)->JsonObject = JsonObject; + FieldExists = EJsonFieldExistsEnum::Changed; + return; + } + } + else + { + FieldExists = EJsonFieldExistsEnum::NotChanged; + return; + } + } + else + { + FieldExists = EJsonFieldExistsEnum::NotChanged; + return; + } +} + +// undocumented; from source: DeterminesOutputType = "Parameter", DynamicOutputParam="Param" +// UFUNCTION(BlueprintCallable, Category="Utilities", meta=(DeterminesOutputType="Interface", DynamicOutputParam="OutActors")) +// static void GetAllActorsWithInterface(TSubclassOf Interface, TArray& OutActors); +void UUnrealJsonBPLibrary::JsonWrapper_FromField(struct FJsonObjectWrapper InJsonWrapper, FString WithFieldPath, EJsonFieldExistsEnum& FieldExists, FJsonObjectWrapper& OutJsonWrapper) { + // JsonObjectWrapper is poorly defined in UE 4.22 + OutJsonWrapper.JsonObject = InJsonWrapper.JsonObject.IsValid() ? InJsonWrapper.JsonObject : (TSharedPtr) (new FJsonObject()); + FJsonObject Root = *OutJsonWrapper.JsonObject.Get(); + if(JsonObject_WithFieldPath(Root, WithFieldPath)) + { + OutJsonWrapper.JsonObject = MakeShared(Root); + FieldExists = EJsonFieldExistsEnum::Changed; + return; + } + FieldExists = EJsonFieldExistsEnum::NotChanged; + return; +} \ No newline at end of file diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealJson/Public/UnrealJson.h b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealJson/Public/UnrealJson.h new file mode 100644 index 0000000..5d35b53 --- /dev/null +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealJson/Public/UnrealJson.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Modules/ModuleManager.h" + +class FUnrealJsonModule : public IModuleInterface +{ +public: + + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; +}; diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealJson/Public/UnrealJsonBPLibrary.h b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealJson/Public/UnrealJsonBPLibrary.h new file mode 100644 index 0000000..2694816 --- /dev/null +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealJson/Public/UnrealJsonBPLibrary.h @@ -0,0 +1,205 @@ +#pragma once + +#include "Kismet/BlueprintFunctionLibrary.h" +#include "UObject/ObjectMacros.h" +#include "JsonObjectConverter.h" +#include "JsonObjectWrapper.h" +#include "Runtime/Core/Public/Misc/ConfigCacheIni.h" +#include "Runtime/Launch/Resources/Version.h" +#include "Runtime/Json/Public/Policies/CondensedJsonPrintPolicy.h" +#include "UnrealJsonBPLibrary.generated.h" + +UENUM(BlueprintType) +enum class EJsonFieldExistsEnum : uint8 +{ + Changed UMETA(DisplayName = "Changed"), + NotChanged UMETA(DisplayName = "Not Changed"), +}; + +/* + * JSON struct serialization/deserialization + * from mhoelzl/PropertyTest tutorial on gitlab, and reflection tutorial on forums. + */ +UCLASS() +class UUnrealJsonBPLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_UCLASS_BODY() + + /** + * JSON struct serialization/deserialization + * in the style of KismetArrayLibrary.h + */ + + /** + * Convert structure to JSON + * work-around the build in converter because names are mangled: + * - Built-in: FJsonObjectConverter::UStructToJsonObjectString(StructProperty->Struct, StructPtr, JsonString, 0, 0, 0, nullptr, false); + * - Property->GetAuthoredName() should be called, not GetName() + * - There's a normalization which lowercases the first character and treats ID as a special string + * Convert JSON string into a structure + * - JsonObjectToUStruct did not seem to populate correctly + * - FJsonObjectConverter::JsonObjectToUStruct(JsonObject.ToSharedRef(), StructProperty->Struct, StructPtr, 0, 0)) + * - NOTE: Make Structure must be followed by Set Members or Set to create a value usable with pass-by-reference + */ + + /* + // Could be a helper at some point, may be unnecessary. + UFUNCTION(BlueprintPure, meta = (DisplayName = "Class to JSON", Keywords = "Json"), Category = "Unreal Helper BP Library") + static FString ClassToJson(UPARAM(ref) UObject* Object) + { + UE_LOG(LogTemp, Warning, TEXT("Explore class %s"), *Object->GetClass()->GetName()); + FString JsonString = ""; + // PropertyPtrAsJsonString(WildcardProperty, PropertyAddr, JsonString); + return JsonString; + } + */ + + /** + * Serialize from a wildcard property to a JSON string + * + * @param Wildcard The input to serialize to JSON + * @return String containing serializable properties as JSON + */ + UFUNCTION(BlueprintPure, meta = (DisplayName = "Object to JSON", Keywords = "Json", CustomStructureParam = "Wildcard"), Category = "Unreal Helper BP Library", CustomThunk) + static FString ToJson(UPARAM(ref) TFieldPath& Wildcard); + UFUNCTION(BlueprintPure, meta = (DisplayName = "Object to JSON Schema", Keywords = "Json", CustomStructureParam = "Wildcard"), Category = "Unreal Helper BP Library", CustomThunk) + static FString ToJsonSchema(UPARAM(ref) TFieldPath& Wildcard); + static void ObjectAsJsonObject(FJsonObject& JsonObject, FObjectProperty* ObjectProperty, void* ObjectPtr, const bool AsSchema); + static void StructAsJsonObject(FJsonObject& JsonObject, FStructProperty* StructProperty, void* StructPtr, const bool AsSchema); + static void PropertyAsJsonObject(FJsonObject& JsonObject, FProperty* Property, void* ValuePtr, const bool AsSchema); + static FString GetJsonTypeString(EJson& JsonType); + + // FIXME: Property and PropertyPtr should be const + static void PropertyPtrAsJsonString( + FProperty* Property, + void* PropertyPtr, FString& JsonString, const bool AsSchema); + DECLARE_FUNCTION(execToJson) + { + Stack.MostRecentProperty = nullptr; + Stack.StepCompiledIn(NULL); + FProperty* WildcardProperty = CastField(Stack.MostRecentProperty); + void* PropertyAddr = Stack.MostRecentPropertyAddress; + // P_GET_PROPERTY(FBoolProperty, AsSchema); + P_FINISH; + + P_NATIVE_BEGIN; + FString JsonString; + bool AsSchema = false; + PropertyPtrAsJsonString(WildcardProperty, PropertyAddr, JsonString, AsSchema); + *(FString*)RESULT_PARAM = JsonString; + P_NATIVE_END; + } + + // Notes: Do not use, still under development + DECLARE_FUNCTION(execToJsonSchema) + { + Stack.MostRecentProperty = nullptr; + Stack.StepCompiledIn(NULL); + FProperty* WildcardProperty = CastField(Stack.MostRecentProperty); + void* PropertyAddr = Stack.MostRecentPropertyAddress; + P_FINISH; + + P_NATIVE_BEGIN; + FString JsonString; + bool AsSchema = true; + PropertyPtrAsJsonString(WildcardProperty, PropertyAddr, JsonString, AsSchema); + *(FString*)RESULT_PARAM = JsonString; + P_NATIVE_END; + } + + /** + * Deserialize a JSON string into an existing a wildcard property + * + * @param Wildcard The structure or object to populate + * @param JsonString The JSON string to deserialize into the target structure or object + * @return bool True if json was parseable + */ + + UFUNCTION(BlueprintCallable, meta = (DisplayName = "JSON to Object", Keywords = "Json", CustomStructureParam = "Wildcard", AutoCreateRefTerm="Wildcard"), Category = "Unreal Helper BP Library", CustomThunk) + static bool FromJson( + UPARAM(ref) TFieldPath& Wildcard, + UPARAM(ref) FString& JsonString); + static void FromJson_Object(TSharedPtr JsonObject, FProperty* StructProperty, void* StructPtr); + static void JsonAsObject(TSharedPtr JsonObject, FObjectProperty* ObjectProperty, void* ObjectPtr); + static void JsonAsStruct(TSharedPtr JsonObject, FStructProperty* StructProperty, void* StructPtr); + static void JsonAsProperty(TSharedPtr JsonObject, FProperty* Property, void* ValuePtr); + + static bool FromJson_Generic( + FProperty* WildcardProperty, + void* PropertyPtr, FString& JsonString); + DECLARE_FUNCTION(execFromJson) + { + Stack.MostRecentProperty = nullptr; + Stack.StepCompiledIn(NULL); + FProperty* WildcardProperty = CastField(Stack.MostRecentProperty); + void* PropertyAddr = Stack.MostRecentPropertyAddress; + P_GET_PROPERTY_REF(FStrProperty, JsonString); + + P_FINISH; + + P_NATIVE_BEGIN; + // MARK_PROPERTY_DIRTY(Stack.Object, WildcardProperty); + *(bool*)RESULT_PARAM = FromJson_Generic(WildcardProperty, PropertyAddr, JsonString); + P_NATIVE_END; + } + + /** + * Work with JsonWrapper to check if a field exists + * + * @param JsonWrapper (optional) Unreal Json Wrapper over a JsonObject + * @param JsonString (optional) JSON string to deserialize into a Json Wrapper + * @param FieldName A top level field name to The JSON string to look for in the json object + * @param OutJsonWrapper The JsonWrapper to populate when the field was found with the resulting object + * @param FieldExists Enum of Changed or Not Changed based on field name filter and validity + */ + UFUNCTION(BlueprintCallable, meta = (DisplayName = "JsonObjectWrapper From Field", Keywords = "Json", ExpandEnumAsExecs = "FieldExists", AutoCreateRefTerm="JsonString"), Category = "Unreal Helper BP Library") + static void JsonWrapper_FromField(struct FJsonObjectWrapper InJsonWrapper, FString WithFieldPath, EJsonFieldExistsEnum& FieldExists, FJsonObjectWrapper& OutJsonWrapper); + + /** + * Work with JsonWrapper to check if a field exists + * + * @param JsonString JSON string to deserialize into a Json Wrapper + * @param WithFieldPath A top level field name or dot separated field path to traverse in the JSON object + * @param JsonWrapper Blueprint wrapper over a JsonObject + */ + UFUNCTION(BlueprintCallable, meta = (DisplayName = "JsonObjectWrapper From String", Keywords = "Json", ExpandEnumAsExecs = "FieldExists", AutoCreateRefTerm="JsonString"), Category = "Unreal Helper BP Library") + static void JsonWrapper_FromString(UPARAM(ref) FString& JsonString, const FString WithFieldPath, EJsonFieldExistsEnum& FieldExists, FJsonObjectWrapper& JsonWrapper); + + /** + * Work with JsonWrapper to check if a field exists + * + * @param JsonWrapper Unreal Json Wrapper over a JsonObject + * @return FString Serialized JSON as a string + */ + UFUNCTION(BlueprintCallable, meta = (DisplayName = "To String", Keywords = "Json"), Category = "Unreal Helper BP Library") + static FString JsonObjectWrapper_ToString(struct FJsonObjectWrapper JsonWrapper, const bool PrettyPrint=false); + static bool JsonObject_WithFieldPath(FJsonObject& JsonObject, const FString& WithFieldPath); + + /** + * Unwrap a JSON wrapper into an existing a wildcard property + * + * @param Wildcard The structure or object to populate + * @param JsonWrapper The Json Wrapper to unwrap into the target structure or object + * @return void + */ + UFUNCTION(BlueprintCallable, meta = (DisplayName = "To Object", Keywords = "Json", CustomStructureParam = "Wildcard", AutoCreateRefTerm="Wildcard"), Category = "Unreal Helper BP Library", CustomThunk) + static void JsonObjectWrapper_ToObject(struct FJsonObjectWrapper JsonWrapper, + UPARAM(ref) TFieldPath& Wildcard + ); + DECLARE_FUNCTION(execJsonObjectWrapper_ToObject) + { + P_GET_STRUCT(FJsonObjectWrapper, JsonWrapper); + Stack.MostRecentProperty = nullptr; + Stack.StepCompiledIn(NULL); + FProperty* WildcardProperty = CastField(Stack.MostRecentProperty); + void* PropertyAddr = Stack.MostRecentPropertyAddress; + + P_FINISH; + + P_NATIVE_BEGIN; + // MARK_PROPERTY_DIRTY(Stack.Object, WildcardProperty); + FromJson_Object(JsonWrapper.JsonObject, WildcardProperty, PropertyAddr); + P_NATIVE_END; + } + +}; diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealJson/UnrealJson.Build.cs b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealJson/UnrealJson.Build.cs new file mode 100644 index 0000000..b5c1386 --- /dev/null +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealJson/UnrealJson.Build.cs @@ -0,0 +1,30 @@ +using System.IO; +using UnrealBuildTool; + +public class UnrealJson : ModuleRules +{ + public UnrealJson(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + } + ); + + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "CoreUObject", + "Engine", + "HTTP", + "Json", + "JsonUtilities" + } + ); + + } +} diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealMediaOutputSocket/Private/SocketMediaCapture.cpp b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealMediaOutputSocket/Private/SocketMediaCapture.cpp new file mode 100644 index 0000000..1fef81d --- /dev/null +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealMediaOutputSocket/Private/SocketMediaCapture.cpp @@ -0,0 +1,1038 @@ +#include "SocketMediaCapture.h" +#include "Async/Async.h" +#include "Misc/Paths.h" +#include "MediaIOCoreFileWriter.h" +#include "Modules/ModuleManager.h" +#include "Containers/CircularQueue.h" +#if PLATFORM_WINDOWS +#include "Windows/WindowsHWrapper.h" +#endif +// UnrealAudioUtilities seems to have the nicer queue code +// #include "RenderUtils.h" +#include "RenderingThread.h" + +/** + * Write to a target pipe/socket as a consumer thread. + */ +/* Short-hand seemed a lot shorter - but harder to manage async task + Semaphore = FPlatformProcess::GetSynchEventFromPool(false); + DrainTask = FPlatformProcess::GetSynchEventFromPool(true); // called once + AsyncTask(ENamedThreads::AnyBackgroundThreadNormalTask, [this, bHasTcpEndpoint]() { + UE_LOG(LogTemp, Warning, TEXT("Ffmpeg async thread started")); + LockedSendQueue( + bHasTcpEndpoint ? Socket : nullptr, + bHasTcpEndpoint ? nullptr : StdinWritePipe, + StopTaskFlag, PendingFrames, Queue, Semaphore, DrainTask, PacketSize); + UE_LOG(LogTemp, Warning, TEXT("Ffmpeg async thread done")); + }); +*/ + +class UNREALMEDIAOUTPUTSOCKET_API SocketMediaCaptureSink : public FRunnable, FSingleThreadRunnable +{ + +public: + FThreadSafeBool StopTaskFlag; + FThreadSafeCounter PendingFrames; + FEvent *Semaphore = nullptr; + TCircularQueue> *Queue; + FRunnableThread *Thread = nullptr; + uint8 *SingleThreadData = nullptr; + // TQueue> Queue; // = TQueue>(121); + +private: + int32 PacketSize; + FSocket *WriteSocket; + void *WritePipe = nullptr; + +public: + SocketMediaCaptureSink(FSocket *TargetSocket, void *TargetPipe, int32 FramePacketSize) + { + WriteSocket = TargetSocket; + WritePipe = TargetPipe; + PacketSize = FramePacketSize; + } + + ~SocketMediaCaptureSink() + { + UE_LOG(LogTemp, Warning, TEXT("LockedSendQueue destructor")); + StopTaskFlag = true; + WriteSocket = nullptr; + WritePipe = nullptr; + StopListening(); + UE_LOG(LogTemp, Warning, TEXT("Media Capture Sink Destroyed")); + } + + FSingleThreadRunnable *GetSingleThreadInterface() + { + return this; + } + + bool Init() + { + Semaphore = FPlatformProcess::GetSynchEventFromPool(true); + Queue = new TCircularQueue>(511 + 1); + return true; + } + + void Exit() + { + UE_LOG(LogTemp, Warning, TEXT("LockedSendQueue exiting")); + StopTaskFlag = true; + Queue->Empty(); + Semaphore->Trigger(); + // Is this destructor implemented so return synch does not need to? + // delete Semaphore; + FPlatformProcess::ReturnSynchEventToPool(Semaphore); + Semaphore = nullptr; + UE_LOG(LogTemp, Warning, TEXT("LockedSendQueue exit")); + } + + void Stop() + { + UE_LOG(LogTemp, Warning, TEXT("LockedSendQueue stop early")); + if (StopTaskFlag) + { + return; + } + // FIXME: May already be handled via Exit() + StopTaskFlag = true; + Queue->Empty(); + if (Semaphore != nullptr) + { + Semaphore->Trigger(); + } + } + + bool EnqueuePacket(void *InBuffer, bool asAsync) + { + if (StopTaskFlag) + { + return false; + } + if (!asAsync) + { + SingleThreadData = (uint8 *)InBuffer; + Tick(); + } + else + { + // InBuffer is on main thread and needs to be copied out before getting clobbered. + TArray FrameData; + FrameData.AddUninitialized(PacketSize); + FMemory::Memcpy(FrameData.GetData(), InBuffer, PacketSize); + Queue->Enqueue(FrameData); + PendingFrames.Increment(); + int32 MAX_BUFFER_SIZE = 1024 * 1024 * 1024; // 1 gigabyte ram buffer + Semaphore->Trigger(); + if (PendingFrames.GetValue() * PacketSize > MAX_BUFFER_SIZE) + { + UE_LOG(LogTemp, Warning, TEXT("Reached max buffer size %d with pending frames %d"), MAX_BUFFER_SIZE, PendingFrames.GetValue()); + return false; + } + // Seems suspend/unsuspend would be bad form: + // https://docs.microsoft.com/en-us/dotnet/api/system.threading.thread.suspend?view=net-5.0 + // Thread->Suspend(false); + } + return !StopTaskFlag; + } + + // This is convoluted, using EnqueuePacket and Tick. + void Tick() + { + // Single-thread interface + if (WriteSocket != nullptr) + { + int32 BytesLeft = PacketSize; + double SocketTimeoutMs = 100; // 15; // 60fps requires a low timeout + if (!SocketMediaCaptureSink::SocketSend(WriteSocket, ((const uint8 *)SingleThreadData), BytesLeft, SocketTimeoutMs)) + { + UE_LOG(LogTemp, Warning, TEXT("Unexpected connection issue to ffmpeg")); + StopTaskFlag = true; + } + else if (BytesLeft > 0) + { + if (BytesLeft == PacketSize) + { + UE_LOG(LogTemp, Warning, TEXT("Partial packet on pipe")); + } + else + { + UE_LOG(LogTemp, Warning, TEXT("Timeout on pipe: %d"), BytesLeft); + } + } + } + else if (WritePipe != nullptr) + { + int32 BytesLeft = PacketSize; + FThreadSafeBool AlwaysFalse; + if (!SocketMediaCaptureSink::PipeSend(WritePipe, ((const uint8 *)SingleThreadData), BytesLeft, AlwaysFalse)) // , StopTaskFlag)) + { + UE_LOG(LogTemp, Warning, TEXT("Unexpected connection issue to ffmpeg")); + StopTaskFlag = true; + // StopCaptureImpl(false); + } + } + } + + // This is a single frame writer; for debugging we want multiple frames (and a very large file) + // MediaIOCoreFileWriter::WriteRawFile(OutputFilename, reinterpret_cast(InBuffer), Stride * Height); + static bool SocketSend(FSocket *TargetSocket, const uint8 *InBuffer, int32 &BytesLeft, double ReadyTimeoutMs) + { + int32 BytesOffset = 0; + int32 BytesSent = 0; + + while (TargetSocket->Wait(ESocketWaitConditions::WaitForWrite, FTimespan::FromMilliseconds(ReadyTimeoutMs))) + // && BytesLeft > 0 + { + if (BytesLeft == 0) + break; + // UE_LOG(LogTemp, Warning, TEXT("Socket Send Attempt %d at point %d"), BytesLeft, BytesOffset); + TargetSocket->Send((InBuffer) + BytesOffset, BytesLeft, BytesSent); + if (BytesSent == -1) + { + UE_LOG(LogTemp, Warning, TEXT("Socket Send Failure of %d at point %d"), BytesLeft, BytesOffset); + break; + } + BytesLeft -= BytesSent; + BytesOffset += BytesSent; + } + if (BytesSent == -1) + { + return false; + } + return true; + } + + static bool PipeSend(void *TargetPipe, const uint8 *InBuffer, int32 &BytesLeft, FThreadSafeBool &Stop) + { + int32 BytesOffset = 0; + int32 BytesSent = 0; + + while (BytesLeft > 0 && !Stop) + { + if (BytesLeft == 0) + break; + FPlatformProcess::WritePipe(TargetPipe, (InBuffer) + BytesOffset, BytesLeft, &BytesSent); + if (BytesSent == -1) + break; + BytesLeft -= BytesSent; + BytesOffset += BytesSent; + } + + // Clear stdout/stderr or ffmpeg will deadlock + // FString StdoutErr = FPlatformProcess::ReadPipe(TargetPipe); + + if (BytesSent == -1) + { + return false; + } + return true; + } + +public: + bool StartListening() + { + if (Thread != nullptr) + return false; + Thread = FRunnableThread::Create(this, TEXT("USocketMediaCaptureThread"), 128 * 1024, EThreadPriority::TPri_AboveNormal, FPlatformAffinity::GetPoolThreadMask()); + return (Thread != nullptr); + } + + void StopListening() + { + UE_LOG(LogTemp, Warning, TEXT("Stopping thread")); + if (Thread != nullptr) + { + StopTaskFlag = true; + if (Semaphore != nullptr) + { + Semaphore->Trigger(); + } + Thread->WaitForCompletion(); + delete Thread; + Thread = nullptr; + } + } + + uint32 Run() + { + UE_LOG(LogTemp, Warning, TEXT("LockedSendQueue started")); + + TArray InElement; + const uint8 *InBuffer = nullptr; + int32 BytesLeft = 0; + bool SendFailed = false; + const double SocketTimeoutMs = 2000; // This is a limit on delay + + while (!Queue->IsEmpty() || !StopTaskFlag) + { + if (!Queue->Dequeue(InElement)) + { + if (StopTaskFlag) + continue; + Semaphore->Reset(); + Semaphore->Wait(); + continue; + } + InBuffer = InElement.GetData(); + // UE_LOG(LogTemp, Warning, TEXT("LockedSendQueue loop begin")); + + // Bypass the pipe to debug the queue implementation + if (false) + { + PendingFrames.Decrement(); + continue; + } + + BytesLeft = PacketSize; + if (WritePipe != nullptr) + { + // UE_LOG(LogTemp, Warning, TEXT("Send via Pipe")); + if (!PipeSend(WritePipe, InBuffer, BytesLeft, StopTaskFlag)) + { + SendFailed = true; + break; + } + } + + else if (WriteSocket != nullptr) + { + if (!SocketSend(WriteSocket, InBuffer, BytesLeft, SocketTimeoutMs)) + { + SendFailed = true; + break; + } + } + + if (BytesLeft > 0) + { + if (BytesLeft != PacketSize) + { + UE_LOG(LogTemp, Warning, TEXT("Partial packet sent, pipe corrupted")); + SendFailed = true; + break; + } + UE_LOG(LogTemp, Warning, TEXT("Timeout on pipe with frames remaining: %d - packet size: %d"), PendingFrames.GetValue(), PacketSize); + SendFailed = true; + break; + } + + if (SendFailed && WritePipe != nullptr) + { + UE_LOG(LogTemp, Warning, TEXT("FFmpeg pipe failed early")); + StopTaskFlag = true; + } + + else if (SendFailed && WriteSocket != nullptr) + { + ISocketSubsystem *PlatformSockets = ISocketSubsystem::Get(); + ESocketErrors ErrorCode = PlatformSockets->GetLastErrorCode(); + FString ErrorString = FString(PlatformSockets->GetSocketError(ErrorCode)); + if (ErrorString == "SE_ECONNRESET") + { + UE_LOG(LogTemp, Warning, TEXT("FFmpeg failure on port connection %s"), *ErrorString); + } + else if (ErrorString == "SE_EFAULT") + { + UE_LOG(LogTemp, Warning, TEXT("Ffmpeg socket dropped unexpectedly: %s"), *ErrorString); + } + else + { + UE_LOG(LogTemp, Warning, TEXT("Ffmpeg unknown connection issue: %s"), *ErrorString); + } + StopTaskFlag = true; + } + + else + { + PendingFrames.Decrement(); + } + } + + UE_LOG(LogTemp, Warning, TEXT("LockedSendQueue drained")); + + StopTaskFlag = true; + + return 0; + } +}; + +/** + * Media output to write to an off-thread sink, optional spawned process + * off-thread writes to a socket/pipe to allow the next frame to render. + */ + +bool USocketMediaCapture::ValidateMediaOutput() const +{ + USocketMediaOutput *SocketMediaOutput = Cast(MediaOutput); + if (!SocketMediaOutput) + { + UE_LOG(LogTemp, Error, TEXT("Socket Media Capture unable to cast provided Media Output")); + return false; + } + + bool bHasTcpEndpoint = !SocketMediaOutput->NoNetwork; + if (bHasTcpEndpoint) + { + FString IPAddress = FString("127.0.0.1"); + uint32 Port = 4445; + + if (!SocketMediaOutput->IPAddress.IsEmpty()) + { + IPAddress = SocketMediaOutput->IPAddress; + } + + if (SocketMediaOutput->Port > 0) + { + Port = (uint32)SocketMediaOutput->Port; + } + + ISocketSubsystem *PlatformSockets = ISocketSubsystem::Get(); + if (PlatformSockets == nullptr) + { + UE_LOG(LogTemp, Warning, TEXT("Failed to access platform sockets")); + return false; + } + bool bIsValid; + TSharedPtr Endpoint = PlatformSockets->CreateInternetAddr(); + Endpoint->SetIp(*IPAddress, bIsValid); + Endpoint->SetPort(Port); + if (!bIsValid) + { + UE_LOG(LogTemp, Warning, TEXT("Failed to set ip and port")); + return false; + } + // UE_LOG(LogTemp, Warning, TEXT("TCP:connect %s"), *Endpoint->ToString(true)); + } + + return true; +} + +TArray USocketMediaCapture::AsProcessArgs(FIntPoint Size, FFrameRate Framerate, FString IPAddress, uint32 Port) +{ + USocketMediaOutput *SocketMediaOutput = CastChecked(MediaOutput); + + FString inputFormat; + inputFormat = TEXT("-f rawvideo -pixel_format rgba"); + if (SocketMediaOutput->PixelFormat == ESocketMediaOutputPixelFormat::MATTE) + { + inputFormat = TEXT("-f rawvideo -pixel_format gray"); + } + else if (SocketMediaOutput->PixelFormat == ESocketMediaOutputPixelFormat::RGBA) + { + inputFormat = TEXT("-f rawvideo -pixel_format rgba"); + // Untested for A2RGB10 - currently an ffmpeg compile-time: + // -pixel_format x2rgb10 + // still fresh: https://master.gitmailbox.com/ffmpegdev/20220218055012.916556-1-wenbin.chen@intel.com/T/ + } + else if (SocketMediaOutput->PixelFormat == ESocketMediaOutputPixelFormat::UYVY) + { + // Preferred output format as this is an animation + inputFormat = TEXT("-f rawvideo -pixel_format uyvy422"); + } + else if (SocketMediaOutput->PixelFormat == ESocketMediaOutputPixelFormat::V210) + { + // Library of congress notes v210 for analog capture + // incorrect, will lead to double image and flicker: + // inputFormat = TEXT("-f rawvideo -pixel_format yuv422p10le -c:v v210"); + // V210 is the 10-bit standard input for production capture cards in Unreal + inputFormat = TEXT("-f v210"); + } + + FString inputFramerate = FString::Printf(TEXT("%d/%d"), Framerate.Numerator, Framerate.Denominator); + + FString OutputMov = FPaths::ConvertRelativePathToFull(FPaths::Combine(*FPaths::ProjectSavedDir(), *FString("output.mp4"))); + if (!SocketMediaOutput->OutputFilename.IsEmpty()) + { + OutputMov = SocketMediaOutput->OutputFilename; + } + + TArray args; + args.Add(FStringFormatArg(inputFormat)); + args.Add(FStringFormatArg(Size.X)); + args.Add(FStringFormatArg(Size.Y)); + args.Add(FStringFormatArg(inputFramerate)); + args.Add(FStringFormatArg(IPAddress)); + args.Add(FStringFormatArg(Port)); + args.Add(FStringFormatArg(OutputMov)); + + return args; +} + +static FORCEINLINE bool CreatePipeWrite(void *&ReadPipe, void *&WritePipe) +{ +#if PLATFORM_WINDOWS + SECURITY_ATTRIBUTES Attr = {sizeof(SECURITY_ATTRIBUTES), NULL, true}; + + if (!::CreatePipe(&ReadPipe, &WritePipe, &Attr, 0)) + { + return false; + } + + if (!::SetHandleInformation(WritePipe, HANDLE_FLAG_INHERIT, 0)) + { + return false; + } + + return true; +#else + return FPlatformProcess::CreatePipe(ReadPipe, WritePipe); +#endif // PLATFORM_WINDOWS +} + +bool USocketMediaCapture::SpawnProcessBlocking(uint32 *ProcessId, TArray FormatArgs, FString ExpectStr) +{ + USocketMediaOutput *SocketMediaOutput = Cast(MediaOutput); + + // FIXME: Not working out for writing to an anonymous pipe (stdin of ffmpeg) + bool bHasTcpEndpoint = !SocketMediaOutput->NoNetwork; + // This defaults to a null output for reporting input framerate/bandwidth: + FString FfmpegParams = FString::Printf(TEXT("-y -report -vsync 0 -hwaccel auto {0} -video_size {1}x{2} -framerate {3} -i %s -f null {6}"), bHasTcpEndpoint ? TEXT("tcp://{4}:{5}?listen") : TEXT("-")); + + FString ExecutableParamsTemplate = SocketMediaOutput->ExecutableParams.IsEmpty() ? FfmpegParams : SocketMediaOutput->ExecutableParams; + FString Params = FString::Format(*ExecutableParamsTemplate, FormatArgs); + + // FFmpeg specific defaults + +#if PLATFORM_WINDOWS + FString URL = SocketMediaOutput->ExecutablePath.IsEmpty() ? TEXT("C:\\ffmpeg\\bin\\ffmpeg.exe") : SocketMediaOutput->ExecutablePath; +#else + FString URL = SocketMediaOutput->ExecutablePath.IsEmpty() ? TEXT("/usr/local/bin/ffmpeg") : SocketMediaOutput->ExecutablePath; +#endif + + if (!FPlatformProcess::CreatePipe(StderrReadPipe, StderrWritePipe)) + { + UE_LOG(LogTemp, Warning, TEXT("Failed to create stdout pipe")); + return false; + } + + if (!bHasTcpEndpoint) + { + // Needs: bLaunchDetached=True on create proc + if (!CreatePipeWrite(StdinReadPipe, StdinWritePipe)) + { + UE_LOG(LogTemp, Warning, TEXT("Failed to create stdin pipe")); + return false; + } + } + + bool bHasReport = !SocketMediaOutput->NoReport; + if (bHasReport) + { +// UE_LOG(LogTemp, Warning, TEXT("Reporting of my dreams")); +#if PLATFORM_WINDOWS + // The colon in drive paths causes file= to fail on absolute paths + FPlatformMisc::SetEnvironmentVar(TEXT("FFREPORT"), TEXT("file=output.log")); +#else + // OS X PIE does not seem to respect the working folder but absolute paths work + FString OutputLog = FPaths::ConvertRelativePathToFull(FPaths::Combine(*FPaths::ProjectSavedDir(), *FString("output.log"))); + FPlatformMisc::SetEnvironmentVar(TEXT("FFREPORT"), *FString::Printf(TEXT("file=%s"), *OutputLog)); +#endif + } + + UE_LOG(LogTemp, Warning, TEXT("Launch process: %s %s"), *URL, *Params); + + bool bHiddenExecutable = !SocketMediaOutput->NoHiddenExecutable; + int32 PriorityModifier = 2; // High. (2 is Higher) + ProcessHandle = FPlatformProcess::CreateProc(*URL, *Params, !bHasTcpEndpoint || !bHiddenExecutable, bHiddenExecutable, bHiddenExecutable, + ProcessId, PriorityModifier, *FPaths::ProjectSavedDir(), StderrWritePipe, StdinReadPipe); + + if (!ProcessHandle.IsValid()) + { + UE_LOG(LogTemp, Warning, TEXT("Failed to launch process.")); + return false; + } + + if (ExpectStr.IsEmpty()) + { + return true; + } + + // Sleep, because WaitForWrite does not seem to block for ffmpeg readiness in OS X + // and cut ffmpeg a little more slack for gpu probe / other startup activities + for (uint8 Attempts = 0; Attempts < 10; Attempts++) + { + FString TmpStdout = FPlatformProcess::ReadPipe(StderrReadPipe); + if (!TmpStdout.IsEmpty()) + { + if (TmpStdout.Contains(*ExpectStr)) + { + UE_LOG(LogTemp, Warning, TEXT("Process ready via stdout after waiting #%d: %s"), Attempts, *TmpStdout); + break; + } + } + else if (Attempts == 9) + { + UE_LOG(LogTemp, Warning, TEXT("Process stdout not ready, continuing anyway after attempt #%d: %s"), Attempts, *TmpStdout); + } + FPlatformProcess::Sleep(0.05); + } + FPlatformProcess::Sleep(0.1); + return true; +} + +// TODO: See if this is needed - we block anyway as we wait for the process to terminate +// virtual bool HasFinishedProcessing() const; + +// From FunctionalUIScreenshotTest and MediaCapture +void USocketMediaCapture::GetBackbufferInfo(const FSceneViewport *InViewport, EPixelFormat *OutPixelFormat, bool *OutIsSRGB, FIntPoint *Size) +{ + + /* + // Or if an actual texture as provided, as in 4.26 custom capture: + FTextureRenderTargetResource* InTextureRenderTargetResource + SourceTexture = InTextureRenderTargetResource->GetTextureRenderTarget2DResource()->GetTextureRHI(); + */ + + /** + * #if WITH_EDITOR + * if (!IsRunningGame()) + * { + */ + FTexture2DRHIRef SourceTexture = InViewport->GetRenderTargetTexture(); + if (SourceTexture.IsValid()) + { + *OutPixelFormat = SourceTexture->GetFormat(); + *OutIsSRGB = (SourceTexture->GetFlags() & TexCreate_SRGB) == TexCreate_SRGB; + *Size = SourceTexture->GetSizeXY(); + return; + } + + if (!InViewport->GetViewportRHI()) + { + return; + } + + ENQUEUE_RENDER_COMMAND(GetBackbufferFormatCmd) + ( + [InViewport, OutPixelFormat, OutIsSRGB, Size](FRHICommandListImmediate &RHICmdList) + { + FViewportRHIRef ViewportRHI = InViewport->GetViewportRHI(); + if (!ViewportRHI.IsValid()) + { + return; + } + FTexture2DRHIRef BackbufferTexture = RHICmdList.GetViewportBackBuffer(ViewportRHI); + if (!BackbufferTexture.IsValid()) + { + return; + } + *OutPixelFormat = BackbufferTexture->GetFormat(); + *OutIsSRGB = (BackbufferTexture->GetFlags() & TexCreate_SRGB) == TexCreate_SRGB; + *Size = BackbufferTexture->GetSizeXY(); + }); + FlushRenderingCommands(); +} + +// TCP / Process state is better stuffed into the Output class as the Socket / Process connections could be long-lived +// and they also require setup/teardown which have delays. +// However, all MediaOutput classes are reserved in conventional use as parameter stashes and nothing more. + +EPixelFormat USocketMediaCapture::GetPixelFormat() +{ + return SourcePixelFormat; +} + +bool USocketMediaCapture::CaptureSceneViewportImpl(TSharedPtr &InSceneViewport) +{ + + const auto CVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.VSync")); + bool bLockToVsync = CVar->GetValueOnGameThread() != 0; + if (bLockToVsync) + { + UE_LOG(LogTemp, Warning, TEXT("VSync is set to on which may result in reduced frame rate rendering for capture.")); + } + + USocketMediaOutput *SocketMediaOutput = CastChecked(MediaOutput); + OutputPixelFormat = SocketMediaOutput->PixelFormat; // Workaround alpha matte challenges + SocketMediaOutput->SourcePixelFormat = EPixelFormat::PF_B8G8R8A8; // Workaround standalone mode issue + + // Really difficult to get to: InMediaCapture->DesiredOutputSize.X / Y + // seems required when the command line flag -forceres is not in use + // FIntPoint Size = InSceneViewport->GetRenderTargetTextureSizeXY(); + FIntPoint Size = InSceneViewport->GetSizeXY(); + + EPixelFormat PixelFormat = PF_A2B10G10R10; + bool bIsSRGB = false; + // Standalone may have a different buffer than the default backing buffer; force them to meet. + GetBackbufferInfo(&*InSceneViewport, &PixelFormat, &bIsSRGB, &Size); + + if (SocketMediaOutput->PixelFormat == ESocketMediaOutputPixelFormat::MATTE) + { + // PixelFormat = EPixelFormat::PF_B8G8R8A8; + } + + // Pixel format can mean many different things, the enum is overloaded. + SourcePixelFormat = PixelFormat; + + UE_LOG(LogTemp, Warning, TEXT("Enum PixelFormat: %s"), GetPixelFormatString(SourcePixelFormat)); + + // Currently on GetState == EMediaCaptureState::Preparing; + + // SocketMediaOutput->DesiredPixelFormat // Bypass???? + // if (InMediaCapture->DesiredPixelFormat != SourceTexture->GetFormat()) + + bool bHasProcess = !SocketMediaOutput->NoExecutable; + bool bHasReport = !SocketMediaOutput->NoReport; + bool bHasTcpEndpoint = !SocketMediaOutput->NoNetwork; + bool bHiddenExecutable = !SocketMediaOutput->NoHiddenExecutable; + + // Used throughout the methods + bHasAsyncQueue = !SocketMediaOutput->NoAsync && FPlatformProcess::SupportsMultithreading(); + + // For on-cpu bit shifting. + + // One channel of 8 bits per pixel. + if (OutputPixelFormat == ESocketMediaOutputPixelFormat::MATTE) + { + PixelStrideBytes = 4; + PacketSize = Size.X * Size.Y; + OutputPacketBuffer = reinterpret_cast(FMemory::Malloc(PacketSize)); + } + + // RGBA 32 bit word, one pixel + if (OutputPixelFormat == ESocketMediaOutputPixelFormat::RGBA) + { + PixelStrideBytes = 4; + PacketSize = Size.X * Size.Y * PixelStrideBytes; + } + + // UYVY 32 bit word, two pixels + if (OutputPixelFormat == ESocketMediaOutputPixelFormat::UYVY) + { + PixelStrideBytes = 4; + PacketSize = Size.X / 2 * Size.Y * PixelStrideBytes; + } + + // V210 - 128 bit word, 6 pixels - Code from upstream (floor, aligned to 128 bit words) + if (OutputPixelFormat == ESocketMediaOutputPixelFormat::V210) + { + PixelStrideBytes = 16; + PacketSize = ((((Size.X + 47) / 48) * 48) / 6) * Size.Y * PixelStrideBytes; + // When on a 1280 width on window, seeing ceil or an extra padding, e.g: + // (math.ceil((1280 + 47) / 48) * 48) / 6 + } + + FFrameRate Framerate = FApp::GetTimecodeFrameRate(); + + FString IPAddress = FString("127.0.0.1"); + uint32 Port = 4445; + + if (bHasTcpEndpoint) + { + if (!SocketMediaOutput->IPAddress.IsEmpty()) + { + IPAddress = SocketMediaOutput->IPAddress; + } + + if (SocketMediaOutput->Port > 0) + { + Port = (uint32)SocketMediaOutput->Port; + } + } + + // Interprocess pipe, Stdout/Stderr, with Stdin if tcp is disabled + uint32 ProcessId = 0; + if (bHasProcess) + { + FString ExpectFfmpegOutputContains = FString("ffmpeg started on"); + if (!SpawnProcessBlocking(&ProcessId, AsProcessArgs(Size, Framerate, IPAddress, Port), ExpectFfmpegOutputContains)) + { + return false; + } + } + + if (bHasTcpEndpoint) + { + bool bIsValid; + ISocketSubsystem *PlatformSockets = ISocketSubsystem::Get(); + TSharedPtr Endpoint = PlatformSockets->CreateInternetAddr(); + Endpoint->SetIp(*IPAddress, bIsValid); + Endpoint->SetPort(Port); + + FString SocketDesc = FString("Image Stream"); + Socket = FTcpSocketBuilder(SocketDesc).AsBlocking().Build(); + Socket->SetNoDelay(true); + Socket->Connect(*Endpoint); + + // FIXME: Wait may return immediately on OS X, check state too + // for(uint8 Attempts = 0; Attempts < 10; Attempts++) + // if Socket->GetConnectionState() == ESocketConnectionState::SCS_Connected break; + UE_LOG(LogTemp, Warning, TEXT("Waiting for Socket")); + if (Socket->Wait(ESocketWaitConditions::WaitForWrite, FTimespan::FromMilliseconds(30))) + { + UE_LOG(LogTemp, Warning, TEXT("Socket ready")); + } + else + { + UE_LOG(LogTemp, Warning, TEXT("Socket not yet ready, continuing anyway")); + } + } + + if (bHasAsyncQueue) + { + UE_LOG(LogTemp, Warning, TEXT("Booting output buffer")); + SocketMediaCaptureSink *OutputBuffer = new SocketMediaCaptureSink(Socket, StdinWritePipe, PacketSize); + this->Sink = (void *)OutputBuffer; + OutputBuffer->StartListening(); + UE_LOG(LogTemp, Warning, TEXT("Booted output buffer")); + } + + if (bHasProcess) + { + FString StdoutErr = ""; + StdoutErr = FPlatformProcess::ReadPipe(StderrReadPipe); + if (bHasTcpEndpoint && Socket->GetConnectionState() != ESocketConnectionState::SCS_Connected) + { + UE_LOG(LogTemp, Warning, TEXT("FFMpeg Local Tcp Endpoint unreachable")); + } + else + { + if (FPlatformProcess::IsProcRunning(ProcessHandle)) + { + UE_LOG(LogTemp, Warning, TEXT("FFMpeg Boot: %s"), *StdoutErr); + SetState(EMediaCaptureState::Capturing); + return true; + } + UE_LOG(LogTemp, Warning, TEXT("Process stopped unexpectedly")); + } + if (bHasTcpEndpoint) + { + ISocketSubsystem *PlatformSockets = ISocketSubsystem::Get(); + PlatformSockets->DestroySocket(Socket); + } + + UE_LOG(LogTemp, Warning, TEXT("Process failed to boot: %s"), *StdoutErr); + if (FPlatformProcess::IsProcRunning(ProcessHandle)) + { + FPlatformProcess::TerminateProc(ProcessHandle, true); + } + FPlatformProcess::CloseProc(ProcessHandle); + } + else if (bHasTcpEndpoint) + { + if (Socket->GetConnectionState() == ESocketConnectionState::SCS_Connected) + { + SetState(EMediaCaptureState::Capturing); + return true; + } + + ISocketSubsystem *PlatformSockets = ISocketSubsystem::Get(); + PlatformSockets->DestroySocket(Socket); + + if (Socket->GetConnectionState() == ESocketConnectionState::SCS_ConnectionError) + { + UE_LOG(LogTemp, Warning, TEXT("Socket connection error: tcp://%s:%d"), *IPAddress, Port); + } + else + { + UE_LOG(LogTemp, Warning, TEXT("Socket failed unexpectedly: tcp://%s:%d"), *IPAddress, Port); + } + } + + if (OutputPixelFormat == ESocketMediaOutputPixelFormat::MATTE) + { + FMemory::Free(OutputPacketBuffer); + } + + SetState(EMediaCaptureState::Error); + return false; +} + +// NOTES: Event override has to block until complete brecause: +// - Parent StopCapture runs SetState Stopped before calling StopCaptureImpl +// - Seems we are not hooked into SetState(EMediaCaptureState::StopRequested); +// - So we can not ourselves trigger appropriately SetState(EMediaCaptureState::Stopped); + +void USocketMediaCapture::StopCaptureImpl(bool bAllowPendingFrameToBeProcess) +{ + + if (bAllowPendingFrameToBeProcess) + { + UE_LOG(LogTemp, Warning, TEXT("Pending frame before shutdown")); + return; + } + + if (OutputPacketBuffer != nullptr) + { + FMemory::Free(OutputPacketBuffer); + OutputPacketBuffer = nullptr; + } + + UE_LOG(LogTemp, Warning, TEXT("Shutting down process")); + if (Sink != nullptr) + { + UE_LOG(LogTemp, Warning, TEXT("Shutting down locked thread")); + SocketMediaCaptureSink *OutputBuffer = (SocketMediaCaptureSink *)Sink; + + UE_LOG(LogTemp, Warning, TEXT("Waiting on drain thread to complete")); + OutputBuffer->StopListening(); + delete static_cast(Sink); + UE_LOG(LogTemp, Warning, TEXT("Drain thread has completed")); + } + + if (Socket != nullptr) + { + UE_LOG(LogTemp, Warning, TEXT("Shutting down tcp socket: wait time")); + Socket->Wait(ESocketWaitConditions::WaitForWrite, FTimespan::FromMilliseconds(1500)); + UE_LOG(LogTemp, Warning, TEXT("Shutting down tcp socket: shutdown time")); + Socket->Shutdown(ESocketShutdownMode::ReadWrite); + UE_LOG(LogTemp, Warning, TEXT("Shutting down tcp socket: close time")); + Socket->Close(); + ISocketSubsystem *PlatformSockets = ISocketSubsystem::Get(); + PlatformSockets->DestroySocket(Socket); + UE_LOG(LogTemp, Warning, TEXT("Socket closed")); + } + + if (StdinReadPipe != nullptr) + { + UE_LOG(LogTemp, Warning, TEXT("Shutting down process input pipes")); + FPlatformProcess::ClosePipe(StdinReadPipe, StdinWritePipe); + StdinReadPipe = nullptr; + StdinWritePipe = nullptr; + } + + if (StderrReadPipe != nullptr) + { + UE_LOG(LogTemp, Warning, TEXT("Shutting down process output pipes")); + int wait_lock = 0; + while (!FPlatformProcess::ReadPipe(StderrReadPipe).IsEmpty()) + { + // Flush for awhile + // UE_LOG(LogTemp, Warning, TEXT("FFmpeg: %s"), *StdoutErr); + if (wait_lock++ > 10) + { + UE_LOG(LogTemp, Warning, TEXT("Stopped waiting for process output")); + break; + } + } + FPlatformProcess::ClosePipe(StderrReadPipe, StderrWritePipe); + StderrReadPipe = nullptr; + StderrWritePipe = nullptr; + } + + if (ProcessHandle.IsValid()) + { + // FIXME: This has no timeout, could freeze + UE_LOG(LogTemp, Warning, TEXT("Closing process")); + int32 ReturnCode = -1; + // WaitForProc has no timeout - can easily deadlock the process + FPlatformProcess::WaitForProc(ProcessHandle); + FPlatformProcess::GetProcReturnCode(ProcessHandle, &ReturnCode); + FPlatformProcess::CloseProc(ProcessHandle); + if (ReturnCode != 0) + { + UE_LOG(LogTemp, Warning, TEXT("FFmpeg unsuccessful return code %d"), ReturnCode); + } + UE_LOG(LogTemp, Warning, TEXT("Closed proc ffmpeg")); + if (FPlatformProcess::IsProcRunning(ProcessHandle)) + { + FPlatformProcess::TerminateProc(ProcessHandle, true); + UE_LOG(LogTemp, Warning, TEXT("Forced ffmpeg to stop.")); + } + ProcessHandle.Reset(); + // Seems like logging still does not flush to disk; give it a pause. + FPlatformProcess::Sleep(0.05); + UE_LOG(LogTemp, Warning, TEXT("done sleeping, releasing.")); + } +} + +/** + * This is guaranteed to be a single thread, in-order, on the render thread path. + */ + +void USocketMediaCapture::OnFrameCaptured_RenderingThread(const FCaptureBaseData &InBaseData, + TSharedPtr InUserData, + void *InBuffer, int32 Width, int32 Height +#if ENGINE_MAJOR_VERSION > 4 + , + int32 BytesPerRow +#endif +) +{ + if (Sink == nullptr) + { + return; + } + + if (GetState() != EMediaCaptureState::Capturing) + { + return; + } + + SocketMediaCaptureSink *OutputBuffer = (SocketMediaCaptureSink *)Sink; + if (OutputBuffer->StopTaskFlag) + { + UE_LOG(LogTemp, Warning, TEXT("Skipping frame on stopped capture")); + return; + } + + // SourceFrameNumber is available as of 4.24 + // if(InBaseData.SourceFrameNumber < 4) { + // UE_LOG(LogTemp, Warning, TEXT("packet size: %d height x width %d x %d"), PacketSize, Height, Width); + // UE_LOG(LogTemp, Warning, TEXT("Start capture frame: %d with pending %d"), InBaseData.SourceFrameNumber, PendingFrames.GetValue()); + //} + + // Copy out a GRAY8 buffer. ffmpeg has x2rgb10. + // support for a2rgb10 is still cutting edge, with hevc support only in OS X and in nvidia drivers. some othermovement here: + // https://github.com/intel-media-ci/ffmpeg/pull/219 + // https://patchwork.ffmpeg.org/project/ffmpeg/patch/20190910093526.13442-1-zachary.zhou@intel.com/ + // ffmpeg does like to use rgba8, vp9 has support: + // https://stackoverflow.com/questions/66769652/ue4-capture-frame-using-id3d11texture2d-and-convert-to-r8g8b8-bitmap + + if (OutputPixelFormat == ESocketMediaOutputPixelFormat::MATTE) + { + // PixelFormat == PF_FloatRGBA + if (SourcePixelFormat == PF_B8G8R8A8) + { + FColor *PixelBuffer = reinterpret_cast(InBuffer); + for (int32 i = 0; i < PacketSize; i++) + { + *(OutputPacketBuffer + i) = PixelBuffer[i].A; // (uint8) (PixelBuffer[i] & 0x000000ff); + } + } + else if (SourcePixelFormat == PF_A2B10G10R10) + { + // Assuming directx, this is likely: DXGI_FORMAT_R10G10B10A2_UNORM + // a 2-bit UNORM represents 0.0f, 1/3, 2/3, and 1.0f. + // use uint32* for portability. + // https://docs.microsoft.com/en-us/windows/win32/api/dxgiformat/ne-dxgiformat-dxgi_format + uint32 *PixelBuffer = reinterpret_cast(InBuffer); + for (int32 i = 0; i < PacketSize; i++) + { + // uint8 alpha = (uint8)((PixelBuffer[i] << 30) >> 24); + uint8 alpha = (uint8)((PixelBuffer[i] >> 30) << 6); + *(OutputPacketBuffer + i) = alpha | (alpha >> 2) | (alpha >> 4) | (alpha >> 6); + } + } + + if (!OutputBuffer->EnqueuePacket((void *)OutputPacketBuffer, bHasAsyncQueue)) + { + SetState(EMediaCaptureState::Error); + } + return; + } + + int32 FramePacketSize = 4 * Width * Height; + if (FramePacketSize != PacketSize) + { + // Resulting stream will be out of alignment - 4.24 downscales in PIE giving wrong size to StartCaptureImpl. + // In practice we may want to reinitialize our output pipe to our actual texture instead of our hope at initialization + // Width is set via private parent properties: + // InMediaCapture->DesiredOutputSize.X hitting the ReadyFrame->ReadbackTexture + UE_LOG(LogTemp, Warning, TEXT("packet re-size: from %d to %d"), PacketSize, FramePacketSize); + // UE_LOG(LogTemp, Warning, TEXT("Frame size: %d x %d @ %d == %d"), Width, Height, PixelStrideBytes, PacketSize); + PacketSize = FramePacketSize; + } + + if (StderrReadPipe != nullptr) + { + // Flush subprocess stderr/stdout or it will deadlock when the buffer fills + FPlatformProcess::ReadPipe(StderrReadPipe); + } + + if (!OutputBuffer->EnqueuePacket(InBuffer, bHasAsyncQueue)) + { + SetState(EMediaCaptureState::Error); + } +} diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealMediaOutputSocket/Private/SocketMediaOutput.cpp b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealMediaOutputSocket/Private/SocketMediaOutput.cpp new file mode 100644 index 0000000..b29bce3 --- /dev/null +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealMediaOutputSocket/Private/SocketMediaOutput.cpp @@ -0,0 +1,167 @@ +#include "SocketMediaOutput.h" +#include "SocketMediaCapture.h" + +#include "Misc/Paths.h" +#include "UnrealEngine.h" + +// Really not fun methods of finding the viewport + +#include "Slate/SceneViewport.h" +#include "Engine/GameEngine.h" +#if WITH_EDITOR +#include "Editor.h" +#include "Editor/EditorEngine.h" +#include "Engine/Engine.h" +#include "Engine/EngineTypes.h" +#endif + +// MediaCaptureDetails was stashed in MediaOutput.cpp +USocketMediaOutput::USocketMediaOutput() + : Super() +{ +} + +bool USocketMediaOutput::FindSceneViewportAndLevel(TSharedPtr &OutSceneViewport) const +{ +#if WITH_EDITOR + if (GIsEditor) + { + for (const FWorldContext &Context : GEngine->GetWorldContexts()) + { + if (Context.WorldType == EWorldType::PIE) + { + // UEditorEngine::GetPrivateStaticClass missing from link; plsfix + // UEditorEngine* EditorEngine = CastChecked(GEngine); + UEditorEngine *EditorEngine = (UEditorEngine *)(GEngine); + FSlatePlayInEditorInfo &Info = EditorEngine->SlatePlayInEditorMap.FindChecked(Context.ContextHandle); + if (Info.SlatePlayInEditorWindowViewport.IsValid()) + { + OutSceneViewport = Info.SlatePlayInEditorWindowViewport; + return true; + } + } + } + return false; + } + else +#endif + { + UGameEngine *GameEngine = CastChecked(GEngine); + OutSceneViewport = GameEngine->SceneViewport; + return true; + } +} + +// TODO: Add initialize option to check for resize, look into resize options +bool USocketMediaOutput::Validate(FString &OutFailureReason) const +{ + return true; +} + +/* + * Hard coded the logic: + * Uncertain as to why UMediaOutput::RequestCaptureSourceSize (FIntPoint::ZeroValue) + * did not fall back to FoundSceneViewport->GetSizeXY + * e.g. (GetRequestedSize() == UMediaOutput::RequestCaptureSourceSize) + */ +FIntPoint USocketMediaOutput::GetRequestedSize() const +{ + TSharedPtr FoundSceneViewport; + if (FindSceneViewportAndLevel(FoundSceneViewport)) + { + FIntPoint Size = FoundSceneViewport->GetRenderTargetTextureSizeXY(); + // MediaCapture should have handled this, but does not seem to in 4.22 + // FIntPoint SizeIsh = FoundSceneViewport->GetSizeXY(); + return Size; + } + // assert(FIntPoint::ZeroValue == UMediaOutput::RequestCaptureSourceSize); + return FIntPoint::ZeroValue; +} + +EPixelFormat USocketMediaOutput::GetRequestedPixelFormat() const +{ + // Trying again for matte processing in a2rgb10 + // if(PixelFormat == ESocketMediaOutputPixelFormat::MATTE) + //{ + // return EPixelFormat::PF_B8G8R8A8; + // } + + // ValidateSceneViewport seems to require this: + if (SourcePixelFormat == EPixelFormat::PF_Unknown) + { + static const auto CVarDefaultBackBufferPixelFormat = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.DefaultBackBufferPixelFormat")); + return EDefaultBackBufferPixelFormat::Convert2PixelFormat(EDefaultBackBufferPixelFormat::FromInt(CVarDefaultBackBufferPixelFormat->GetValueOnAnyThread())); + } + + // Then CaptureSceneViewportImpl is run; which can update our Pixel Format to the correct one? + + // return EPixelFormat::PF_B8G8R8A8; + // return EPixelFormat::PF_A2B10G10R10; + /* + if(SourcePixelFormat == EPixelFormat::PF_Unknown) + { + // CaptureImpl is not set - this is all one big workaround + SourcePixelFormat = ((USocketMediaCapture*) CaptureImpl)->GetPixelFormat(); + } + */ + return SourcePixelFormat; + // This worked nicely except that Standalone mode can switch from rgb10 to rgb8 +} + +EMediaCaptureConversionOperation USocketMediaOutput::GetConversionOperation(EMediaCaptureSourceType InSourceType) const +{ + static const auto CVarDefaultBackBufferPixelFormat = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.DefaultBackBufferPixelFormat")); + EPixelFormat SceneTargetFormat = EDefaultBackBufferPixelFormat::Convert2PixelFormat(EDefaultBackBufferPixelFormat::FromInt(CVarDefaultBackBufferPixelFormat->GetValueOnAnyThread())); + + // Same as the PNG / EXR encoder + if (PixelFormat == ESocketMediaOutputPixelFormat::MATTE) + { + return EMediaCaptureConversionOperation::INVERT_ALPHA; + } + if (PixelFormat == ESocketMediaOutputPixelFormat::RGBA) + { + return EMediaCaptureConversionOperation::NONE; + } + // This triggers a pixel shader to compress/alter the format, e.g. rgba to uyuv. + if (SceneTargetFormat == EPixelFormat::PF_A2B10G10R10) + { + if (PixelFormat == ESocketMediaOutputPixelFormat::V210) + { + UE_LOG(LogTemp, Warning, TEXT("V210 Capture Format")); + return EMediaCaptureConversionOperation::RGB10_TO_YUVv210_10BIT; + } + UE_LOG(LogTemp, Warning, TEXT("UYVY Capture Format")); + return EMediaCaptureConversionOperation::RGBA8_TO_YUV_8BIT; + // UE 4.23+ EMediaCaptureConversionOperation::CUSTOM + } + if (SceneTargetFormat == EPixelFormat::PF_B8G8R8A8) + { + if (PixelFormat == ESocketMediaOutputPixelFormat::V210) + { + UE_LOG(LogTemp, Warning, TEXT("V210 Capture Format Selected but Backing is RGBA8 - Falling to UYUV")); + } + return EMediaCaptureConversionOperation::RGBA8_TO_YUV_8BIT; + } + return EMediaCaptureConversionOperation::NONE; +} + +template +static FString EnumToString(const FString &enumName, const T value) +{ + UEnum *pEnum = FindObject(ANY_PACKAGE, *enumName); + return *(pEnum ? pEnum->GetNameStringByIndex(static_cast(value)) : "null"); +} + +UMediaCapture *USocketMediaOutput::CreateMediaCaptureImpl() +{ + if (PixelFormat == ESocketMediaOutputPixelFormat::MATTE) + { + DesiredPixelFormat = EPixelFormat::PF_B8G8R8A8; + } + UMediaCapture *Result = NewObject(); + if (Result) + { + Result->SetMediaOutput(this); + } + return Result; +} diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealMediaOutputSocket/Private/UnrealMediaOutputSocket.cpp b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealMediaOutputSocket/Private/UnrealMediaOutputSocket.cpp new file mode 100644 index 0000000..5443aa1 --- /dev/null +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealMediaOutputSocket/Private/UnrealMediaOutputSocket.cpp @@ -0,0 +1,20 @@ +// Copyright 2020 Disney Direct-to-Consumer and International. All Rights Reserved. + +#include "UnrealMediaOutputSocket.h" + +#define LOCTEXT_NAMESPACE "FUnrealMediaOutputSocketModule" + +void FUnrealMediaOutputSocketModule::StartupModule() +{ + // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module +} + +void FUnrealMediaOutputSocketModule::ShutdownModule() +{ + // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, + // we call this function before unloading the module. +} + +#undef LOCTEXT_NAMESPACE + +IMPLEMENT_MODULE(FUnrealMediaOutputSocketModule, UnrealMediaOutputSocket) diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealMediaOutputSocket/Public/SocketMediaCapture.h b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealMediaOutputSocket/Public/SocketMediaCapture.h new file mode 100644 index 0000000..01099e0 --- /dev/null +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealMediaOutputSocket/Public/SocketMediaCapture.h @@ -0,0 +1,64 @@ +#pragma once + +#include "MediaCapture.h" +#include "Slate/SceneViewport.h" +#include "Runtime/Core/Public/GenericPlatform/GenericPlatformProcess.h" +#include "Runtime/Core/Public/GenericPlatform/GenericPlatformMisc.h" +#include "Runtime/Launch/Resources/Version.h" +#include "Runtime/Networking/Public/Common/TcpSocketBuilder.h" +#include "IPAddress.h" +#include "Sockets.h" +#include "SocketSubsystem.h" +#include "SocketMediaOutput.h" +#include "SocketMediaCapture.generated.h" + +UCLASS(BlueprintType) +class UNREALMEDIAOUTPUTSOCKET_API USocketMediaCapture : public UMediaCapture +{ + GENERATED_BODY() +protected: + virtual bool ValidateMediaOutput() const; + virtual bool CaptureSceneViewportImpl(TSharedPtr &InSceneViewport) override; + virtual void StopCaptureImpl(bool bAllowPendingFrameToBeProcess) override; + virtual void OnFrameCaptured_RenderingThread(const FCaptureBaseData &InBaseData, + TSharedPtr InUserData, + void *InBuffer, int32 Width, int32 Height +#if ENGINE_MAJOR_VERSION > 4 + , + int32 BytesPerRow +#endif + ) override; + +public: + EPixelFormat GetPixelFormat(); + +private: + EPixelFormat SourcePixelFormat; + ESocketMediaOutputPixelFormat OutputPixelFormat; + uint8 *OutputPacketBuffer = nullptr; + + void GetBackbufferInfo(const FSceneViewport *InViewport, EPixelFormat *OutPixelFormat, bool *OutIsSRGB, FIntPoint *Size); + + uint8 PixelStrideBytes; + // Still getting a different Width*Height from Standalone mode. + int32 PacketSize = 0; + + // Subprocess, Stderr and Stdout + FProcHandle ProcessHandle; + void *StderrReadPipe = nullptr; + void *StderrWritePipe = nullptr; + + // Stdin (vs TCP socket) + void *StdinReadPipe = nullptr; + void *StdinWritePipe = nullptr; + + TArray AsProcessArgs(FIntPoint Size, FFrameRate Framerate, FString IPAddress, uint32 Port); + bool SpawnProcessBlocking(uint32 *ProcessId, TArray FormatArgs, FString ExpectStr); + + // TCP Socket + FSocket *Socket; + + // Copy frame data from rendering thread + bool bHasAsyncQueue = false; + void *Sink = nullptr; +}; diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealMediaOutputSocket/Public/SocketMediaOutput.h b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealMediaOutputSocket/Public/SocketMediaOutput.h new file mode 100644 index 0000000..0784a4c --- /dev/null +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealMediaOutputSocket/Public/SocketMediaOutput.h @@ -0,0 +1,103 @@ +#pragma once + +#include "FileMediaOutput.h" +#include "Engine/RendererSettings.h" +#include "Slate/SceneViewport.h" +#include "SocketMediaOutput.generated.h" + +/* + * UYVY422 is two pixels packed into 4 bytes + * - Apple: 2yuv + * - FFmpeg: -pixel_format uyvy422 + * - Unreal: RGBA8_TO_YUV_8BIT + * + * V210 is four pixels packed into 16 bites + * - Apple: V210 + * - FFmpeg: -pixel_format yuv422p10le -c:v v210 + * -pix_fmt yuv422p10le -vcodec v210 + * - Unreal: RGB10_TO_YUVv210_10BIT + * + * RGBA is one pixel in 4 bytes with format by back buffer + * Unreal: PF_A2B10G10R10 + * - Nvidia: NV_ENC_BUFFER_FORMAT_ABGR10 + * - FFmpeg: -pix_fmt x2rgb10 + * - Apple: R210 + * - Kona: R10K + * Unreal: PF_B8G8R8A8 + * - Nvidia: NV_ENC_BUFFER_FORMAT_ABGR + * - FFmpeg: -pixel_format bgra + * For ffmpeg see ffmpeg -pix_fmts + */ + +UENUM(BlueprintType) +enum class ESocketMediaOutputPixelFormat : uint8 +{ + UYVY UMETA(DisplayName = "UYVY"), + V210 UMETA(DisplayName = "V210"), + RGBA UMETA(DisplayName = "RGBA"), + MATTE UMETA(DisplayName = "MATTE") +}; + +/** + * Output information for a socket media capture. + */ +UCLASS(BlueprintType) +class UNREALMEDIAOUTPUTSOCKET_API USocketMediaOutput : public UMediaOutput +{ + GENERATED_BODY() +public: + USocketMediaOutput(); + +public: + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Network", meta = (DisplayName = "IP Address", MakeStructureDefaultValue = "127.0.0.1")) + FString IPAddress; + + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Network", meta = (ClampMin = "0", ClampMax = "65535", MakeStructureDefaultValue = "4445")) + int32 Port; + + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Process", meta = (DisplayName = "No Background Process")) + bool NoExecutable; + + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Process", meta = (DisplayName = "Show Background Process Window")) + bool NoHiddenExecutable; + + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Process", meta = (DisplayName = "No FFMpeg Report")) + bool NoReport; + + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Process", meta = (DisplayName = "No TCP Network Pipe")) + bool NoNetwork; + + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Process", meta = (DisplayName = "No Async Queue")) + bool NoAsync; + + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Process", meta = (MakeStructureDefaultValue = "output.mkv")) + FString OutputFilename; + + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Process") + FString ExecutablePath; + + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Process") + FString ExecutableParams; + + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Media", meta = (MakeStructureDefaultValue = "UYUV")) + ESocketMediaOutputPixelFormat PixelFormat; + + // Kind of broken: + EPixelFormat DesiredPixelFormat; + +public: + // primary viewport to match GetRequestedSize to back buffer resolution + bool FindSceneViewportAndLevel(TSharedPtr &OutSceneViewport) const; + virtual bool Validate(FString &FailureReason) const override; + virtual FIntPoint GetRequestedSize() const override; + virtual EPixelFormat GetRequestedPixelFormat() const override; + virtual EMediaCaptureConversionOperation GetConversionOperation(EMediaCaptureSourceType InSourceType) const override; + +protected: + virtual UMediaCapture *CreateMediaCaptureImpl() override; + UMediaCapture *CreateMediaCapture(); + +public: + // Work-around the pixel format check in MediaCapture + EPixelFormat SourcePixelFormat; +}; diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealMediaOutputSocket/Public/UnrealMediaOutputSocket.h b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealMediaOutputSocket/Public/UnrealMediaOutputSocket.h new file mode 100644 index 0000000..02e7212 --- /dev/null +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealMediaOutputSocket/Public/UnrealMediaOutputSocket.h @@ -0,0 +1,13 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Modules/ModuleManager.h" + +class FUnrealMediaOutputSocketModule : public IModuleInterface +{ +public: + + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; +}; diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealMediaOutputSocket/UnrealMediaOutputSocket.Build.cs b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealMediaOutputSocket/UnrealMediaOutputSocket.Build.cs new file mode 100644 index 0000000..c14a9ee --- /dev/null +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealMediaOutputSocket/UnrealMediaOutputSocket.Build.cs @@ -0,0 +1,28 @@ +using UnrealBuildTool; + +public class UnrealMediaOutputSocket : ModuleRules +{ + public UnrealMediaOutputSocket(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + "MediaIOCore", + "RenderCore", + "RHI", + "Networking", + "Sockets" + } + ); + PrivateDependencyModuleNames.AddRange( + new string[] + { + "CoreUObject", + "Engine", + } + ); + } +} diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/Private/UnrealWebSocket.cpp b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/Private/UnrealWebSocket.cpp new file mode 100644 index 0000000..506c8d6 --- /dev/null +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/Private/UnrealWebSocket.cpp @@ -0,0 +1,112 @@ +#include "UnrealWebSocket.h" + +UUnrealWebSocket::UUnrealWebSocket(const FObjectInitializer& ObjectInitializer) +: Super(ObjectInitializer) +{ + WebSocket = nullptr; + ReadyState = EWebSocketReadyState::CLOSED; +} + + +void UUnrealWebSocket::PostInitProperties() +{ + Super::PostInitProperties(); + FWebSocketsModule& Module = FModuleManager::LoadModuleChecked(TEXT("WebSockets")); + Protocols.Add(TEXT("ws")); + Protocols.Add(TEXT("wss")); +} + +void UUnrealWebSocket::PostLoad() +{ + Super::PostLoad(); + +} + +void UUnrealWebSocket::Connect(const FString& Url) +{ + WebSocket = FWebSocketsModule::Get().CreateWebSocket(Url, Protocols); + + // https://html.spec.whatwg.org/multipage/web-sockets.html#the-websocket-interface + if (WebSocket.IsValid()) + { + ReadyState = EWebSocketReadyState::CONNECTING; + + WebSocket->OnConnected().AddWeakLambda(this, [this]() -> void { + + ReadyState = EWebSocketReadyState::OPEN; + OnOpen.Broadcast(); + + }); + + WebSocket->OnConnectionError().AddWeakLambda(this, [this](const FString& Error) -> void { + + ReadyState = EWebSocketReadyState::CLOSED; + OnError.Broadcast(Error); + + }); + + WebSocket->OnClosed().AddWeakLambda(this, [this](int32 StatusCode, const FString Reason, bool bWasClean) -> void { + + ReadyState = EWebSocketReadyState::CLOSED; + OnClosed.Broadcast(Reason); + Cleanup(); + + }); + + WebSocket->OnMessage().AddWeakLambda(this, [this](const FString& Message) -> void { + + OnMessage.Broadcast(Message); + + }); + + WebSocket->Connect(); + } + else + { + ReadyState = EWebSocketReadyState::CLOSED; + OnError.Broadcast(FString("Unable to Create WebSocket")); + } + +} + +void UUnrealWebSocket::Close(int32 Code, const FString& Reason) +{ + if (WebSocket.IsValid() && WebSocket->IsConnected()) + { + ReadyState = EWebSocketReadyState::CLOSING; + WebSocket->Close(); + } +} + +void UUnrealWebSocket::Send(const FString& Data) +{ + if (WebSocket.IsValid() && WebSocket->IsConnected()) + { + WebSocket->Send(Data); + } +} + +void UUnrealWebSocket::SendBuffer(const TArray& Data) +{ + if (WebSocket.IsValid() && WebSocket->IsConnected()) + { + WebSocket->Send(Data.GetData(), Data.GetAllocatedSize(), true); + } +} + +void UUnrealWebSocket::Cleanup() +{ + if (WebSocket.IsValid()) + { + WebSocket->OnConnected().RemoveAll(this); + WebSocket->OnConnectionError().RemoveAll(this); + WebSocket->OnMessage().RemoveAll(this); + WebSocket->OnClosed().RemoveAll(this); + WebSocket.Reset(); + } +} + +void UUnrealWebSocket::BeginDestroy() +{ + Super::BeginDestroy(); +} diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/Private/UnrealWebSockets.cpp b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/Private/UnrealWebSockets.cpp new file mode 100644 index 0000000..8d3c050 --- /dev/null +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/Private/UnrealWebSockets.cpp @@ -0,0 +1,24 @@ +// Copyright 2020 Disney Direct-to-Consumer and International. All Rights Reserved. + +#include "UnrealWebSockets.h" + +#define LOCTEXT_NAMESPACE "FUnrealWebSocketsModule" + +void FUnrealWebSocketsModule::StartupModule() +{ + // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module + +} + +void FUnrealWebSocketsModule::ShutdownModule() +{ + // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, + // we call this function before unloading the module. + //UE_LOG("") + //FModuleManager::UnloadModule("WebSockets"); + +} + +#undef LOCTEXT_NAMESPACE + +IMPLEMENT_MODULE(FUnrealWebSocketsModule, UnrealWebSockets) \ No newline at end of file diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/Private/UnrealWebSocketsBPLibrary.cpp b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/Private/UnrealWebSocketsBPLibrary.cpp new file mode 100644 index 0000000..8d9a736 --- /dev/null +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/Private/UnrealWebSocketsBPLibrary.cpp @@ -0,0 +1,14 @@ +#include "UnrealWebSocketsBPLibrary.h" +#include "UnrealWebSockets.h" + +UUnrealWebSocketsBPLibrary::UUnrealWebSocketsBPLibrary(const FObjectInitializer& ObjectInitializer) +: Super(ObjectInitializer) +{ + +} +void UUnrealWebSocketsBPLibrary::CreateWebSocket(UObject* Owner, const FString Url, UUnrealWebSocket*& WebSocket) +{ + WebSocket = NewObject(Owner); + WebSocket->Connect(Url); +} + diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/Public/UnrealWebSocket.h b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/Public/UnrealWebSocket.h new file mode 100644 index 0000000..2316c7d --- /dev/null +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/Public/UnrealWebSocket.h @@ -0,0 +1,77 @@ +#pragma once + +#include "CoreMinimal.h" +#include "UObject/NoExportTypes.h" +#include "Modules/ModuleManager.h" +#include "WebSocketsModule.h" +#include "IWebSocket.h" +#include "UnrealWebSocket.generated.h" + +/** + * + */ +// Compromise between Unreal and WebSocket API + +DECLARE_DYNAMIC_MULTICAST_DELEGATE(FWebSocketOnOpenSignature); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FWebSocketOnClosedSignature, const FString&, Reason); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FWebSocketOnErrorSignature, const FString&, error); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FWebSocketOnMessageSignature, const FString&, data); + +UENUM(BlueprintType) +enum class EWebSocketReadyState : uint8 { + CONNECTING UMETA(DisplayName = "Connecting"), + OPEN UMETA(DisplayName = "Open"), + CLOSING UMETA(DisplayName = "Closing"), + CLOSED UMETA(DisplayName = "Closed") +}; + +UCLASS(BlueprintType) +class UNREALWEBSOCKETS_API UUnrealWebSocket : public UObject +{ + GENERATED_BODY() +private: + + TArray Protocols; + + UUnrealWebSocket(const FObjectInitializer& ObjectInitializer); + + virtual void PostInitProperties() override; + + virtual void PostLoad() override; + + virtual void BeginDestroy() override; + +public: + + TSharedPtr WebSocket; + + void Cleanup(); + + void Connect(const FString& Url); + + UPROPERTY(BlueprintReadOnly) + EWebSocketReadyState ReadyState; + + UFUNCTION(BlueprintCallable, meta = (DisplayName = "Close", Keywords = "Close", AutoCreateRefTerm="Reason"), Category = "WebSocket") + void Close(int32 Code = 1000, const FString& Reason = ""); + + UFUNCTION(BlueprintCallable, meta = (DisplayName = "Send", Keywords = "Send"), Category = "WebSocket") + void Send(const FString& Data); + + UFUNCTION(BlueprintCallable, meta = (DisplayName = "Send Buffer", Keywords = "Send"), Category = "WebSocket") + void SendBuffer(const TArray& Data); + + UPROPERTY(BlueprintAssignable, Category = "Unreal WebSockets") + FWebSocketOnClosedSignature OnClosed; + + UPROPERTY(BlueprintAssignable, Category = "Unreal WebSockets") + FWebSocketOnErrorSignature OnError; + + UPROPERTY(BlueprintAssignable, Category = "Unreal WebSockets") + FWebSocketOnOpenSignature OnOpen; + + UPROPERTY(BlueprintAssignable, Category = "Unreal WebSockets") + FWebSocketOnMessageSignature OnMessage; + + +}; diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/Public/UnrealWebSockets.h b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/Public/UnrealWebSockets.h new file mode 100644 index 0000000..bc282d9 --- /dev/null +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/Public/UnrealWebSockets.h @@ -0,0 +1,15 @@ +// Copyright 2020 Disney Direct-to-Consumer and International. All Rights Reserved. + +#pragma once + +#include "Modules/ModuleManager.h" +// + +class FUnrealWebSocketsModule : public IModuleInterface +{ +public: + + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; +}; diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/Public/UnrealWebSocketsBPLibrary.h b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/Public/UnrealWebSocketsBPLibrary.h new file mode 100644 index 0000000..ad61a67 --- /dev/null +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/Public/UnrealWebSocketsBPLibrary.h @@ -0,0 +1,17 @@ +// Copyright 2020 Disney Direct-to-Consumer and International. All Rights Reserved. + +#pragma once + +#include "Kismet/BlueprintFunctionLibrary.h" +#include "UnrealWebSocket.h" +#include "UnrealWebSocketsBPLibrary.generated.h" + +UCLASS() +class UUnrealWebSocketsBPLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_UCLASS_BODY() + + UFUNCTION(BlueprintCallable, meta = (DisplayName = "Create WebSocket", Keywords = "Create", DefaultToSelf="Owner", HidePin="Owner"), Category = "Unreal WebSockets") + static void CreateWebSocket(UObject* Owner, const FString Url, UUnrealWebSocket*& WebSocket); + +}; diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/UnrealWebSockets.Build.cs b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/UnrealWebSockets.Build.cs new file mode 100644 index 0000000..b108e61 --- /dev/null +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/UnrealWebSockets.Build.cs @@ -0,0 +1,34 @@ +// Copyright 2020 Disney Direct-to-Consumer and International. All Rights Reserved. + +using UnrealBuildTool; + +public class UnrealWebSockets : ModuleRules +{ + public UnrealWebSockets(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + "WebSockets", + } + ); + + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "CoreUObject", + "Engine", + "Slate", + "SlateCore", + "HTTP", + "Json", + "JsonUtilities", + "WebSockets", + } + ); + } +} diff --git a/UE4-27-0/Plugins/UnrealHelper/UnrealHelper.uplugin b/UE4-27-0/Plugins/UnrealHelper/UnrealHelper.uplugin new file mode 100644 index 0000000..9699f18 --- /dev/null +++ b/UE4-27-0/Plugins/UnrealHelper/UnrealHelper.uplugin @@ -0,0 +1,54 @@ +{ + "FileVersion": 3, + "Version": 1, + "VersionName": "0.1", + "FriendlyName": "UnrealHelper", + "Description": "Blueprint extensions to built-in Unreal methods", + "Category": "Blueprints", + "CreatedBy": "", + "CreatedByURL": "", + "DocsURL": "", + "MarketplaceURL": "", + "SupportURL": "", + "CanContainContent": false, + "IsBetaVersion": true, + "IsExperimentalVersion": false, + "Installed": false, + "Modules": [ + { + "Name": "UnrealHelper", + "Type": "Runtime", + "LoadingPhase": "PreLoadingScreen" + }, + { + "Name": "UnrealHttp", + "Type": "Runtime", + "LoadingPhase": "PreLoadingScreen" + }, + { + "Name": "UnrealJson", + "Type": "Runtime", + "LoadingPhase": "PreLoadingScreen" + }, + { + "Name": "UnrealMediaOutputSocket", + "Type": "Runtime", + "LoadingPhase": "PreLoadingScreen" + }, + { + "Name": "UnrealWebSockets", + "Type": "Runtime", + "LoadingPhase": "PreLoadingScreen" + } + ], + "Plugins": [ + { + "Name": "MediaIOFramework", + "Enabled": true + }, + { + "Name": "HardwareEncoders", + "Enabled": true + } + ] +} diff --git a/UE4-27-0/README.md b/UE4-27-0/README.md new file mode 100644 index 0000000..e6846ed --- /dev/null +++ b/UE4-27-0/README.md @@ -0,0 +1,11 @@ +# VictoryPlugin Tests + +These Blueprint tests show how to use the VictoryHelper plugin and bring in some automated testing. + +Four submodules are being developed using this method: +- Json - This provides object to JSON and JSON string to object features. +- WebSockets - Exposes the websockets API based on the standard browser api +- Http - Providing streaming HTTP PUT and HTTP GET methods for larger files. +- MediaOutputSocket - Using the capture API to stream real-time frames to a console program, with FFMpeg as the default target + +These four submodules were originally developed by Charles Pritchard at the Walt Disney Company and approved for submission to the VictoryPlugin repository under its open source license. They may be submitted to Epic's Unreal Engine repository once modified for inclusion into the Unreal Engine project. \ No newline at end of file diff --git a/UE4-27-0/UnrealHelper.uproject b/UE4-27-0/UnrealHelper.uproject new file mode 100644 index 0000000..7844e5a --- /dev/null +++ b/UE4-27-0/UnrealHelper.uproject @@ -0,0 +1,16 @@ +{ + "FileVersion": 3, + "EngineAssociation": "4.27", + "Category": "", + "Description": "", + "Plugins": [ + { + "Name": "MediaFrameworkUtilities", + "Enabled": true + }, + { + "Name": "MediaIOFramework", + "Enabled": true + } + ] +} \ No newline at end of file From 4445acad8d9f2973ca0419292d56dcfc43126586 Mon Sep 17 00:00:00 2001 From: Charles Pritchard Date: Mon, 3 Oct 2022 11:50:19 -0700 Subject: [PATCH 2/2] MIT licensed --- .../UnrealHelper/Private/UnrealHelper.cpp | 2 -- .../Private/UnrealHelperBPLibrary.cpp | 22 ------------------- .../Source/UnrealHelper/Public/UnrealHelper.h | 2 -- .../Public/UnrealHelperBPLibrary.h | 2 -- .../Source/UnrealHelper/UnrealHelper.Build.cs | 2 -- .../Source/UnrealHttp/Private/UnrealHttp.cpp | 2 -- .../Source/UnrealHttp/Public/UnrealHttp.h | 2 -- .../UnrealHttp/Public/UnrealHttpBPLibrary.h | 2 -- .../Source/UnrealHttp/UnrealHttp.Build.cs | 2 -- .../Private/UnrealMediaOutputSocket.cpp | 2 -- .../Public/UnrealWebSockets.h | 2 -- .../Public/UnrealWebSocketsBPLibrary.h | 2 -- .../UnrealWebSockets.Build.cs | 2 -- 13 files changed, 46 deletions(-) diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/Private/UnrealHelper.cpp b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/Private/UnrealHelper.cpp index 819aa9d..4a018d3 100644 --- a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/Private/UnrealHelper.cpp +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/Private/UnrealHelper.cpp @@ -1,5 +1,3 @@ -// Copyright 2020 Disney Direct-to-Consumer and International. All Rights Reserved. - #include "UnrealHelper.h" #define LOCTEXT_NAMESPACE "FUnrealHelperModule" diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/Private/UnrealHelperBPLibrary.cpp b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/Private/UnrealHelperBPLibrary.cpp index 8534995..839186b 100644 --- a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/Private/UnrealHelperBPLibrary.cpp +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/Private/UnrealHelperBPLibrary.cpp @@ -1,5 +1,3 @@ -// Copyright 2020 Disney Direct-to-Consumer and International. All Rights Reserved. - #include "UnrealHelperBPLibrary.h" #include "UnrealHelper.h" #include "IImageWrapper.h" @@ -35,26 +33,6 @@ void UUnrealHelperBPLibrary::GetStringFromGameConfig(const FString Section, cons ); } -void UUnrealHelperBPLibrary::GetProjectVersion(FString& ProjectVersion) -{ - GConfig->GetString( - TEXT("/Script/EngineSettings.GeneralProjectSettings"), - TEXT("ProjectVersion"), - ProjectVersion, - GGameIni - ); -} - -void UUnrealHelperBPLibrary::GetFloatAsStringWithPrecision(float InFloat, FString& ReturnValue, int32 Precision, bool IncludeLeadingZero) -{ - FNumberFormattingOptions NumberFormat; - NumberFormat.MinimumIntegralDigits = (IncludeLeadingZero) ? 1 : 0; - NumberFormat.MaximumIntegralDigits = 10000; - NumberFormat.MinimumFractionalDigits = Precision; - NumberFormat.MaximumFractionalDigits = Precision; - ReturnValue = FText::AsNumber(InFloat, &NumberFormat).ToString(); -} - FString UUnrealHelperBPLibrary::RunCommand(FString Cmd, FString Args, FString& StdErr) { FString Result; diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/Public/UnrealHelper.h b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/Public/UnrealHelper.h index da10856..5020def 100644 --- a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/Public/UnrealHelper.h +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/Public/UnrealHelper.h @@ -1,5 +1,3 @@ -// Copyright 2020 Disney Direct-to-Consumer and International. All Rights Reserved. - #pragma once #include "Modules/ModuleManager.h" diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/Public/UnrealHelperBPLibrary.h b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/Public/UnrealHelperBPLibrary.h index 0c0216a..255c8cf 100644 --- a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/Public/UnrealHelperBPLibrary.h +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/Public/UnrealHelperBPLibrary.h @@ -1,5 +1,3 @@ -// Copyright 2020 Disney Direct-to-Consumer and International. All Rights Reserved. - #pragma once #include "Kismet/BlueprintFunctionLibrary.h" diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/UnrealHelper.Build.cs b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/UnrealHelper.Build.cs index 844ea7e..b60ec40 100644 --- a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/UnrealHelper.Build.cs +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHelper/UnrealHelper.Build.cs @@ -1,5 +1,3 @@ -// Copyright 2020 Disney Direct-to-Consumer and International. All Rights Reserved. - using UnrealBuildTool; public class UnrealHelper : ModuleRules diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/Private/UnrealHttp.cpp b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/Private/UnrealHttp.cpp index cbe0149..81e9a49 100644 --- a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/Private/UnrealHttp.cpp +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/Private/UnrealHttp.cpp @@ -1,5 +1,3 @@ -// Copyright 2020 Disney Direct-to-Consumer and International. All Rights Reserved. - #include "UnrealHttp.h" #define LOCTEXT_NAMESPACE "FUnrealHttpModule" diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/Public/UnrealHttp.h b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/Public/UnrealHttp.h index e8fbcbe..6d31fa3 100644 --- a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/Public/UnrealHttp.h +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/Public/UnrealHttp.h @@ -1,5 +1,3 @@ -// Copyright 2020 Disney Direct-to-Consumer and International. All Rights Reserved. - #pragma once #include "Modules/ModuleManager.h" diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/Public/UnrealHttpBPLibrary.h b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/Public/UnrealHttpBPLibrary.h index fe55ec5..d0f9850 100644 --- a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/Public/UnrealHttpBPLibrary.h +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/Public/UnrealHttpBPLibrary.h @@ -1,5 +1,3 @@ -// Copyright 2020 Disney Direct-to-Consumer and International. All Rights Reserved. - #pragma once #include "Kismet/BlueprintFunctionLibrary.h" diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/UnrealHttp.Build.cs b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/UnrealHttp.Build.cs index 9e96991..abfc4a4 100644 --- a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/UnrealHttp.Build.cs +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealHttp/UnrealHttp.Build.cs @@ -1,5 +1,3 @@ -// Copyright 2020 Disney Direct-to-Consumer and International. All Rights Reserved. - using UnrealBuildTool; public class UnrealHttp : ModuleRules diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealMediaOutputSocket/Private/UnrealMediaOutputSocket.cpp b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealMediaOutputSocket/Private/UnrealMediaOutputSocket.cpp index 5443aa1..a10cce8 100644 --- a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealMediaOutputSocket/Private/UnrealMediaOutputSocket.cpp +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealMediaOutputSocket/Private/UnrealMediaOutputSocket.cpp @@ -1,5 +1,3 @@ -// Copyright 2020 Disney Direct-to-Consumer and International. All Rights Reserved. - #include "UnrealMediaOutputSocket.h" #define LOCTEXT_NAMESPACE "FUnrealMediaOutputSocketModule" diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/Public/UnrealWebSockets.h b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/Public/UnrealWebSockets.h index bc282d9..c6a25df 100644 --- a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/Public/UnrealWebSockets.h +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/Public/UnrealWebSockets.h @@ -1,5 +1,3 @@ -// Copyright 2020 Disney Direct-to-Consumer and International. All Rights Reserved. - #pragma once #include "Modules/ModuleManager.h" diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/Public/UnrealWebSocketsBPLibrary.h b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/Public/UnrealWebSocketsBPLibrary.h index ad61a67..eae90f1 100644 --- a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/Public/UnrealWebSocketsBPLibrary.h +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/Public/UnrealWebSocketsBPLibrary.h @@ -1,5 +1,3 @@ -// Copyright 2020 Disney Direct-to-Consumer and International. All Rights Reserved. - #pragma once #include "Kismet/BlueprintFunctionLibrary.h" diff --git a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/UnrealWebSockets.Build.cs b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/UnrealWebSockets.Build.cs index b108e61..347068d 100644 --- a/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/UnrealWebSockets.Build.cs +++ b/UE4-27-0/Plugins/UnrealHelper/Source/UnrealWebSockets/UnrealWebSockets.Build.cs @@ -1,5 +1,3 @@ -// Copyright 2020 Disney Direct-to-Consumer and International. All Rights Reserved. - using UnrealBuildTool; public class UnrealWebSockets : ModuleRules