/
MyGameViewportClient.cpp
81 lines (72 loc) · 2.54 KB
/
MyGameViewportClient.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
// Fill out your copyright notice in the Description page of Project Settings.
#include "RealisticRendering.h"
#include "ImageUtils.h"
#include "MyGameViewportClient.h"
// TODO: Add lock to wait for screen capture finish
UMyGameViewportClient::UMyGameViewportClient()
{
EventWaitCapture = FPlatformProcess::GetSynchEventFromPool(false);
// false means auto-reset, undocumented, but can be found in source code.
}
// Reimplement a GameViewportClient is required according to the discussion from here
// https://forums.unrealengine.com/showthread.php?50857-FViewPort-ReadPixels-crash-while-play-on-quot-standalone-Game-quot-mode
void UMyGameViewportClient::Draw(FViewport * Viewport, FCanvas * SceneCanvas)
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//this line is reaalllly important
Super::Draw(Viewport, SceneCanvas);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (IsPendingSaveRequest)
{
DoCaptureScreen();
}
}
void UMyGameViewportClient::DoCaptureScreen()
{
// Save to Disk
TArray<FColor> Bitmap;
bool bScreenshotSuccessful = false;
// UGameViewportClient* ViewportClient = GetWorld()->GetGameViewport();
// FViewport* InViewport = ViewportClient->Viewport;
FViewport* InViewport = this->Viewport;
// ViewportClient->GetEngineShowFlags()->SetMotionBlur(false);
GetEngineShowFlags()->SetMotionBlur(false);
bScreenshotSuccessful = GetViewportScreenShot(InViewport, Bitmap);
// ViewportClient->GetHighResScreenshotConfig().MergeMaskIntoAlpha(Bitmap);
// Ensure that all pixels' alpha is set to 255
for (auto& Color : Bitmap)
{
Color.A = 255;
}
if (bScreenshotSuccessful)
{
FIntVector Size(InViewport->GetSizeXY().X, InViewport->GetSizeXY().Y, 0);
// TODO: Need to blend alpha, a bit weird from screen.
TArray<uint8> CompressedBitmap;
FImageUtils::CompressImageArray(Size.X, Size.Y, Bitmap, CompressedBitmap);
FFileHelper::SaveArrayToFile(CompressedBitmap, *CaptureFilename);
// return FExecStatus(Filename);
}
else
{
// return FExecStatus::Error("Fail to capture image"); // TODO: Handle error
}
// TODO: Trigger a wait event
IsPendingSaveRequest = false;
EventWaitCapture->Trigger(); // Auto reset
}
void UMyGameViewportClient::CaptureScreen(const FString& Filename)
{
CaptureFilename = Filename;
IsPendingSaveRequest = true;
if (IsInGameThread())
{
// DoCaptureScreen(); // a direct call to DoCaptureScreen is not allowed.
// A potential risk that the file is not saved yet. TODO: Fix this.
}
else
{
// Not allow to wait in Game Thread, Draw will also happen in Game Thread
EventWaitCapture->Wait();
}
}