foxygit / GZDoom Log in
commits tags

/src/net/webjoin/wj_menu.cpp · 3.69 KB

raw
#include "wj_menu.h"
#include "wj_server.h"
#include "wj_qr.h"
#include "wj_qrtexture.h"
#include "wj_input.h"

#include "doomstat.h"
#include "d_player.h"
#include "v_draw.h"
#include "v_video.h"
#include "v_font.h"
#include "gametexture.h"
#include "menu.h"
#include "vm.h"
#include "c_dispatch.h"

EXTERN_CVAR(Bool, ui_classic)

namespace
{
	WJQRTexture *g_qrTex = nullptr;
	FGameTexture *g_qrGameTex = nullptr;
	std::string g_qrForUrl;

	void EnsureQRTexture(const std::string &url)
	{
		if (g_qrGameTex != nullptr && g_qrForUrl == url)
			return;

		if (g_qrGameTex != nullptr)
		{
			delete g_qrGameTex;	// ref-counted Base releases g_qrTex too
			g_qrGameTex = nullptr;
			g_qrTex = nullptr;
		}

		WJQRImage img = WJ_MakeQRCode(url, 6);
		if (img.width == 0)
			return;

		g_qrTex = new WJQRTexture();
		g_qrTex->SetImage(img.width, img.width, img.rgba.data());
		g_qrGameTex = MakeGameTexture(g_qrTex, nullptr, ETextureType::Override);
		g_qrForUrl = url;
	}
}

void WJ_LobbyOpen()
{
	WJ_StartServer(0);
}

void WJ_LobbyDrawer()
{
	FFont *font = ui_classic ? SmallFont : NewSmallFont;
	int width = twod->GetWidth();
	int height = twod->GetHeight();

	int y = 12;
	const char *title = "Scan to join";
	DrawText(twod, BigFont, CR_WHITE, (width - BigFont->StringWidth(title)) / 2, y, title, TAG_DONE);
	y += BigFont->GetHeight() + 8;

	if (!WJ_IsServerRunning() || WJ_GetJoinURLCount() == 0)
	{
		const char *msg = !WJ_IsServerRunning()
			? "Could not start the join server."
			: "No network address found -- connect to Wi-Fi and reopen this screen.";
		DrawText(twod, font, CR_RED, (width - font->StringWidth(msg)) / 2, y, msg, TAG_DONE);
		y += font->GetHeight() + 12;
	}
	else
	{
		std::string url = WJ_GetJoinURL(0);
		EnsureQRTexture(url);

		if (g_qrGameTex != nullptr)
		{
			int qrSize = (width < height ? width : height) / 2;
			int qx = (width - qrSize) / 2;
			// DTA_VirtualWidth/Height must accompany DTA_DestWidth/Height --
			// see the comment in r_splitscreen.cpp's grid draw for why
			// leaving them unset produces an undefined (often tiny/
			// mispositioned) destination rect.
			DrawTexture(twod, g_qrGameTex, qx, y,
				DTA_DestWidth, qrSize, DTA_DestHeight, qrSize,
				DTA_VirtualWidth, width, DTA_VirtualHeight, height,
				DTA_TopLeft, true, TAG_DONE);
			y += qrSize + 8;
		}

		DrawText(twod, font, CR_WHITE, (width - font->StringWidth(url.c_str())) / 2, y, url.c_str(), TAG_DONE);
		y += font->GetHeight() + 12;
	}

	const char *rosterHeader = "Players";
	DrawText(twod, font, CR_GOLD, (width - font->StringWidth(rosterHeader)) / 2, y, rosterHeader, TAG_DONE);
	y += font->GetHeight() + 4;

	for (int i = 0; i < MAXPLAYERS; i++)
	{
		if (!playeringame[i])
			continue;

		bool remote = players[i].RemoteInputSlot;
		bool connected = true;
		if (remote)
		{
			WJRemoteInput &ri = wj_remoteInput[i];
			std::lock_guard<std::mutex> lock(ri.mtx);
			connected = ri.connected;
		}

		FString line;
		line.Format("%s%s", players[i].userinfo.GetName(),
			remote ? (connected ? " (phone)" : " (disconnected)") : " (this PC)");
		int color = (remote && !connected) ? CR_GREY : CR_WHITE;
		DrawText(twod, font, color, (width - font->StringWidth(line.GetChars())) / 2, y, line.GetChars(), TAG_DONE);
		y += font->GetHeight() + 2;
	}

	const char *prompt = "Press ENTER or ESC to close this screen";
	DrawText(twod, font, CR_GREY, (width - font->StringWidth(prompt)) / 2, height - font->GetHeight() - 8, prompt, TAG_DONE);
}

DEFINE_ACTION_FUNCTION_NATIVE(DMenu, WJ_LobbyOpen, WJ_LobbyOpen)
{
	PARAM_PROLOGUE;
	WJ_LobbyOpen();
	return 0;
}

DEFINE_ACTION_FUNCTION_NATIVE(DMenu, WJ_LobbyDrawer, WJ_LobbyDrawer)
{
	PARAM_PROLOGUE;
	WJ_LobbyDrawer();
	return 0;
}

CCMD(webjoin_lobby)
{
	M_StartControlPanel(true);
	M_SetMenu("PhoneJoinLobbyMenu");
}