用UE4来做Zego即构的房间列表

  Zego即构是一家做直播的服务商,Zego即构自己的房间列表,本文只是测试功能用,相应代码并没完全测试,请选择性参考。

  

  我们在UE4中来实现一下,我感觉这个过程有点意思,UE4中C++与蓝图和UI的互相通信基本全部用到了。

  Zego即构没有专门的UE4插件,所以我们主要逻辑全部在C++中,蓝图只是辅助。

  首先,我们定义一个房间结构,因为要想UE4中C++和蓝图可见可用,我们要用C++实现,并实现特定的写法让蓝图知道。

USTRUCT(BlueprintType)
struct FRoomBlueprint
{
    GENERATED_BODY()

        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "")
        FString roomId;
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "")
        FString roomName;
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "")
        FString anchorName;
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "")
        int streamSize;
public:
    FRoomBlueprint()
    {
        roomId = nullptr;
        roomName = nullptr;
        anchorName = nullptr;
        streamSize = 0;
    }
};

FRoomBlueprint

  理一下逻辑,UE得到所有房间列表,然后给UE4蓝图,蓝图根据每个房间列表创建对应个房间,完成了。

  我们找一下Zego即构的如何获得房间列表的API,发现他是通过Http Get方式得到的,因为Http Get我们肯定以异步方式来实现,那么如何通知蓝图了,我们需要定义一个蓝图能识别的事件委托才行。

using namespace ZEGO::LIVEROOM;

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnGetRoomList, TArray<FRoomBlueprint>, roomList);

UCLASS()
class TESTJIGOU_API AJigouMain : public AActor, public IZegoVideoRenderCallback
{
    GENERATED_BODY()

public:
    // Sets default values for this actor‘s properties
    AJigouMain();

protected:
    // Called when the game starts or when spawned
    virtual void BeginPlay() override;
    virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;

public:
    // Called every frame
    virtual void Tick(float DeltaTime) override;
    virtual void OnVideoDataCallback(const unsigned char*, int, const char*, int, int, int[4]);

    UPROPERTY(BlueprintAssignable)
        FOnGetRoomList eventGetRoomList;
    UFUNCTION(BlueprintCallable, Category = "AMRVideo")
        void PullRoomList();

};
void AJigouMain::PullRoomList()
{
    FString baseUri = FString::Printf(_T("https://liveroom%u-api.zego.im/demo/roomlist?appid=%u"),
        ManagerConnect::Get().GetAppID(), ManagerConnect::Get().GetAppID());

    auto HttpRequest = FHttpModule::Get().CreateRequest();
    HttpRequest->SetVerb("GET");
    HttpRequest->SetHeader("Content-Type", "application/json");
    HttpRequest->SetURL(baseUri);
    //HttpRequest->SetContentAsString(JsonStr);
    HttpRequest->OnProcessRequestComplete().BindLambda(
        [&](FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful)
    {
        if (Response.Get() == nullptr)
            return;
        auto content = Response->GetContentAsString();
        TSharedPtr<FJsonObject> JsonObject;
        auto Reader = TJsonReaderFactory<>::Create(content);
        if (FJsonSerializer::Deserialize(Reader, JsonObject))
        {
            auto state = JsonObject->GetIntegerField("code");
            if (state != 1)
            {
                TArray<FRoomBlueprint> roomArray;
                auto data = JsonObject->GetObjectField("data");
                auto roomList = data->GetArrayField("room_list");
                int lenght = roomList.Num();
                for (int i = 0; i < lenght; i++)
                {
                    FRoomBlueprint rInfo = {};
                    auto room = roomList[i]->AsObject();
                    rInfo.roomId = room->GetStringField("room_id");
                    rInfo.roomName = room->GetStringField("room_name");
                    rInfo.anchorName = room->GetStringField("anchor_id_name");

                    auto listStream = room->GetArrayField("stream_info");
                    if (listStream.Num() > 0)
                    {
                        rInfo.streamSize = listStream.Num();
                        roomArray.Add(rInfo);
                    }
                }
                if (eventGetRoomList.IsBound())
                {
                    eventGetRoomList.Broadcast(roomArray);
                }
            }
        }
    });

    HttpRequest->ProcessRequest();

}

AJigouMain

  其实如果我们不直接用C++实例,再实现一个蓝图继承AJigouMain,然后实现UFUNCTION(BlueprintNativeEvent)也一样可以得到这个效果,再这,我们就直接把如上AJigouMain实例结果放入场景中。

  嗯,逻辑部分差不多了,我们开始实现UI,首先我们定义一个房间控件。

  

  嗯,记的我们前面声明的结构FRoomBlueprint吗,一个房间对应一个FRoomBlueprint,前面文本分别绑定对应FRoomBlueprint的流数,房间名。

  我们要考虑的是点击加入后如何把当前房间的信息发散出去,简单来说,调用一个事件,事件要包含当前的点击的房间信息,至于事件绑定的执行函数,我们现在还不知道,也不用考虑。

  

  简单来说,Room这个房间控件知道的就是,我点击了我的加入button,并在点击后,调用OnJoin,调用当前事件把对应的FRoomBlueprint结构传入事件中,这个控件就不需要管别的事了。

  如上,得到所有房间后,需要根据得到的房间列表生成对应的房间列表UI,有如上的房间控件后,我们来看看UE4如何生成列表。

  

  如上主要逻辑都在UIPanel里,Room List box就是一个UE4里的Vertical Box控件,用来垂直放入我们上面的Room控件,并把每个FRoomBlueprint实例传入对应的Room控件,在这个集中门面类中,我们知道对应的Room控件的加入功能具体能做什么了,绑定有相同的函数签名的事件上就行了。并且结合上面的eventGetRoomList事件,我们调用这个方法就行了。

  

  对应的加入房间,我们提供一个简单的UBlueprintFunctionLibrary类,帮我们处理一些基本的C++事件,如:

UCLASS()
class TESTJIGOU_API UBlueprintHelper : public UBlueprintFunctionLibrary
{
    GENERATED_BODY()

public:
    UFUNCTION(BlueprintPure, Category = "AJigouMain")
        static bool OnJoinRoom(FRoomBlueprint room, FString userID);

    UFUNCTION(BlueprintPure, Category = "AJigouMain")
        static TArray<FDeviceInfo> GetDeviceList();

    UFUNCTION(BlueprintPure, Category = "AJigouMain")
        static bool OnCreateRoom(FString userID);

    UFUNCTION(BlueprintPure, Category = "AJigouMain")
        static bool SetDeviceRoom(FString deviceID);

    UFUNCTION(BlueprintPure, Category = "AJigouMain")
        static bool SetDeviceRoom2(FString deviceID);

    UFUNCTION(BlueprintPure, Category = "AJigouMain")
        static bool SetRole(int roleID);

    UFUNCTION(BlueprintPure, Category = "AJigouMain")
        static FString GetRoleName();

    UFUNCTION(BlueprintPure, Category = "AJigouMain")
        static bool PullStream(FString stream);
};
bool UBlueprintHelper::OnJoinRoom(FRoomBlueprint room, FString userID)
{
    auto currentRole = ManagerConnect::Get().getCurrentRole();
    FTCHARToUTF8 user(*(currentRole.userID));
    FString roomID = room.roomId;
    FString roomName = room.roomName;
    auto bJoin = LIVEROOM::SetUser(user.Get(), user.Get());
    if (bJoin)
    {
        FTCHARToUTF8 id(*roomID);
        FTCHARToUTF8 roomName(*roomName);
        auto bJoin = LIVEROOM::LoginRoom(id.Get(), currentRole.role, roomName.Get());
        ManagerConnect::Get().bAuthor = false;
    }
    return bJoin;
}

  倒数第二张图上,点击加入按键,绑定的方法就是这个方法。

  最后效果图:

  和直播出来画面不一样是因为我们在UE4里做了反畸变,用的是in.yml生成的一张UV贴图,需要注意的是,此处这图贴图最好用PF_FloatRGBA,不要用R8G8B8A8,精度不够,生成的图片很多裂变,PF_FloatRGBA对应的是FFloat16Color,而不是FLineColor。  

时间: 2024-08-10 01:59:53

用UE4来做Zego即构的房间列表的相关文章

笔记(用Python做些事情)--变量(列表、元组)

列表:切片,索引,引用 生成列表:a=[1,2,3] 引用:a_ref=a,和a指向同一个地址 列表常用的操作:copy操作 b=a[:] a.append(3):在列表a后面加一个元素 a.insert(1, 20):将20插到列表a的1的位置上 a.pop():把列表的最后个元素弹出来 a.sort():对列表排序 a.reverse():对列表反排序 del a[1]:把列表的第一个元素删除掉 嵌套,多种类型并存到一个列表,比如c=[1,2,'123','abc'] a.count(x):

一步一步来做WebQQ机器人-(四)(获取好友列表和群列表)

× 本篇主要是: 获取好友列表,群列表 我会尽量详细一点,尽我所知的分享一些可能大家已经掌握的或者还不清楚的经验 利于大家阅读,文章样式不再复杂化,根据内容取固定色 目前总进度大概65% 全系列预计会有这些步骤,当然某些步骤可能会合并: 验证码 第一次登陆 第二次登陆 保持在线和接收消息 获取好友和群列表 发送消息 变成智能的(*?∀?*) 获取好友 1-获取QQ好友的hash算法 P = function (b, j) { for (var a = j + "password error&qu

Node.js 打造实时多人游戏框架

在 Node.js 如火如荼发展的今天,我们已经可以用它来做各种各样的事情.前段时间UP主参加了极客松活动,在这次活动中我们意在做出一款让“低头族”能够更多交流的游戏,核心功能便是 Lan Party 概念的实时多人互动.极客松比赛只有短得可怜的36个小时,要求一切都敏捷迅速.在这样的前提下初期的准备显得有些“水到渠成”.跨平台应用的 solution 我们选择了node-webkit,它足够简单且符合我们的要求. 按照需求,我们的开发可以按照模块分开进行.本文具体讲述了开发 Spaceroom

如何在Java平台上使用脚本语言做Java开发

如何在Java平台上使用脚本语言做Java开发     最近开始流行区分Java平台和Java语言,但很多Java开发者还是不能确定如何在 Java应用程序开发中结合脚本.本篇文章,Gregor Roth给出了在Java平台上使用脚本的方法.通过这篇文章,你可以了解怎样在你的Java应用程序中使用脚本,是否你要通过使用Groovy和 Jython把不同的Java应用程序模块粘合在一起,或者写一个你自己的基于JRuby的应用程序,适用于Java平台. 作为一个Java开发者,你可能已经注意到了,J

我们应当怎样做需求分析

我们应当怎样做需求调研:初识 3 我们应当怎样做需求调研:拜访 5 我们应当怎样做需求调研:研讨会 7 我们应当怎样做需求调研:需求研讨 9 我们应当怎样做需求调研:迭代 11 我们应当怎样做需求调研:需求捕获 13 我们应当怎样做需求分析:功能角色分析与用例图 15 我们应当怎样做需求分析:业务流程分析 18 我们应当怎样做需求分析:用例说明 21 我们应当怎样做需求分析:查询报表分析 23 我们应当怎样做需求分析:子用例与扩展用例 24 我们应当怎样做需求分析:行动图和状态图 25 我们应当

我们应该怎么做需求分析

他去过年.而且从日历2011反过来2012岁月.这给了我很多感慨,然后勾起太多的回忆审查.过去10年,毫无疑问,中国的软件业增长最快10年. 当我们刚刚毕业.它仍然是在使用VB.PB开发一些简单的数据库应用程序,现在,我几乎看不到他们的视线.作为回报,如J2EE和.NET这种大型web应用.而这期间,RUP.XP.敏捷开发.持续集成??????一个接一个的新概念层出不穷,令人眼花缭乱.如今想来,恍如隔世. 但更令我印象深刻而难以忘怀的.是我亲自经历的.亲眼目睹的.道听途说的一个又一个的软件项目.

我们应当如何做需求分析

又到新年了,日历又要从2011年翻到2012年了,这使我有太多的感慨,进而勾起了对太多往事的回顾.过去的10年,毫无疑问是中国软件业发展最快的10年.当我们刚刚毕业的时候,还在使用VB.PB开发一些简单的数据库应用,而如今却差点儿看不到它们的踪影,换来的是诸如J2EE和.NET这种大型web应用.而这期间,RUP.XP.敏捷开发.持续集成??????一个接一个的新概念层出不穷,令人眼花缭乱.如今想来,恍如隔世. 但更令我印象深刻而难以忘怀的,是我亲自经历的.亲眼目睹的.道听途说的一个又一个的软件

解构赋值的用途

所谓解构赋值,就是允许按照一定模式,从对象和数组从提取值,对变量进行赋值,这就是解构赋值. 注意:这里只能对数组和对象进行解构赋值. //数组的解构赋值 let a,b,rest; [a,b] = [1,2]; [a,b,...rest] = [1,2,3,4,5]; //对象的解构赋值 ({a,b} = {a:1,b:2}); ({a,b,...rest} = {a:1,b:2,c:3,d:4}) //注意:rest必须是解构赋值参数列表的最后一个参数 let [foo,[[bar],baz]

音视频技术学习

转自https://blog.csdn.net/ucvive/article/details/78220734 音视频SDK开发包涉及的技术要求音视频软件开发,也叫音视频即时通信开发.随着互联网的发展,每天都有相当多的人在使用各种网络交流工具,如MSN,腾讯QQ,ICQ,新浪微博.然而目前大部分网络交流工具都还是以文字为主,语音视频功能大部分还是不够成熟,完全通过网络实现语音视频需要考虑到很多方面,如:硬件.软件.技术.网络;等等.因此,即时通讯软件开发诞生了.简而言之,即时通讯软件开发就是通过