C++ 在 Unreal 中为游戏增加实时音视频互动的教程详解

2020-05-29 11:02:26于丽

要对相应的按钮 "onButtonClick "事件做出反应。

//EnterChannelWidget.h
..

UCLASS()
class AGORAVIDEOCALL_API UEnterChannelWidget : public UUserWidget
{
 GENERATED_BODY()

public:

 ...

 UFUNCTION(BlueprintCallable)
 void OnJoin();

 ...
};
//EnterChannelWidget.cpp


void UEnterChannelWidget::OnJoin()
{
 if (!PlayerController || !VideoCallPtr)
 {
 return;
 }

 FString ChannelName = ChannelNameTextBox->GetText().ToString();

 FString EncryptionKey = EncriptionKeyTextBox->GetText().ToString();
 FString EncryptionType = EncriptionTypeComboBox->GetSelectedOption();

 SetVisibility(ESlateVisibility::Collapsed);

 PlayerController->StartCall(
 std::move(VideoCallPtr),
 ChannelName,
 EncryptionKey,
 EncryptionType);
}

增加 update 方法

//EnterChannelWidget.h


...


UCLASS()
class AGORAVIDEOCALL_API UEnterChannelWidget : public UUserWidget
{
 GENERATED_BODY()

public:
 ...

 void UpdateVersionText(FString newValue);

 ...
};
//EnterChannelWidget.cpp

void UEnterChannelWidget::UpdateVersionText(FString newValue)
{
 if (BuildInfoTextBlock)
 BuildInfoTextBlock->SetText(FText::FromString(newValue));
}

创建 VideoViewWidget C++ 类

VideoViewWidget是一个存储动态纹理并使用RGBA buffer 更新动态纹理的类,该类是从VideoCall OnLocalFrameCallback/OnRemoteFrameCallback函数中接收到的。

创建类和添加所需的 include

//VideoViewWidget.h

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"

#include "Components/Image.h"

#include "VideoViewWidget.generated.h"
//VideoViewWidget.cpp

#include "EngineUtils.h"
#include "Engine/Texture2D.h"

#include <algorithm>

添加成员变量

Buffer:用于存储RGBA缓冲区、Width、Height和BufferSize的变量 - 视频帧的参数。 RenderTargetImage:允许你在UI中显示Slate Brush或纹理或材质的图像小部件。 RenderTargetTexture:动态纹理,我们将使用Buffer变量更新。

FUpdateTextureRegion2D:指定一个纹理的更新区域 刷子 - 一个包含如何绘制Slate元素的笔刷。我们将用它来绘制RenderTargetImage上的RenderTargetTexture。

//VideoViewWidget.h

...

UCLASS()
class AGORAVIDEOCALL_API UVideoViewWidget : public UUserWidget
{
 GENERATED_BODY()

public:
 UPROPERTY(BlueprintReadOnly, meta = (BindWidget))
 UImage* RenderTargetImage = nullptr;

 UPROPERTY(EditDefaultsOnly)
 UTexture2D* RenderTargetTexture = nullptr;

 UTexture2D* CameraoffTexture = nullptr;

 uint8* Buffer = nullptr;
 uint32_t Width = 0;
 uint32_t Height = 0;
 uint32 BufferSize = 0;
 FUpdateTextureRegion2D* UpdateTextureRegion = nullptr;

 FSlateBrush Brush;

 FCriticalSection Mutex;

 ...
};

覆盖 NativeConstruct() 方法

在NativeConstruct中,我们将用默认颜色初始化我们的图像。为了初始化我们的RenderTargetTexture,我们需要使用CreateTransient调用创建动态纹理(Texture2D)。然后分配BufferSize为Width * Height * 4的BufferSize(用于存储RGBA格式,每个像素可以用4个字节表示)。为了更新我们的纹理,我们可以使用UpdateTextureRegions函数。这个函数的输入参数之一是我们的像素数据缓冲区。这样,每当我们修改像素数据缓冲区时,我们就需要调用这个函数来使变化在纹理中可见。现在用我们的RenderTargetTexture初始化Brush变量,然后在RenderTargetImage widget中设置这个Brush。