Citra-qt: Add multiplayer ui
This commit is contained in:
parent
bba2a60b22
commit
871196bc10
34 changed files with 2653 additions and 46 deletions
|
@ -31,8 +31,14 @@
|
|||
#include "citra_qt/game_list.h"
|
||||
#include "citra_qt/hotkeys.h"
|
||||
#include "citra_qt/main.h"
|
||||
#include "citra_qt/multiplayer/client_room.h"
|
||||
#include "citra_qt/multiplayer/direct_connect.h"
|
||||
#include "citra_qt/multiplayer/host_room.h"
|
||||
#include "citra_qt/multiplayer/lobby.h"
|
||||
#include "citra_qt/multiplayer/message.h"
|
||||
#include "citra_qt/ui_settings.h"
|
||||
#include "citra_qt/updater/updater.h"
|
||||
#include "citra_qt/util/clickable_label.h"
|
||||
#include "common/logging/backend.h"
|
||||
#include "common/logging/filter.h"
|
||||
#include "common/logging/log.h"
|
||||
|
@ -129,6 +135,20 @@ GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr) {
|
|||
|
||||
SetupUIStrings();
|
||||
|
||||
Network::Init();
|
||||
|
||||
if (auto member = Network::GetRoomMember().lock()) {
|
||||
// register the network structs to use in slots and signals
|
||||
qRegisterMetaType<Network::RoomMember::State>();
|
||||
state_callback_handle = member->BindOnStateChanged(
|
||||
[this](const Network::RoomMember::State& state) { emit NetworkStateChanged(state); });
|
||||
connect(this, &GMainWindow::NetworkStateChanged, this, &GMainWindow::OnNetworkStateChanged);
|
||||
}
|
||||
|
||||
qRegisterMetaType<Common::WebResult>();
|
||||
|
||||
setWindowTitle(QString("Citra %1| %2-%3")
|
||||
.arg(Common::g_build_name, Common::g_scm_branch, Common::g_scm_desc));
|
||||
show();
|
||||
|
||||
game_list->LoadCompatibilityList();
|
||||
|
@ -153,6 +173,13 @@ GMainWindow::~GMainWindow() {
|
|||
delete render_window;
|
||||
|
||||
Pica::g_debug_context.reset();
|
||||
|
||||
if (state_callback_handle) {
|
||||
if (auto member = Network::GetRoomMember().lock()) {
|
||||
member->Unbind(state_callback_handle);
|
||||
}
|
||||
}
|
||||
Network::Shutdown();
|
||||
}
|
||||
|
||||
void GMainWindow::InitializeWidgets() {
|
||||
|
@ -193,12 +220,22 @@ void GMainWindow::InitializeWidgets() {
|
|||
tr("Time taken to emulate a 3DS frame, not counting framelimiting or v-sync. For "
|
||||
"full-speed emulation this should be at most 16.67 ms."));
|
||||
|
||||
announce_multiplayer_session = std::make_shared<Core::AnnounceMultiplayerSession>();
|
||||
announce_multiplayer_session->BindErrorCallback(
|
||||
[this](const Common::WebResult& result) { emit AnnounceFailed(result); });
|
||||
connect(this, &GMainWindow::AnnounceFailed, this, &GMainWindow::OnAnnounceFailed);
|
||||
network_status = new ClickableLabel();
|
||||
network_status->setToolTip(tr("Current connection status"));
|
||||
|
||||
for (auto& label : {emu_speed_label, game_fps_label, emu_frametime_label}) {
|
||||
label->setVisible(false);
|
||||
label->setFrameStyle(QFrame::NoFrame);
|
||||
label->setContentsMargins(4, 0, 4, 0);
|
||||
statusBar()->addPermanentWidget(label, 0);
|
||||
}
|
||||
statusBar()->addPermanentWidget(network_status, 0);
|
||||
network_status->setPixmap(QIcon::fromTheme("disconnected").pixmap(16));
|
||||
network_status->setText(tr("Not Connected. Join a room for online play!"));
|
||||
statusBar()->setVisible(true);
|
||||
|
||||
// Removes an ugly inner border from the status bar widgets under Linux
|
||||
|
@ -392,6 +429,8 @@ void GMainWindow::ConnectWidgetEvents() {
|
|||
connect(this, &GMainWindow::UpdateProgress, this, &GMainWindow::OnUpdateProgress);
|
||||
connect(this, &GMainWindow::CIAInstallReport, this, &GMainWindow::OnCIAInstallReport);
|
||||
connect(this, &GMainWindow::CIAInstallFinished, this, &GMainWindow::OnCIAInstallFinished);
|
||||
|
||||
connect(network_status, &ClickableLabel::clicked, this, &GMainWindow::OnOpenNetworkRoom);
|
||||
}
|
||||
|
||||
void GMainWindow::ConnectMenuEvents() {
|
||||
|
@ -418,6 +457,15 @@ void GMainWindow::ConnectMenuEvents() {
|
|||
ui.action_Show_Filter_Bar->setShortcut(tr("CTRL+F"));
|
||||
connect(ui.action_Show_Filter_Bar, &QAction::triggered, this, &GMainWindow::OnToggleFilterBar);
|
||||
connect(ui.action_Show_Status_Bar, &QAction::triggered, statusBar(), &QStatusBar::setVisible);
|
||||
|
||||
// Multiplayer
|
||||
connect(ui.action_View_Lobby, &QAction::triggered, this, &GMainWindow::OnViewLobby);
|
||||
connect(ui.action_Start_Room, &QAction::triggered, this, &GMainWindow::OnCreateRoom);
|
||||
connect(ui.action_Stop_Room, &QAction::triggered, this, &GMainWindow::OnCloseRoom);
|
||||
connect(ui.action_Connect_To_Room, &QAction::triggered, this,
|
||||
&GMainWindow::OnDirectConnectToRoom);
|
||||
connect(ui.action_Chat, &QAction::triggered, this, &GMainWindow::OnOpenNetworkRoom);
|
||||
|
||||
ui.action_Fullscreen->setShortcut(GetHotkey("Main Window", "Fullscreen", this)->key());
|
||||
ui.action_Screen_Layout_Swap_Screens->setShortcut(
|
||||
GetHotkey("Main Window", "Swap Screens", this)->key());
|
||||
|
@ -880,6 +928,30 @@ void GMainWindow::OnMenuRecentFile() {
|
|||
}
|
||||
}
|
||||
|
||||
void GMainWindow::OnNetworkStateChanged(const Network::RoomMember::State& state) {
|
||||
LOG_INFO(Frontend, "network state change");
|
||||
if (state == Network::RoomMember::State::Joined) {
|
||||
network_status->setPixmap(QIcon::fromTheme("connected").pixmap(16));
|
||||
network_status->setText(tr("Connected"));
|
||||
ui.action_Chat->setEnabled(true);
|
||||
return;
|
||||
}
|
||||
network_status->setPixmap(QIcon::fromTheme("disconnected").pixmap(16));
|
||||
network_status->setText(tr("Not Connected"));
|
||||
ui.action_Chat->setDisabled(true);
|
||||
|
||||
ChangeRoomState();
|
||||
}
|
||||
|
||||
void GMainWindow::OnAnnounceFailed(const Common::WebResult& result) {
|
||||
announce_multiplayer_session->Stop();
|
||||
QMessageBox::warning(
|
||||
this, tr("Error"),
|
||||
tr("Announcing the room failed.\nThe room will not get listed publicly.\nError: ") +
|
||||
QString::fromStdString(result.result_string),
|
||||
QMessageBox::Ok);
|
||||
}
|
||||
|
||||
void GMainWindow::OnStartGame() {
|
||||
emu_thread->SetRunning(true);
|
||||
qRegisterMetaType<Core::System::ResultStatus>("Core::System::ResultStatus");
|
||||
|
@ -1054,6 +1126,80 @@ void GMainWindow::OnCreateGraphicsSurfaceViewer() {
|
|||
graphicsSurfaceViewerWidget->show();
|
||||
}
|
||||
|
||||
static void BringWidgetToFront(QWidget* widget) {
|
||||
widget->show();
|
||||
widget->activateWindow();
|
||||
widget->raise();
|
||||
}
|
||||
|
||||
void GMainWindow::OnViewLobby() {
|
||||
if (lobby == nullptr) {
|
||||
lobby = new Lobby(this, game_list->GetModel(), announce_multiplayer_session);
|
||||
connect(lobby, &Lobby::Closed, [&] {
|
||||
LOG_INFO(Frontend, "Destroying lobby");
|
||||
// lobby->close();
|
||||
lobby = nullptr;
|
||||
});
|
||||
}
|
||||
BringWidgetToFront(lobby);
|
||||
}
|
||||
|
||||
void GMainWindow::OnCreateRoom() {
|
||||
if (host_room == nullptr) {
|
||||
host_room = new HostRoomWindow(this, game_list->GetModel(), announce_multiplayer_session);
|
||||
connect(host_room, &HostRoomWindow::Closed, [&] {
|
||||
// host_room->close();
|
||||
LOG_INFO(Frontend, "Destroying host room");
|
||||
host_room = nullptr;
|
||||
});
|
||||
}
|
||||
BringWidgetToFront(host_room);
|
||||
}
|
||||
|
||||
void GMainWindow::OnCloseRoom() {
|
||||
if (auto room = Network::GetRoom().lock()) {
|
||||
if (room->GetState() == Network::Room::State::Open) {
|
||||
if (NetworkMessage::WarnCloseRoom()) {
|
||||
room->Destroy();
|
||||
announce_multiplayer_session->Stop();
|
||||
// host_room->close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GMainWindow::OnOpenNetworkRoom() {
|
||||
if (auto member = Network::GetRoomMember().lock()) {
|
||||
if (member->IsConnected()) {
|
||||
if (client_room == nullptr) {
|
||||
client_room = new ClientRoomWindow(this);
|
||||
connect(client_room, &ClientRoomWindow::Closed, [&] {
|
||||
LOG_INFO(Frontend, "Destroying client room");
|
||||
// client_room->close();
|
||||
client_room = nullptr;
|
||||
});
|
||||
}
|
||||
BringWidgetToFront(client_room);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// If the user is not a member of a room, show the lobby instead.
|
||||
// This is currently only used on the clickable label in the status bar
|
||||
OnViewLobby();
|
||||
}
|
||||
|
||||
void GMainWindow::OnDirectConnectToRoom() {
|
||||
if (direct_connect == nullptr) {
|
||||
direct_connect = new DirectConnectWindow(this);
|
||||
connect(direct_connect, &DirectConnectWindow::Closed, [&] {
|
||||
LOG_INFO(Frontend, "Destroying direct connect");
|
||||
// direct_connect->close();
|
||||
direct_connect = nullptr;
|
||||
});
|
||||
}
|
||||
BringWidgetToFront(direct_connect);
|
||||
}
|
||||
|
||||
void GMainWindow::UpdateStatusBar() {
|
||||
if (emu_thread == nullptr) {
|
||||
status_bar_update_timer.stop();
|
||||
|
@ -1187,6 +1333,16 @@ void GMainWindow::closeEvent(QCloseEvent* event) {
|
|||
|
||||
render_window->close();
|
||||
|
||||
// Close Multiplayer windows
|
||||
if (host_room)
|
||||
host_room->close();
|
||||
if (direct_connect)
|
||||
direct_connect->close();
|
||||
if (client_room)
|
||||
client_room->close();
|
||||
if (lobby)
|
||||
lobby->close();
|
||||
|
||||
QWidget::closeEvent(event);
|
||||
}
|
||||
|
||||
|
@ -1306,6 +1462,18 @@ void GMainWindow::SyncMenuUISettings() {
|
|||
ui.action_Screen_Layout_Swap_Screens->setChecked(Settings::values.swap_screen);
|
||||
}
|
||||
|
||||
void GMainWindow::ChangeRoomState() {
|
||||
if (auto room = Network::GetRoom().lock()) {
|
||||
if (room->GetState() == Network::Room::State::Open) {
|
||||
ui.action_Start_Room->setDisabled(true);
|
||||
ui.action_Stop_Room->setEnabled(true);
|
||||
return;
|
||||
}
|
||||
ui.action_Start_Room->setEnabled(true);
|
||||
ui.action_Stop_Room->setDisabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef main
|
||||
#undef main
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue