mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-02-13 15:59:23 +01:00
Merge pull request #3588 from Aestek/feature/improve-netplay-dialog
Improve netplay UX
This commit is contained in:
commit
d7de39ebbe
@ -208,25 +208,6 @@ void TraversalClient::OnFailure(FailureReason reason)
|
|||||||
m_State = Failure;
|
m_State = Failure;
|
||||||
m_FailureReason = reason;
|
m_FailureReason = reason;
|
||||||
|
|
||||||
switch (reason)
|
|
||||||
{
|
|
||||||
case TraversalClient::BadHost:
|
|
||||||
PanicAlertT("Couldn't look up central server %s", m_Server.c_str());
|
|
||||||
break;
|
|
||||||
case TraversalClient::VersionTooOld:
|
|
||||||
PanicAlertT("Dolphin too old for traversal server");
|
|
||||||
break;
|
|
||||||
case TraversalClient::ServerForgotAboutUs:
|
|
||||||
PanicAlertT("Disconnected from traversal server");
|
|
||||||
break;
|
|
||||||
case TraversalClient::SocketSendError:
|
|
||||||
PanicAlertT("Socket error sending to traversal server");
|
|
||||||
break;
|
|
||||||
case TraversalClient::ResendTimeout:
|
|
||||||
PanicAlertT("Timeout connecting to traversal server");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_Client)
|
if (m_Client)
|
||||||
m_Client->OnTraversalStateChanged();
|
m_Client->OnTraversalStateChanged();
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,8 @@
|
|||||||
#include "Core/Movie.h"
|
#include "Core/Movie.h"
|
||||||
#include "Core/NetPlayClient.h"
|
#include "Core/NetPlayClient.h"
|
||||||
#include "InputCommon/GCAdapter.h"
|
#include "InputCommon/GCAdapter.h"
|
||||||
|
#include "VideoCommon/OnScreenDisplay.h"
|
||||||
|
#include "VideoCommon/VideoConfig.h"
|
||||||
|
|
||||||
static std::mutex crit_netplay_client;
|
static std::mutex crit_netplay_client;
|
||||||
static NetPlayClient* netplay_client = nullptr;
|
static NetPlayClient* netplay_client = nullptr;
|
||||||
@ -351,6 +353,7 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
|
|||||||
packet >> size;
|
packet >> size;
|
||||||
|
|
||||||
m_target_buffer_size = size;
|
m_target_buffer_size = size;
|
||||||
|
m_dialog->OnPadBufferChanged(size);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -428,17 +431,10 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case NP_MSG_STOP_GAME:
|
case NP_MSG_STOP_GAME:
|
||||||
{
|
|
||||||
m_dialog->OnMsgStopGame();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NP_MSG_DISABLE_GAME:
|
case NP_MSG_DISABLE_GAME:
|
||||||
{
|
{
|
||||||
PanicAlertT("Other client disconnected while game is running!! NetPlay is disabled. You must "
|
StopGame();
|
||||||
"manually stop the game.");
|
m_dialog->OnMsgStopGame();
|
||||||
m_is_running.store(false);
|
|
||||||
NetPlay_Disable();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -466,6 +462,7 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
|
|||||||
packet >> player.ping;
|
packet >> player.ping;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DisplayPlayersPing();
|
||||||
m_dialog->Update();
|
m_dialog->Update();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -476,18 +473,15 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
|
|||||||
u32 frame;
|
u32 frame;
|
||||||
packet >> pid_to_blame;
|
packet >> pid_to_blame;
|
||||||
packet >> frame;
|
packet >> frame;
|
||||||
const char* blame_str = "";
|
|
||||||
const char* blame_name = "";
|
std::string player = "??";
|
||||||
std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
|
std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
|
||||||
if (pid_to_blame != -1)
|
|
||||||
{
|
{
|
||||||
auto it = m_players.find(pid_to_blame);
|
auto it = m_players.find(pid_to_blame);
|
||||||
blame_str = " from player ";
|
if (it != m_players.end())
|
||||||
blame_name = it != m_players.end() ? it->second.name.c_str() : "??";
|
player = it->second.name;
|
||||||
}
|
}
|
||||||
|
m_dialog->OnDesync(frame, player);
|
||||||
m_dialog->AppendChat(StringFromFormat("/!\\ Possible desync detected%s%s on frame %u",
|
|
||||||
blame_str, blame_name, frame));
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -571,6 +565,24 @@ void NetPlayClient::Send(sf::Packet& packet)
|
|||||||
enet_peer_send(m_server, 0, epac);
|
enet_peer_send(m_server, 0, epac);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetPlayClient::DisplayPlayersPing()
|
||||||
|
{
|
||||||
|
if (!g_ActiveConfig.bShowNetPlayPing)
|
||||||
|
return;
|
||||||
|
|
||||||
|
OSD::AddTypedMessage(OSD::MessageType::NetPlayPing,
|
||||||
|
StringFromFormat("Ping: %u", GetPlayersMaxPing()), OSD::Duration::SHORT,
|
||||||
|
OSD::Color::CYAN);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 NetPlayClient::GetPlayersMaxPing() const
|
||||||
|
{
|
||||||
|
return std::max_element(
|
||||||
|
m_players.begin(), m_players.end(),
|
||||||
|
[](const auto& a, const auto& b) { return a.second.ping < b.second.ping; })
|
||||||
|
->second.ping;
|
||||||
|
}
|
||||||
|
|
||||||
void NetPlayClient::Disconnect()
|
void NetPlayClient::Disconnect()
|
||||||
{
|
{
|
||||||
ENetEvent netEvent;
|
ENetEvent netEvent;
|
||||||
@ -636,13 +648,11 @@ void NetPlayClient::ThreadFunc()
|
|||||||
enet_packet_destroy(netEvent.packet);
|
enet_packet_destroy(netEvent.packet);
|
||||||
break;
|
break;
|
||||||
case ENET_EVENT_TYPE_DISCONNECT:
|
case ENET_EVENT_TYPE_DISCONNECT:
|
||||||
m_is_running.store(false);
|
m_dialog->OnConnectionLost();
|
||||||
NetPlay_Disable();
|
|
||||||
m_dialog->AppendChat("< LOST CONNECTION TO SERVER >");
|
if (m_is_running.load())
|
||||||
PanicAlertT("Lost connection to server!");
|
StopGame();
|
||||||
m_do_loop.store(false);
|
|
||||||
|
|
||||||
netEvent.peer->data = nullptr;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -786,8 +796,6 @@ bool NetPlayClient::StartGame(const std::string& path)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_dialog->AppendChat(" -- STARTING GAME -- ");
|
|
||||||
|
|
||||||
m_timebase_frame = 0;
|
m_timebase_frame = 0;
|
||||||
|
|
||||||
m_is_running.store(true);
|
m_is_running.store(true);
|
||||||
@ -895,6 +903,7 @@ void NetPlayClient::OnTraversalStateChanged()
|
|||||||
m_traversal_client->m_State == TraversalClient::Failure)
|
m_traversal_client->m_State == TraversalClient::Failure)
|
||||||
{
|
{
|
||||||
Disconnect();
|
Disconnect();
|
||||||
|
m_dialog->OnTraversalError(m_traversal_client->m_FailureReason);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1080,8 +1089,6 @@ bool NetPlayClient::StopGame()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_dialog->AppendChat(" -- STOPPING GAME -- ");
|
|
||||||
|
|
||||||
m_is_running.store(false);
|
m_is_running.store(false);
|
||||||
NetPlay_Disable();
|
NetPlay_Disable();
|
||||||
|
|
||||||
|
@ -32,6 +32,10 @@ public:
|
|||||||
virtual void OnMsgChangeGame(const std::string& filename) = 0;
|
virtual void OnMsgChangeGame(const std::string& filename) = 0;
|
||||||
virtual void OnMsgStartGame() = 0;
|
virtual void OnMsgStartGame() = 0;
|
||||||
virtual void OnMsgStopGame() = 0;
|
virtual void OnMsgStopGame() = 0;
|
||||||
|
virtual void OnPadBufferChanged(u32 buffer) = 0;
|
||||||
|
virtual void OnDesync(u32 frame, const std::string& player) = 0;
|
||||||
|
virtual void OnConnectionLost() = 0;
|
||||||
|
virtual void OnTraversalError(int error) = 0;
|
||||||
virtual bool IsRecording() = 0;
|
virtual bool IsRecording() = 0;
|
||||||
virtual std::string FindGame(const std::string& game) = 0;
|
virtual std::string FindGame(const std::string& game) = 0;
|
||||||
virtual void ShowMD5Dialog(const std::string& file_identifier) = 0;
|
virtual void ShowMD5Dialog(const std::string& file_identifier) = 0;
|
||||||
@ -157,6 +161,8 @@ private:
|
|||||||
void Disconnect();
|
void Disconnect();
|
||||||
bool Connect();
|
bool Connect();
|
||||||
void ComputeMD5(const std::string& file_identifier);
|
void ComputeMD5(const std::string& file_identifier);
|
||||||
|
void DisplayPlayersPing();
|
||||||
|
u32 GetPlayersMaxPing() const;
|
||||||
|
|
||||||
bool m_is_connected = false;
|
bool m_is_connected = false;
|
||||||
ConnectionState m_connection_state = ConnectionState::Failure;
|
ConnectionState m_connection_state = ConnectionState::Failure;
|
||||||
|
@ -350,15 +350,13 @@ unsigned int NetPlayServer::OnDisconnect(Client& player)
|
|||||||
{
|
{
|
||||||
if (mapping == pid && pid != 1)
|
if (mapping == pid && pid != 1)
|
||||||
{
|
{
|
||||||
PanicAlertT("Client disconnect while game is running!! NetPlay is disabled. You must "
|
|
||||||
"manually stop the game.");
|
|
||||||
std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
|
std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
|
||||||
m_is_running = false;
|
m_is_running = false;
|
||||||
|
|
||||||
sf::Packet spac;
|
sf::Packet spac;
|
||||||
spac << (MessageId)NP_MSG_DISABLE_GAME;
|
spac << (MessageId)NP_MSG_DISABLE_GAME;
|
||||||
// this thread doesn't need players lock
|
// this thread doesn't need players lock
|
||||||
SendToClients(spac, 1);
|
SendToClients(spac, -1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -636,19 +634,15 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, Client& player)
|
|||||||
}))
|
}))
|
||||||
{
|
{
|
||||||
int pid_to_blame = -1;
|
int pid_to_blame = -1;
|
||||||
if (timebases.size() > 2)
|
for (auto pair : timebases)
|
||||||
{
|
{
|
||||||
for (auto pair : timebases)
|
if (std::all_of(timebases.begin(), timebases.end(), [&](std::pair<PlayerId, u64> other) {
|
||||||
|
return other.first == pair.first || other.second != pair.second;
|
||||||
|
}))
|
||||||
{
|
{
|
||||||
if (std::all_of(timebases.begin(), timebases.end(),
|
// we are the only outlier
|
||||||
[&](std::pair<PlayerId, u64> other) {
|
pid_to_blame = pair.first;
|
||||||
return other.first == pair.first || other.second != pair.second;
|
break;
|
||||||
}))
|
|
||||||
{
|
|
||||||
// we are the only outlier
|
|
||||||
pid_to_blame = pair.first;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -720,8 +714,8 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, Client& player)
|
|||||||
|
|
||||||
void NetPlayServer::OnTraversalStateChanged()
|
void NetPlayServer::OnTraversalStateChanged()
|
||||||
{
|
{
|
||||||
if (m_dialog)
|
if (m_dialog && m_traversal_client->m_State == TraversalClient::Failure)
|
||||||
m_dialog->Update();
|
m_dialog->OnTraversalError(m_traversal_client->m_FailureReason);
|
||||||
}
|
}
|
||||||
|
|
||||||
// called from ---GUI--- thread
|
// called from ---GUI--- thread
|
||||||
|
@ -43,10 +43,11 @@ NetPlaySetupFrame::NetPlaySetupFrame(wxWindow* const parent, const CGameListCtrl
|
|||||||
: wxFrame(parent, wxID_ANY, _("Dolphin NetPlay Setup")), m_game_list(game_list)
|
: wxFrame(parent, wxID_ANY, _("Dolphin NetPlay Setup")), m_game_list(game_list)
|
||||||
{
|
{
|
||||||
IniFile inifile;
|
IniFile inifile;
|
||||||
inifile.Load(File::GetUserPath(D_CONFIG_IDX) + "Dolphin.ini");
|
inifile.Load(File::GetUserPath(F_DOLPHINCONFIG_IDX));
|
||||||
IniFile::Section& netplay_section = *inifile.GetOrCreateSection("NetPlay");
|
IniFile::Section& netplay_section = *inifile.GetOrCreateSection("NetPlay");
|
||||||
|
|
||||||
wxPanel* const panel = new wxPanel(this);
|
wxPanel* const panel = new wxPanel(this);
|
||||||
|
panel->Bind(wxEVT_CHAR_HOOK, &NetPlaySetupFrame::OnKeyDown, this);
|
||||||
|
|
||||||
// top row
|
// top row
|
||||||
wxBoxSizer* const trav_szr = new wxBoxSizer(wxHORIZONTAL);
|
wxBoxSizer* const trav_szr = new wxBoxSizer(wxHORIZONTAL);
|
||||||
@ -57,7 +58,7 @@ NetPlaySetupFrame::NetPlaySetupFrame(wxWindow* const parent, const CGameListCtrl
|
|||||||
panel, wxID_ANY, _("Connection Type:"), wxDefaultPosition, wxSize(100, -1));
|
panel, wxID_ANY, _("Connection Type:"), wxDefaultPosition, wxSize(100, -1));
|
||||||
|
|
||||||
m_direct_traversal = new wxChoice(panel, wxID_ANY, wxDefaultPosition, wxSize(150, -1));
|
m_direct_traversal = new wxChoice(panel, wxID_ANY, wxDefaultPosition, wxSize(150, -1));
|
||||||
m_direct_traversal->Bind(wxEVT_CHOICE, &NetPlaySetupFrame::OnChoice, this);
|
m_direct_traversal->Bind(wxEVT_CHOICE, &NetPlaySetupFrame::OnDirectTraversalChoice, this);
|
||||||
m_direct_traversal->Append(_("Direct Connection"));
|
m_direct_traversal->Append(_("Direct Connection"));
|
||||||
m_direct_traversal->Append(_("Traversal Server"));
|
m_direct_traversal->Append(_("Traversal Server"));
|
||||||
|
|
||||||
@ -90,11 +91,11 @@ NetPlaySetupFrame::NetPlaySetupFrame(wxWindow* const parent, const CGameListCtrl
|
|||||||
netplay_section.Get("TraversalChoice", &travChoice, "direct");
|
netplay_section.Get("TraversalChoice", &travChoice, "direct");
|
||||||
if (travChoice == "traversal")
|
if (travChoice == "traversal")
|
||||||
{
|
{
|
||||||
m_direct_traversal->Select(1);
|
m_direct_traversal->Select(TRAVERSAL_CHOICE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_direct_traversal->Select(0);
|
m_direct_traversal->Select(DIRECT_CHOICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string centralPort;
|
std::string centralPort;
|
||||||
@ -106,19 +107,26 @@ NetPlaySetupFrame::NetPlaySetupFrame(wxWindow* const parent, const CGameListCtrl
|
|||||||
centralServer + ":" + centralPort);
|
centralServer + ":" + centralPort);
|
||||||
}
|
}
|
||||||
// tabs
|
// tabs
|
||||||
wxNotebook* const notebook = new wxNotebook(panel, wxID_ANY);
|
m_notebook = new wxNotebook(panel, wxID_ANY);
|
||||||
wxPanel* const connect_tab = new wxPanel(notebook, wxID_ANY);
|
wxPanel* const connect_tab = new wxPanel(m_notebook, wxID_ANY);
|
||||||
notebook->AddPage(connect_tab, _("Connect"));
|
m_notebook->AddPage(connect_tab, _("Connect"));
|
||||||
wxPanel* const host_tab = new wxPanel(notebook, wxID_ANY);
|
wxPanel* const host_tab = new wxPanel(m_notebook, wxID_ANY);
|
||||||
notebook->AddPage(host_tab, _("Host"));
|
m_notebook->AddPage(host_tab, _("Host"));
|
||||||
|
|
||||||
// connect tab
|
// connect tab
|
||||||
{
|
{
|
||||||
m_ip_lbl = new wxStaticText(connect_tab, wxID_ANY, _("Host Code :"));
|
m_ip_lbl = new wxStaticText(connect_tab, wxID_ANY, _("Host Code :"));
|
||||||
|
|
||||||
std::string address;
|
std::string last_hash_code;
|
||||||
netplay_section.Get("HostCode", &address, "00000000");
|
netplay_section.Get("HostCode", &last_hash_code, "00000000");
|
||||||
m_connect_ip_text = new wxTextCtrl(connect_tab, wxID_ANY, StrToWxStr(address));
|
std::string last_ip_address;
|
||||||
|
netplay_section.Get("Address", &last_ip_address, "127.0.0.1");
|
||||||
|
m_connect_ip_text = new wxTextCtrl(connect_tab, wxID_ANY, StrToWxStr(last_ip_address));
|
||||||
|
m_connect_hashcode_text = new wxTextCtrl(connect_tab, wxID_ANY, StrToWxStr(last_hash_code));
|
||||||
|
|
||||||
|
// Will be overridden by OnDirectTraversalChoice, but is necessary
|
||||||
|
// so that both inputs do not take up space
|
||||||
|
m_connect_hashcode_text->Hide();
|
||||||
|
|
||||||
m_client_port_lbl = new wxStaticText(connect_tab, wxID_ANY, _("Port :"));
|
m_client_port_lbl = new wxStaticText(connect_tab, wxID_ANY, _("Port :"));
|
||||||
|
|
||||||
@ -144,7 +152,8 @@ NetPlaySetupFrame::NetPlaySetupFrame(wxWindow* const parent, const CGameListCtrl
|
|||||||
|
|
||||||
top_szr->Add(m_ip_lbl, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 5);
|
top_szr->Add(m_ip_lbl, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 5);
|
||||||
top_szr->Add(m_connect_ip_text, 3);
|
top_szr->Add(m_connect_ip_text, 3);
|
||||||
top_szr->Add(m_client_port_lbl, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT | wxLEFT, 5);
|
top_szr->Add(m_connect_hashcode_text, 3);
|
||||||
|
top_szr->Add(m_client_port_lbl, 0, wxCENTER | wxRIGHT | wxLEFT, 5);
|
||||||
top_szr->Add(m_connect_port_text, 1);
|
top_szr->Add(m_connect_port_text, 1);
|
||||||
|
|
||||||
wxBoxSizer* const con_szr = new wxBoxSizer(wxVERTICAL);
|
wxBoxSizer* const con_szr = new wxBoxSizer(wxVERTICAL);
|
||||||
@ -190,6 +199,10 @@ NetPlaySetupFrame::NetPlaySetupFrame(wxWindow* const parent, const CGameListCtrl
|
|||||||
|
|
||||||
NetPlayDialog::FillWithGameNames(m_game_lbox, *game_list);
|
NetPlayDialog::FillWithGameNames(m_game_lbox, *game_list);
|
||||||
|
|
||||||
|
std::string last_hosted_game;
|
||||||
|
if (netplay_section.Get("SelectedHostGame", &last_hosted_game, ""))
|
||||||
|
m_game_lbox->SetStringSelection(last_hosted_game);
|
||||||
|
|
||||||
wxBoxSizer* const top_szr = new wxBoxSizer(wxHORIZONTAL);
|
wxBoxSizer* const top_szr = new wxBoxSizer(wxHORIZONTAL);
|
||||||
top_szr->Add(m_host_port_lbl, 0, wxCENTER | wxRIGHT, 5);
|
top_szr->Add(m_host_port_lbl, 0, wxCENTER | wxRIGHT, 5);
|
||||||
top_szr->Add(m_host_port_text, 0);
|
top_szr->Add(m_host_port_text, 0);
|
||||||
@ -221,11 +234,14 @@ NetPlaySetupFrame::NetPlaySetupFrame(wxWindow* const parent, const CGameListCtrl
|
|||||||
main_szr->Add(trav_szr, 0, wxALL | wxALIGN_LEFT, 5);
|
main_szr->Add(trav_szr, 0, wxALL | wxALIGN_LEFT, 5);
|
||||||
main_szr->Add(nick_szr, 0, wxALL | wxALIGN_LEFT, 5);
|
main_szr->Add(nick_szr, 0, wxALL | wxALIGN_LEFT, 5);
|
||||||
main_szr->Add(m_traversal_lbl, 0, wxALL | wxALIGN_LEFT, 5);
|
main_szr->Add(m_traversal_lbl, 0, wxALL | wxALIGN_LEFT, 5);
|
||||||
main_szr->Add(notebook, 1, wxLEFT | wxRIGHT | wxEXPAND, 5);
|
main_szr->Add(m_notebook, 1, wxLEFT | wxRIGHT | wxEXPAND, 5);
|
||||||
main_szr->Add(quit_btn, 0, wxALL | wxALIGN_RIGHT, 5);
|
main_szr->Add(quit_btn, 0, wxALL | wxALIGN_RIGHT, 5);
|
||||||
|
|
||||||
panel->SetSizerAndFit(main_szr);
|
panel->SetSizerAndFit(main_szr);
|
||||||
|
|
||||||
|
// Handle focus on tab changes
|
||||||
|
panel->Bind(wxEVT_NOTEBOOK_PAGE_CHANGED, &NetPlaySetupFrame::OnTabChanged, this);
|
||||||
|
|
||||||
// wxBoxSizer* const diag_szr = new wxBoxSizer(wxVERTICAL);
|
// wxBoxSizer* const diag_szr = new wxBoxSizer(wxVERTICAL);
|
||||||
// diag_szr->Add(panel, 1, wxEXPAND);
|
// diag_szr->Add(panel, 1, wxEXPAND);
|
||||||
// SetSizerAndFit(diag_szr);
|
// SetSizerAndFit(diag_szr);
|
||||||
@ -237,37 +253,35 @@ NetPlaySetupFrame::NetPlaySetupFrame(wxWindow* const parent, const CGameListCtrl
|
|||||||
|
|
||||||
// Needs to be done last or it set up the spacing on the page correctly
|
// Needs to be done last or it set up the spacing on the page correctly
|
||||||
wxCommandEvent ev;
|
wxCommandEvent ev;
|
||||||
OnChoice(ev);
|
OnDirectTraversalChoice(ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
NetPlaySetupFrame::~NetPlaySetupFrame()
|
NetPlaySetupFrame::~NetPlaySetupFrame()
|
||||||
{
|
{
|
||||||
IniFile inifile;
|
IniFile inifile;
|
||||||
const std::string dolphin_ini = File::GetUserPath(D_CONFIG_IDX) + "Dolphin.ini";
|
const std::string dolphin_ini = File::GetUserPath(F_DOLPHINCONFIG_IDX);
|
||||||
inifile.Load(dolphin_ini);
|
inifile.Load(dolphin_ini);
|
||||||
IniFile::Section& netplay_section = *inifile.GetOrCreateSection("NetPlay");
|
IniFile::Section& netplay_section = *inifile.GetOrCreateSection("NetPlay");
|
||||||
|
|
||||||
std::string travChoice = "traversal";
|
std::string travChoice;
|
||||||
if (m_direct_traversal->GetSelection() == 1)
|
switch (m_direct_traversal->GetSelection())
|
||||||
{
|
|
||||||
netplay_section.Set("TraversalChoice", travChoice);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
|
case TRAVERSAL_CHOICE:
|
||||||
|
travChoice = "traversal";
|
||||||
|
break;
|
||||||
|
case DIRECT_CHOICE:
|
||||||
travChoice = "direct";
|
travChoice = "direct";
|
||||||
netplay_section.Set("TraversalChoice", travChoice);
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
netplay_section.Set("TraversalChoice", travChoice);
|
||||||
netplay_section.Set("Nickname", WxStrToStr(m_nickname_text->GetValue()));
|
netplay_section.Set("Nickname", WxStrToStr(m_nickname_text->GetValue()));
|
||||||
|
|
||||||
if (m_direct_traversal->GetCurrentSelection() == 0)
|
if (m_direct_traversal->GetCurrentSelection() == DIRECT_CHOICE)
|
||||||
{
|
|
||||||
netplay_section.Set("Address", WxStrToStr(m_connect_ip_text->GetValue()));
|
netplay_section.Set("Address", WxStrToStr(m_connect_ip_text->GetValue()));
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
netplay_section.Set("HostCode", WxStrToStr(m_connect_hashcode_text->GetValue()));
|
||||||
netplay_section.Set("HostCode", WxStrToStr(m_connect_ip_text->GetValue()));
|
|
||||||
}
|
|
||||||
netplay_section.Set("ConnectPort", WxStrToStr(m_connect_port_text->GetValue()));
|
netplay_section.Set("ConnectPort", WxStrToStr(m_connect_port_text->GetValue()));
|
||||||
netplay_section.Set("HostPort", WxStrToStr(m_host_port_text->GetValue()));
|
netplay_section.Set("HostPort", WxStrToStr(m_host_port_text->GetValue()));
|
||||||
netplay_section.Set("ListenPort", m_traversal_listen_port_enabled->IsChecked() ?
|
netplay_section.Set("ListenPort", m_traversal_listen_port_enabled->IsChecked() ?
|
||||||
@ -283,21 +297,19 @@ void NetPlaySetupFrame::MakeNetPlayDiag(int port, const std::string& game, bool
|
|||||||
NetPlayDialog*& npd = NetPlayDialog::GetInstance();
|
NetPlayDialog*& npd = NetPlayDialog::GetInstance();
|
||||||
NetPlayClient*& netplay_client = NetPlayDialog::GetNetPlayClient();
|
NetPlayClient*& netplay_client = NetPlayDialog::GetNetPlayClient();
|
||||||
|
|
||||||
|
bool trav = !is_hosting && m_direct_traversal->GetCurrentSelection() == TRAVERSAL_CHOICE;
|
||||||
|
|
||||||
std::string ip;
|
std::string ip;
|
||||||
npd = new NetPlayDialog(m_parent, m_game_list, game, is_hosting);
|
npd = new NetPlayDialog(m_parent, m_game_list, game, is_hosting);
|
||||||
if (is_hosting)
|
if (is_hosting)
|
||||||
ip = "127.0.0.1";
|
ip = "127.0.0.1";
|
||||||
|
else if (trav)
|
||||||
|
ip = WxStrToStr(m_connect_hashcode_text->GetValue());
|
||||||
else
|
else
|
||||||
ip = WxStrToStr(m_connect_ip_text->GetValue());
|
ip = WxStrToStr(m_connect_ip_text->GetValue());
|
||||||
|
|
||||||
bool trav;
|
|
||||||
if (!is_hosting && m_direct_traversal->GetCurrentSelection() == 1)
|
|
||||||
trav = true;
|
|
||||||
else
|
|
||||||
trav = false;
|
|
||||||
|
|
||||||
IniFile inifile;
|
IniFile inifile;
|
||||||
inifile.Load(File::GetUserPath(D_CONFIG_IDX) + "Dolphin.ini");
|
inifile.Load(File::GetUserPath(F_DOLPHINCONFIG_IDX));
|
||||||
IniFile::Section& netplay_section = *inifile.GetOrCreateSection("NetPlay");
|
IniFile::Section& netplay_section = *inifile.GetOrCreateSection("NetPlay");
|
||||||
|
|
||||||
std::string centralPortString;
|
std::string centralPortString;
|
||||||
@ -323,6 +335,16 @@ void NetPlaySetupFrame::MakeNetPlayDiag(int port, const std::string& game, bool
|
|||||||
|
|
||||||
void NetPlaySetupFrame::OnHost(wxCommandEvent&)
|
void NetPlaySetupFrame::OnHost(wxCommandEvent&)
|
||||||
{
|
{
|
||||||
|
DoHost();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetPlaySetupFrame::DoHost()
|
||||||
|
{
|
||||||
|
IniFile ini_file;
|
||||||
|
const std::string dolphin_ini = File::GetUserPath(F_DOLPHINCONFIG_IDX);
|
||||||
|
ini_file.Load(dolphin_ini);
|
||||||
|
IniFile::Section& netplay_section = *ini_file.GetOrCreateSection("NetPlay");
|
||||||
|
|
||||||
NetPlayDialog*& npd = NetPlayDialog::GetInstance();
|
NetPlayDialog*& npd = NetPlayDialog::GetInstance();
|
||||||
NetPlayServer*& netplay_server = NetPlayDialog::GetNetPlayServer();
|
NetPlayServer*& netplay_server = NetPlayDialog::GetNetPlayServer();
|
||||||
|
|
||||||
@ -342,7 +364,7 @@ void NetPlaySetupFrame::OnHost(wxCommandEvent&)
|
|||||||
|
|
||||||
bool trav;
|
bool trav;
|
||||||
unsigned long listen_port = 0;
|
unsigned long listen_port = 0;
|
||||||
if (m_direct_traversal->GetCurrentSelection() == 1)
|
if (m_direct_traversal->GetCurrentSelection() == TRAVERSAL_CHOICE)
|
||||||
{
|
{
|
||||||
trav = true;
|
trav = true;
|
||||||
listen_port =
|
listen_port =
|
||||||
@ -354,10 +376,6 @@ void NetPlaySetupFrame::OnHost(wxCommandEvent&)
|
|||||||
m_host_port_text->GetValue().ToULong(&listen_port);
|
m_host_port_text->GetValue().ToULong(&listen_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
IniFile inifile;
|
|
||||||
inifile.Load(File::GetUserPath(D_CONFIG_IDX) + "Dolphin.ini");
|
|
||||||
IniFile::Section& netplay_section = *inifile.GetOrCreateSection("NetPlay");
|
|
||||||
|
|
||||||
std::string centralPortString;
|
std::string centralPortString;
|
||||||
GetTraversalPort(netplay_section, ¢ralPortString);
|
GetTraversalPort(netplay_section, ¢ralPortString);
|
||||||
unsigned long int centralPort;
|
unsigned long int centralPort;
|
||||||
@ -377,6 +395,9 @@ void NetPlaySetupFrame::OnHost(wxCommandEvent&)
|
|||||||
#endif
|
#endif
|
||||||
MakeNetPlayDiag(netplay_server->GetPort(), game, true);
|
MakeNetPlayDiag(netplay_server->GetPort(), game, true);
|
||||||
netplay_server->SetNetPlayUI(NetPlayDialog::GetInstance());
|
netplay_server->SetNetPlayUI(NetPlayDialog::GetInstance());
|
||||||
|
|
||||||
|
netplay_section.Set("SelectedHostGame", game);
|
||||||
|
ini_file.Save(dolphin_ini);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -390,6 +411,11 @@ void NetPlaySetupFrame::OnHost(wxCommandEvent&)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void NetPlaySetupFrame::OnJoin(wxCommandEvent&)
|
void NetPlaySetupFrame::OnJoin(wxCommandEvent&)
|
||||||
|
{
|
||||||
|
DoJoin();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetPlaySetupFrame::DoJoin()
|
||||||
{
|
{
|
||||||
NetPlayDialog*& npd = NetPlayDialog::GetInstance();
|
NetPlayDialog*& npd = NetPlayDialog::GetInstance();
|
||||||
if (npd)
|
if (npd)
|
||||||
@ -406,7 +432,7 @@ void NetPlaySetupFrame::OnJoin(wxCommandEvent&)
|
|||||||
void NetPlaySetupFrame::OnResetTraversal(wxCommandEvent& event)
|
void NetPlaySetupFrame::OnResetTraversal(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
IniFile inifile;
|
IniFile inifile;
|
||||||
const std::string dolphin_ini = File::GetUserPath(D_CONFIG_IDX) + "Dolphin.ini";
|
const std::string dolphin_ini = File::GetUserPath(F_DOLPHINCONFIG_IDX);
|
||||||
inifile.Load(dolphin_ini);
|
inifile.Load(dolphin_ini);
|
||||||
IniFile::Section& netplay_section = *inifile.GetOrCreateSection("NetPlay");
|
IniFile::Section& netplay_section = *inifile.GetOrCreateSection("NetPlay");
|
||||||
netplay_section.Set("TraversalServer", (std::string) "stun.dolphin-emu.org");
|
netplay_section.Set("TraversalServer", (std::string) "stun.dolphin-emu.org");
|
||||||
@ -421,26 +447,23 @@ void NetPlaySetupFrame::OnTraversalListenPortChanged(wxCommandEvent& event)
|
|||||||
m_traversal_listen_port->Enable(m_traversal_listen_port_enabled->IsChecked());
|
m_traversal_listen_port->Enable(m_traversal_listen_port_enabled->IsChecked());
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetPlaySetupFrame::OnChoice(wxCommandEvent& event)
|
void NetPlaySetupFrame::OnDirectTraversalChoice(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
int sel = m_direct_traversal->GetSelection();
|
int sel = m_direct_traversal->GetSelection();
|
||||||
IniFile inifile;
|
IniFile inifile;
|
||||||
inifile.Load(File::GetUserPath(D_CONFIG_IDX) + "Dolphin.ini");
|
inifile.Load(File::GetUserPath(F_DOLPHINCONFIG_IDX));
|
||||||
IniFile::Section& netplay_section = *inifile.GetOrCreateSection("NetPlay");
|
IniFile::Section& netplay_section = *inifile.GetOrCreateSection("NetPlay");
|
||||||
|
|
||||||
if (sel == 1)
|
if (sel == TRAVERSAL_CHOICE)
|
||||||
{
|
{
|
||||||
m_traversal_lbl->Show();
|
m_traversal_lbl->Show();
|
||||||
m_trav_reset_btn->Show();
|
m_trav_reset_btn->Show();
|
||||||
|
m_connect_hashcode_text->Show();
|
||||||
|
m_connect_ip_text->Hide();
|
||||||
// Traversal
|
// Traversal
|
||||||
// client tab
|
// client tab
|
||||||
{
|
{
|
||||||
m_ip_lbl->SetLabelText("Host Code: ");
|
m_ip_lbl->SetLabelText("Host Code: ");
|
||||||
|
|
||||||
std::string address;
|
|
||||||
netplay_section.Get("HostCode", &address, "00000000");
|
|
||||||
m_connect_ip_text->SetLabelText(address);
|
|
||||||
|
|
||||||
m_client_port_lbl->Hide();
|
m_client_port_lbl->Hide();
|
||||||
m_connect_port_text->Hide();
|
m_connect_port_text->Hide();
|
||||||
}
|
}
|
||||||
@ -460,6 +483,8 @@ void NetPlaySetupFrame::OnChoice(wxCommandEvent& event)
|
|||||||
{
|
{
|
||||||
m_traversal_lbl->Hide();
|
m_traversal_lbl->Hide();
|
||||||
m_trav_reset_btn->Hide();
|
m_trav_reset_btn->Hide();
|
||||||
|
m_connect_hashcode_text->Hide();
|
||||||
|
m_connect_ip_text->Show();
|
||||||
// Direct
|
// Direct
|
||||||
// Client tab
|
// Client tab
|
||||||
{
|
{
|
||||||
@ -482,6 +507,65 @@ void NetPlaySetupFrame::OnChoice(wxCommandEvent& event)
|
|||||||
m_upnp_chk->Show();
|
m_upnp_chk->Show();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
m_connect_ip_text->GetParent()->Layout();
|
||||||
|
DispatchFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetPlaySetupFrame::OnKeyDown(wxKeyEvent& event)
|
||||||
|
{
|
||||||
|
// Let the event propagate
|
||||||
|
event.Skip();
|
||||||
|
|
||||||
|
if (event.GetKeyCode() != wxKeyCode::WXK_RETURN)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int current_tab = m_notebook->GetSelection();
|
||||||
|
|
||||||
|
switch (current_tab)
|
||||||
|
{
|
||||||
|
case CONNECT_TAB:
|
||||||
|
DoJoin();
|
||||||
|
break;
|
||||||
|
case HOST_TAB:
|
||||||
|
DoHost();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetPlaySetupFrame::OnTabChanged(wxCommandEvent& event)
|
||||||
|
{
|
||||||
|
// Propagate event
|
||||||
|
event.Skip();
|
||||||
|
|
||||||
|
// Delaying action so the first tab order element doesn't override the focus
|
||||||
|
m_notebook->Bind(wxEVT_IDLE, &NetPlaySetupFrame::OnAfterTabChange, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetPlaySetupFrame::OnAfterTabChange(wxIdleEvent&)
|
||||||
|
{
|
||||||
|
// Unbinding so we don't hog the idle event
|
||||||
|
m_notebook->Unbind(wxEVT_IDLE, &NetPlaySetupFrame::OnAfterTabChange, this);
|
||||||
|
|
||||||
|
DispatchFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetPlaySetupFrame::DispatchFocus()
|
||||||
|
{
|
||||||
|
int current_tab = m_notebook->GetSelection();
|
||||||
|
|
||||||
|
switch (current_tab)
|
||||||
|
{
|
||||||
|
case CONNECT_TAB:
|
||||||
|
if (m_direct_traversal->GetCurrentSelection() == TRAVERSAL_CHOICE)
|
||||||
|
m_connect_hashcode_text->SetFocus();
|
||||||
|
else
|
||||||
|
m_connect_ip_text->SetFocus();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HOST_TAB:
|
||||||
|
m_game_lbox->SetFocus();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetPlaySetupFrame::OnQuit(wxCommandEvent&)
|
void NetPlaySetupFrame::OnQuit(wxCommandEvent&)
|
||||||
|
@ -23,12 +23,24 @@ public:
|
|||||||
~NetPlaySetupFrame();
|
~NetPlaySetupFrame();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static constexpr int CONNECT_TAB = 0;
|
||||||
|
static constexpr int HOST_TAB = 1;
|
||||||
|
|
||||||
|
static constexpr int DIRECT_CHOICE = 0;
|
||||||
|
static constexpr int TRAVERSAL_CHOICE = 1;
|
||||||
|
|
||||||
void OnJoin(wxCommandEvent& event);
|
void OnJoin(wxCommandEvent& event);
|
||||||
void OnHost(wxCommandEvent& event);
|
void OnHost(wxCommandEvent& event);
|
||||||
|
void DoJoin();
|
||||||
|
void DoHost();
|
||||||
void OnQuit(wxCommandEvent& event);
|
void OnQuit(wxCommandEvent& event);
|
||||||
void OnChoice(wxCommandEvent& event);
|
void OnDirectTraversalChoice(wxCommandEvent& event);
|
||||||
void OnResetTraversal(wxCommandEvent& event);
|
void OnResetTraversal(wxCommandEvent& event);
|
||||||
void OnTraversalListenPortChanged(wxCommandEvent& event);
|
void OnTraversalListenPortChanged(wxCommandEvent& event);
|
||||||
|
void OnKeyDown(wxKeyEvent& event);
|
||||||
|
void OnTabChanged(wxCommandEvent& event);
|
||||||
|
void OnAfterTabChange(wxIdleEvent& event);
|
||||||
|
void DispatchFocus();
|
||||||
|
|
||||||
void MakeNetPlayDiag(int port, const std::string& game, bool is_hosting);
|
void MakeNetPlayDiag(int port, const std::string& game, bool is_hosting);
|
||||||
|
|
||||||
@ -39,11 +51,13 @@ private:
|
|||||||
wxTextCtrl* m_host_port_text;
|
wxTextCtrl* m_host_port_text;
|
||||||
wxTextCtrl* m_connect_port_text;
|
wxTextCtrl* m_connect_port_text;
|
||||||
wxTextCtrl* m_connect_ip_text;
|
wxTextCtrl* m_connect_ip_text;
|
||||||
|
wxTextCtrl* m_connect_hashcode_text;
|
||||||
wxChoice* m_direct_traversal;
|
wxChoice* m_direct_traversal;
|
||||||
wxStaticText* m_traversal_lbl;
|
wxStaticText* m_traversal_lbl;
|
||||||
wxButton* m_trav_reset_btn;
|
wxButton* m_trav_reset_btn;
|
||||||
wxCheckBox* m_traversal_listen_port_enabled;
|
wxCheckBox* m_traversal_listen_port_enabled;
|
||||||
wxSpinCtrl* m_traversal_listen_port;
|
wxSpinCtrl* m_traversal_listen_port;
|
||||||
|
wxNotebook* m_notebook;
|
||||||
|
|
||||||
wxListBox* m_game_lbox;
|
wxListBox* m_game_lbox;
|
||||||
#ifdef USE_UPNP
|
#ifdef USE_UPNP
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include <wx/checkbox.h>
|
#include <wx/checkbox.h>
|
||||||
#include <wx/choice.h>
|
#include <wx/choice.h>
|
||||||
#include <wx/clipbrd.h>
|
#include <wx/clipbrd.h>
|
||||||
|
#include <wx/colour.h>
|
||||||
#include <wx/dialog.h>
|
#include <wx/dialog.h>
|
||||||
#include <wx/frame.h>
|
#include <wx/frame.h>
|
||||||
#include <wx/listbox.h>
|
#include <wx/listbox.h>
|
||||||
@ -48,29 +49,13 @@
|
|||||||
#include "DolphinWX/WxUtils.h"
|
#include "DolphinWX/WxUtils.h"
|
||||||
#include "MD5Dialog.h"
|
#include "MD5Dialog.h"
|
||||||
|
|
||||||
|
#include "VideoCommon/OnScreenDisplay.h"
|
||||||
|
#include "VideoCommon/VideoConfig.h"
|
||||||
|
|
||||||
NetPlayServer* NetPlayDialog::netplay_server = nullptr;
|
NetPlayServer* NetPlayDialog::netplay_server = nullptr;
|
||||||
NetPlayClient* NetPlayDialog::netplay_client = nullptr;
|
NetPlayClient* NetPlayDialog::netplay_client = nullptr;
|
||||||
NetPlayDialog* NetPlayDialog::npd = nullptr;
|
NetPlayDialog* NetPlayDialog::npd = nullptr;
|
||||||
|
|
||||||
static wxString FailureReasonStringForHostLabel(int reason)
|
|
||||||
{
|
|
||||||
switch (reason)
|
|
||||||
{
|
|
||||||
case TraversalClient::BadHost:
|
|
||||||
return _("(Error: Bad host)");
|
|
||||||
case TraversalClient::VersionTooOld:
|
|
||||||
return _("(Error: Dolphin too old)");
|
|
||||||
case TraversalClient::ServerForgotAboutUs:
|
|
||||||
return _("(Error: Disconnected)");
|
|
||||||
case TraversalClient::SocketSendError:
|
|
||||||
return _("(Error: Socket)");
|
|
||||||
case TraversalClient::ResendTimeout:
|
|
||||||
return _("(Error: Timeout)");
|
|
||||||
default:
|
|
||||||
return _("(Error: Unknown)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string BuildGameName(const GameListItem& game)
|
static std::string BuildGameName(const GameListItem& game)
|
||||||
{
|
{
|
||||||
// Lang needs to be consistent
|
// Lang needs to be consistent
|
||||||
@ -280,13 +265,13 @@ NetPlayDialog::~NetPlayDialog()
|
|||||||
|
|
||||||
void NetPlayDialog::OnChat(wxCommandEvent&)
|
void NetPlayDialog::OnChat(wxCommandEvent&)
|
||||||
{
|
{
|
||||||
wxString text = m_chat_msg_text->GetValue();
|
std::string text = WxStrToStr(m_chat_msg_text->GetValue());
|
||||||
|
|
||||||
if (!text.empty())
|
if (!text.empty())
|
||||||
{
|
{
|
||||||
netplay_client->SendChatMessage(WxStrToStr(text));
|
netplay_client->SendChatMessage(text);
|
||||||
m_chat_text->AppendText(text.Prepend(" >> ").Append('\n'));
|
|
||||||
m_chat_msg_text->Clear();
|
m_chat_msg_text->Clear();
|
||||||
|
AddChatMessage(ChatMessageType::UserOut, text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,11 +391,46 @@ void NetPlayDialog::OnAdjustBuffer(wxCommandEvent& event)
|
|||||||
{
|
{
|
||||||
const int val = ((wxSpinCtrl*)event.GetEventObject())->GetValue();
|
const int val = ((wxSpinCtrl*)event.GetEventObject())->GetValue();
|
||||||
netplay_server->AdjustPadBufferSize(val);
|
netplay_server->AdjustPadBufferSize(val);
|
||||||
|
}
|
||||||
|
|
||||||
std::ostringstream ss;
|
void NetPlayDialog::OnPadBufferChanged(u32 buffer)
|
||||||
ss << "< Pad Buffer: " << val << " >";
|
{
|
||||||
netplay_client->SendChatMessage(ss.str());
|
m_pad_buffer = buffer;
|
||||||
m_chat_text->AppendText(StrToWxStr(ss.str()).Append('\n'));
|
wxThreadEvent evt(wxEVT_THREAD, NP_GUI_EVT_PAD_BUFFER_CHANGE);
|
||||||
|
GetEventHandler()->AddPendingEvent(evt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetPlayDialog::OnDesync(u32 frame, const std::string& player)
|
||||||
|
{
|
||||||
|
m_desync_frame = frame;
|
||||||
|
m_desync_player = player;
|
||||||
|
wxThreadEvent evt(wxEVT_THREAD, NP_GUI_EVT_DESYNC);
|
||||||
|
GetEventHandler()->AddPendingEvent(evt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetPlayDialog::OnConnectionLost()
|
||||||
|
{
|
||||||
|
wxThreadEvent evt(wxEVT_THREAD, NP_GUI_EVT_CONNECTION_LOST);
|
||||||
|
GetEventHandler()->AddPendingEvent(evt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetPlayDialog::OnTraversalError(int error)
|
||||||
|
{
|
||||||
|
switch (error)
|
||||||
|
{
|
||||||
|
case TraversalClient::BadHost:
|
||||||
|
PanicAlertT("Couldn't look up central server");
|
||||||
|
break;
|
||||||
|
case TraversalClient::VersionTooOld:
|
||||||
|
PanicAlertT("Dolphin is too old for traversal server");
|
||||||
|
break;
|
||||||
|
case TraversalClient::ServerForgotAboutUs:
|
||||||
|
case TraversalClient::SocketSendError:
|
||||||
|
case TraversalClient::ResendTimeout:
|
||||||
|
wxThreadEvent evt(wxEVT_THREAD, NP_GUI_EVT_TRAVERSAL_CONNECTION_ERROR);
|
||||||
|
GetEventHandler()->AddPendingEvent(evt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetPlayDialog::OnQuit(wxCommandEvent&)
|
void NetPlayDialog::OnQuit(wxCommandEvent&)
|
||||||
@ -477,17 +497,16 @@ void NetPlayDialog::OnThread(wxThreadEvent& event)
|
|||||||
case NP_GUI_EVT_START_GAME:
|
case NP_GUI_EVT_START_GAME:
|
||||||
// client start game :/
|
// client start game :/
|
||||||
{
|
{
|
||||||
std::string game = FindCurrentGame();
|
netplay_client->StartGame(FindCurrentGame());
|
||||||
if (game.empty())
|
std::string msg = "Starting game";
|
||||||
WxUtils::ShowErrorDialog(_("Game not found!"));
|
AddChatMessage(ChatMessageType::Info, msg);
|
||||||
else
|
|
||||||
netplay_client->StartGame(game);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NP_GUI_EVT_STOP_GAME:
|
case NP_GUI_EVT_STOP_GAME:
|
||||||
// client stop game
|
// client stop game
|
||||||
{
|
{
|
||||||
netplay_client->StopGame();
|
std::string msg = "Stopping game";
|
||||||
|
AddChatMessage(ChatMessageType::Info, msg);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NP_GUI_EVT_DISPLAY_MD5_DIALOG:
|
case NP_GUI_EVT_DISPLAY_MD5_DIALOG:
|
||||||
@ -515,6 +534,42 @@ void NetPlayDialog::OnThread(wxThreadEvent& event)
|
|||||||
m_MD5_dialog->SetResult(payload.first, payload.second);
|
m_MD5_dialog->SetResult(payload.first, payload.second);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case NP_GUI_EVT_PAD_BUFFER_CHANGE:
|
||||||
|
{
|
||||||
|
std::string msg = StringFromFormat("Pad buffer: %d", m_pad_buffer);
|
||||||
|
|
||||||
|
if (g_ActiveConfig.bShowNetPlayMessages)
|
||||||
|
{
|
||||||
|
OSD::AddTypedMessage(OSD::MessageType::NetPlayBuffer, msg, OSD::Duration::NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
AddChatMessage(ChatMessageType::Info, msg);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NP_GUI_EVT_DESYNC:
|
||||||
|
{
|
||||||
|
std::string msg = "Possible desync detected from player " + m_desync_player + " on frame " +
|
||||||
|
std::to_string(m_desync_frame);
|
||||||
|
|
||||||
|
AddChatMessage(ChatMessageType::Error, msg);
|
||||||
|
|
||||||
|
if (g_ActiveConfig.bShowNetPlayMessages)
|
||||||
|
{
|
||||||
|
OSD::AddMessage(msg, OSD::Duration::VERY_LONG, OSD::Color::RED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NP_GUI_EVT_CONNECTION_LOST:
|
||||||
|
{
|
||||||
|
std::string msg = "Lost connection to server";
|
||||||
|
AddChatMessage(ChatMessageType::Error, msg);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NP_GUI_EVT_TRAVERSAL_CONNECTION_ERROR:
|
||||||
|
{
|
||||||
|
std::string msg = "Traversal server connection error";
|
||||||
|
AddChatMessage(ChatMessageType::Error, msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// chat messages
|
// chat messages
|
||||||
@ -522,8 +577,12 @@ void NetPlayDialog::OnThread(wxThreadEvent& event)
|
|||||||
{
|
{
|
||||||
std::string s;
|
std::string s;
|
||||||
chat_msgs.Pop(s);
|
chat_msgs.Pop(s);
|
||||||
// PanicAlert("message: %s", s.c_str());
|
AddChatMessage(ChatMessageType::UserIn, s);
|
||||||
m_chat_text->AppendText(StrToWxStr(s).Append('\n'));
|
|
||||||
|
if (g_ActiveConfig.bShowNetPlayMessages)
|
||||||
|
{
|
||||||
|
OSD::AddMessage(s, OSD::Duration::NORMAL, OSD::Color::GREEN);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -690,7 +749,7 @@ void NetPlayDialog::UpdateHostLabel()
|
|||||||
break;
|
break;
|
||||||
case TraversalClient::Failure:
|
case TraversalClient::Failure:
|
||||||
m_host_label->SetForegroundColour(*wxBLACK);
|
m_host_label->SetForegroundColour(*wxBLACK);
|
||||||
m_host_label->SetLabel(FailureReasonStringForHostLabel(g_TraversalClient->m_FailureReason));
|
m_host_label->SetLabel("...");
|
||||||
m_host_copy_btn->SetLabel(_("Retry"));
|
m_host_copy_btn->SetLabel(_("Retry"));
|
||||||
m_host_copy_btn->Enable();
|
m_host_copy_btn->Enable();
|
||||||
m_host_copy_btn_is_retry = true;
|
m_host_copy_btn_is_retry = true;
|
||||||
@ -724,3 +783,36 @@ void NetPlayDialog::UpdateHostLabel()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetPlayDialog::AddChatMessage(ChatMessageType type, const std::string& msg)
|
||||||
|
{
|
||||||
|
wxColour colour = *wxBLACK;
|
||||||
|
std::string printed_msg = msg;
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case ChatMessageType::Info:
|
||||||
|
colour = wxColour(0, 150, 150); // cyan
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ChatMessageType::Error:
|
||||||
|
colour = *wxRED;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ChatMessageType::UserIn:
|
||||||
|
colour = wxColour(0, 150, 0); // green
|
||||||
|
printed_msg = "▶ " + msg;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ChatMessageType::UserOut:
|
||||||
|
colour = wxColour(100, 100, 100); // grey
|
||||||
|
printed_msg = "◀ " + msg;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == ChatMessageType::Info || type == ChatMessageType::Error)
|
||||||
|
printed_msg = "― " + msg + " ―";
|
||||||
|
|
||||||
|
m_chat_text->SetDefaultStyle(wxTextAttr(colour));
|
||||||
|
m_chat_text->AppendText(StrToWxStr(printed_msg + "\n"));
|
||||||
|
}
|
||||||
|
@ -31,6 +31,10 @@ enum
|
|||||||
NP_GUI_EVT_DISPLAY_MD5_DIALOG,
|
NP_GUI_EVT_DISPLAY_MD5_DIALOG,
|
||||||
NP_GUI_EVT_MD5_PROGRESS,
|
NP_GUI_EVT_MD5_PROGRESS,
|
||||||
NP_GUI_EVT_MD5_RESULT,
|
NP_GUI_EVT_MD5_RESULT,
|
||||||
|
NP_GUI_EVT_PAD_BUFFER_CHANGE,
|
||||||
|
NP_GUI_EVT_DESYNC,
|
||||||
|
NP_GUI_EVT_CONNECTION_LOST,
|
||||||
|
NP_GUI_EVT_TRAVERSAL_CONNECTION_ERROR,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
@ -38,6 +42,18 @@ enum
|
|||||||
INITIAL_PAD_BUFFER_SIZE = 5
|
INITIAL_PAD_BUFFER_SIZE = 5
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class ChatMessageType
|
||||||
|
{
|
||||||
|
// Info messages logged to chat
|
||||||
|
Info,
|
||||||
|
// Error messages logged to chat
|
||||||
|
Error,
|
||||||
|
// Incoming user chat messages
|
||||||
|
UserIn,
|
||||||
|
// Outcoming user chat messages
|
||||||
|
UserOut,
|
||||||
|
};
|
||||||
|
|
||||||
// IDs are UI-dependent here
|
// IDs are UI-dependent here
|
||||||
enum class MD5Target
|
enum class MD5Target
|
||||||
{
|
{
|
||||||
@ -72,6 +88,10 @@ public:
|
|||||||
void OnMsgChangeGame(const std::string& filename) override;
|
void OnMsgChangeGame(const std::string& filename) override;
|
||||||
void OnMsgStartGame() override;
|
void OnMsgStartGame() override;
|
||||||
void OnMsgStopGame() override;
|
void OnMsgStopGame() override;
|
||||||
|
void OnPadBufferChanged(u32 buffer) override;
|
||||||
|
void OnDesync(u32 frame, const std::string& player) override;
|
||||||
|
void OnConnectionLost() override;
|
||||||
|
void OnTraversalError(int error) override;
|
||||||
|
|
||||||
static NetPlayDialog*& GetInstance() { return npd; }
|
static NetPlayDialog*& GetInstance() { return npd; }
|
||||||
static NetPlayClient*& GetNetPlayClient() { return netplay_client; }
|
static NetPlayClient*& GetNetPlayClient() { return netplay_client; }
|
||||||
@ -92,7 +112,8 @@ private:
|
|||||||
void OnPlayerSelect(wxCommandEvent& event);
|
void OnPlayerSelect(wxCommandEvent& event);
|
||||||
void GetNetSettings(NetSettings& settings);
|
void GetNetSettings(NetSettings& settings);
|
||||||
std::string FindCurrentGame();
|
std::string FindCurrentGame();
|
||||||
std::string FindGame(const std::string& game) override;
|
std::string FindGame(const std::string& game);
|
||||||
|
void AddChatMessage(ChatMessageType type, const std::string& msg);
|
||||||
|
|
||||||
void OnCopyIP(wxCommandEvent&);
|
void OnCopyIP(wxCommandEvent&);
|
||||||
void OnChoice(wxCommandEvent& event);
|
void OnChoice(wxCommandEvent& event);
|
||||||
@ -116,6 +137,9 @@ private:
|
|||||||
MD5Dialog* m_MD5_dialog = nullptr;
|
MD5Dialog* m_MD5_dialog = nullptr;
|
||||||
bool m_host_copy_btn_is_retry;
|
bool m_host_copy_btn_is_retry;
|
||||||
bool m_is_hosting;
|
bool m_is_hosting;
|
||||||
|
u32 m_pad_buffer;
|
||||||
|
u32 m_desync_frame;
|
||||||
|
std::string m_desync_player;
|
||||||
|
|
||||||
std::vector<int> m_playerids;
|
std::vector<int> m_playerids;
|
||||||
|
|
||||||
|
@ -201,13 +201,20 @@ static wxString disable_fog_desc =
|
|||||||
"detail.\nDisabling fog will break some games which rely on proper fog "
|
"detail.\nDisabling fog will break some games which rely on proper fog "
|
||||||
"emulation.\n\nIf unsure, leave this unchecked.");
|
"emulation.\n\nIf unsure, leave this unchecked.");
|
||||||
static wxString show_fps_desc =
|
static wxString show_fps_desc =
|
||||||
wxTRANSLATE("Show the number of frames rendered per second as a measure of emulation "
|
wxTRANSLATE("Show the number of frames rendered per second as a measure of "
|
||||||
"speed.\n\nIf unsure, leave this unchecked.");
|
"emulation speed.\n\nIf unsure, leave this unchecked.");
|
||||||
static wxString log_render_time_to_file_desc = wxTRANSLATE(
|
static wxString show_netplay_ping_desc =
|
||||||
"Log the render time of every frame to User/Logs/render_time.txt. Use this feature when you "
|
wxTRANSLATE("Show the players' maximum Ping while playing on "
|
||||||
"want to measure the performance of Dolphin.\n\nIf unsure, leave this unchecked.");
|
"NetPlay.\n\nIf unsure, leave this unchecked.");
|
||||||
|
static wxString log_render_time_to_file_desc =
|
||||||
|
wxTRANSLATE("Log the render time of every frame to User/Logs/render_time.txt. Use this "
|
||||||
|
"feature when you want to measure the performance of Dolphin.\n\nIf "
|
||||||
|
"unsure, leave this unchecked.");
|
||||||
static wxString show_stats_desc =
|
static wxString show_stats_desc =
|
||||||
wxTRANSLATE("Show various rendering statistics.\n\nIf unsure, leave this unchecked.");
|
wxTRANSLATE("Show various rendering statistics.\n\nIf unsure, leave this unchecked.");
|
||||||
|
static wxString show_netplay_messages_desc =
|
||||||
|
wxTRANSLATE("When playing on NetPlay, show chat messages, buffer changes and "
|
||||||
|
"desync alerts.\n\nIf unsure, leave this unchecked.");
|
||||||
static wxString texfmt_desc =
|
static wxString texfmt_desc =
|
||||||
wxTRANSLATE("Modify textures to show the format they're encoded in. Needs an emulation reset "
|
wxTRANSLATE("Modify textures to show the format they're encoded in. Needs an emulation reset "
|
||||||
"in most cases.\n\nIf unsure, leave this unchecked.");
|
"in most cases.\n\nIf unsure, leave this unchecked.");
|
||||||
@ -442,12 +449,18 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
|
|||||||
{
|
{
|
||||||
szr_other->Add(CreateCheckBox(page_general, _("Show FPS"), wxGetTranslation(show_fps_desc),
|
szr_other->Add(CreateCheckBox(page_general, _("Show FPS"), wxGetTranslation(show_fps_desc),
|
||||||
vconfig.bShowFPS));
|
vconfig.bShowFPS));
|
||||||
|
szr_other->Add(CreateCheckBox(page_general, _("Show NetPlay Ping"),
|
||||||
|
wxGetTranslation(show_netplay_ping_desc),
|
||||||
|
vconfig.bShowNetPlayPing));
|
||||||
szr_other->Add(CreateCheckBox(page_general, _("Log Render Time to File"),
|
szr_other->Add(CreateCheckBox(page_general, _("Log Render Time to File"),
|
||||||
wxGetTranslation(log_render_time_to_file_desc),
|
wxGetTranslation(log_render_time_to_file_desc),
|
||||||
vconfig.bLogRenderTimeToFile));
|
vconfig.bLogRenderTimeToFile));
|
||||||
szr_other->Add(CreateCheckBox(page_general, _("Auto adjust Window Size"),
|
szr_other->Add(CreateCheckBox(page_general, _("Auto adjust Window Size"),
|
||||||
wxGetTranslation(auto_window_size_desc),
|
wxGetTranslation(auto_window_size_desc),
|
||||||
SConfig::GetInstance().bRenderWindowAutoSize));
|
SConfig::GetInstance().bRenderWindowAutoSize));
|
||||||
|
szr_other->Add(CreateCheckBox(page_general, _("Show NetPlay Messages"),
|
||||||
|
wxGetTranslation(show_netplay_messages_desc),
|
||||||
|
vconfig.bShowNetPlayMessages));
|
||||||
szr_other->Add(CreateCheckBox(page_general, _("Keep Window on Top"),
|
szr_other->Add(CreateCheckBox(page_general, _("Keep Window on Top"),
|
||||||
wxGetTranslation(keep_window_on_top_desc),
|
wxGetTranslation(keep_window_on_top_desc),
|
||||||
SConfig::GetInstance().bKeepWindowOnTop));
|
SConfig::GetInstance().bKeepWindowOnTop));
|
||||||
|
@ -17,21 +17,30 @@
|
|||||||
|
|
||||||
namespace OSD
|
namespace OSD
|
||||||
{
|
{
|
||||||
struct Message
|
|
||||||
{
|
|
||||||
Message() {}
|
|
||||||
Message(const std::string& s, u32 ts, u32 rgba) : m_str(s), m_timestamp(ts), m_rgba(rgba) {}
|
|
||||||
std::string m_str;
|
|
||||||
u32 m_timestamp;
|
|
||||||
u32 m_rgba;
|
|
||||||
};
|
|
||||||
|
|
||||||
static std::multimap<CallbackType, Callback> s_callbacks;
|
static std::multimap<CallbackType, Callback> s_callbacks;
|
||||||
static std::list<Message> s_msgList;
|
static std::multimap<MessageType, Message> s_messages;
|
||||||
|
static std::mutex s_messages_mutex;
|
||||||
|
|
||||||
void AddMessage(const std::string& str, u32 ms, u32 rgba)
|
void AddTypedMessage(MessageType type, const std::string& message, u32 ms, u32 rgba)
|
||||||
{
|
{
|
||||||
s_msgList.emplace_back(str, Common::Timer::GetTimeMs() + ms, rgba);
|
std::lock_guard<std::mutex> lock(s_messages_mutex);
|
||||||
|
s_messages.erase(type);
|
||||||
|
s_messages.emplace(type, Message(message, Common::Timer::GetTimeMs() + ms, rgba));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddMessage(const std::string& message, u32 ms, u32 rgba)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(s_messages_mutex);
|
||||||
|
s_messages.emplace(MessageType::Typeless,
|
||||||
|
Message(message, Common::Timer::GetTimeMs() + ms, rgba));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawMessage(const Message& msg, int top, int left, int time_left)
|
||||||
|
{
|
||||||
|
float alpha = std::min(1.0f, std::max(0.0f, time_left / 1024.0f));
|
||||||
|
u32 color = (msg.m_rgba & 0xFFFFFF) | ((u32)((msg.m_rgba >> 24) * alpha) << 24);
|
||||||
|
|
||||||
|
g_renderer->RenderText(msg.m_str, left, top, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawMessages()
|
void DrawMessages()
|
||||||
@ -39,28 +48,32 @@ void DrawMessages()
|
|||||||
if (!SConfig::GetInstance().bOnScreenDisplayMessages)
|
if (!SConfig::GetInstance().bOnScreenDisplayMessages)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int left = 25, top = 15;
|
|
||||||
auto it = s_msgList.begin();
|
|
||||||
while (it != s_msgList.end())
|
|
||||||
{
|
{
|
||||||
int time_left = (int)(it->m_timestamp - Common::Timer::GetTimeMs());
|
std::lock_guard<std::mutex> lock(s_messages_mutex);
|
||||||
float alpha = std::max(1.0f, std::min(0.0f, time_left / 1024.0f));
|
|
||||||
u32 color = (it->m_rgba & 0xFFFFFF) | ((u32)((it->m_rgba >> 24) * alpha) << 24);
|
|
||||||
|
|
||||||
g_renderer->RenderText(it->m_str, left, top, color);
|
u32 now = Common::Timer::GetTimeMs();
|
||||||
|
int left = 20, top = 35;
|
||||||
|
|
||||||
top += 15;
|
auto it = s_messages.begin();
|
||||||
|
while (it != s_messages.end())
|
||||||
|
{
|
||||||
|
const Message& msg = it->second;
|
||||||
|
int time_left = (int)(msg.m_timestamp - now);
|
||||||
|
DrawMessage(msg, top, left, time_left);
|
||||||
|
|
||||||
if (time_left <= 0)
|
if (time_left <= 0)
|
||||||
it = s_msgList.erase(it);
|
it = s_messages.erase(it);
|
||||||
else
|
else
|
||||||
++it;
|
++it;
|
||||||
|
top += 15;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClearMessages()
|
void ClearMessages()
|
||||||
{
|
{
|
||||||
s_msgList.clear();
|
std::lock_guard<std::mutex> lock(s_messages_mutex);
|
||||||
|
s_messages.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// On-Screen Display Callbacks
|
// On-Screen Display Callbacks
|
||||||
|
@ -11,9 +11,47 @@
|
|||||||
|
|
||||||
namespace OSD
|
namespace OSD
|
||||||
{
|
{
|
||||||
|
struct Message
|
||||||
|
{
|
||||||
|
Message() {}
|
||||||
|
Message(const std::string& s, u32 ts, u32 rgba) : m_str(s), m_timestamp(ts), m_rgba(rgba) {}
|
||||||
|
std::string m_str;
|
||||||
|
u32 m_timestamp;
|
||||||
|
u32 m_rgba;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class MessageType
|
||||||
|
{
|
||||||
|
NetPlayPing,
|
||||||
|
NetPlayBuffer,
|
||||||
|
|
||||||
|
// This entry must be kept last so that persistent typed messages are
|
||||||
|
// displayed before other messages
|
||||||
|
Typeless,
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace Color
|
||||||
|
{
|
||||||
|
constexpr u32 CYAN = 0xFF00FFFF;
|
||||||
|
constexpr u32 GREEN = 0xFF00FF00;
|
||||||
|
constexpr u32 RED = 0xFFFF0000;
|
||||||
|
constexpr u32 YELLOW = 0xFFFFFF30;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace Duration
|
||||||
|
{
|
||||||
|
constexpr u32 SHORT = 2000;
|
||||||
|
constexpr u32 NORMAL = 5000;
|
||||||
|
constexpr u32 VERY_LONG = 10000;
|
||||||
|
};
|
||||||
|
|
||||||
// On-screen message display (colored yellow by default)
|
// On-screen message display (colored yellow by default)
|
||||||
void AddMessage(const std::string& str, u32 ms = 2000, u32 rgba = 0xFFFFFF30);
|
void AddMessage(const std::string& message, u32 ms = Duration::SHORT, u32 rgba = Color::YELLOW);
|
||||||
void DrawMessages(); // draw the current messages on the screen. Only call once per frame.
|
void AddTypedMessage(MessageType type, const std::string& message, u32 ms = Duration::SHORT,
|
||||||
|
u32 rgba = Color::YELLOW);
|
||||||
|
void DrawMessage(const Message& msg, int top, int left, int time_left); // draw one message
|
||||||
|
void DrawMessages(); // draw the current messages on the screen. Only call once
|
||||||
|
// per frame.
|
||||||
void ClearMessages();
|
void ClearMessages();
|
||||||
|
|
||||||
// On-screen callbacks
|
// On-screen callbacks
|
||||||
|
@ -60,6 +60,8 @@ void VideoConfig::Load(const std::string& ini_file)
|
|||||||
settings->Get("UseRealXFB", &bUseRealXFB, 0);
|
settings->Get("UseRealXFB", &bUseRealXFB, 0);
|
||||||
settings->Get("SafeTextureCacheColorSamples", &iSafeTextureCache_ColorSamples, 128);
|
settings->Get("SafeTextureCacheColorSamples", &iSafeTextureCache_ColorSamples, 128);
|
||||||
settings->Get("ShowFPS", &bShowFPS, false);
|
settings->Get("ShowFPS", &bShowFPS, false);
|
||||||
|
settings->Get("ShowNetPlayPing", &bShowNetPlayPing, false);
|
||||||
|
settings->Get("ShowNetPlayMessages", &bShowNetPlayMessages, false);
|
||||||
settings->Get("LogRenderTimeToFile", &bLogRenderTimeToFile, false);
|
settings->Get("LogRenderTimeToFile", &bLogRenderTimeToFile, false);
|
||||||
settings->Get("OverlayStats", &bOverlayStats, false);
|
settings->Get("OverlayStats", &bOverlayStats, false);
|
||||||
settings->Get("OverlayProjStats", &bOverlayProjStats, false);
|
settings->Get("OverlayProjStats", &bOverlayProjStats, false);
|
||||||
@ -267,6 +269,8 @@ void VideoConfig::Save(const std::string& ini_file)
|
|||||||
settings->Set("UseRealXFB", bUseRealXFB);
|
settings->Set("UseRealXFB", bUseRealXFB);
|
||||||
settings->Set("SafeTextureCacheColorSamples", iSafeTextureCache_ColorSamples);
|
settings->Set("SafeTextureCacheColorSamples", iSafeTextureCache_ColorSamples);
|
||||||
settings->Set("ShowFPS", bShowFPS);
|
settings->Set("ShowFPS", bShowFPS);
|
||||||
|
settings->Set("ShowNetPlayPing", bShowNetPlayPing);
|
||||||
|
settings->Set("ShowNetPlayMessages", bShowNetPlayMessages);
|
||||||
settings->Set("LogRenderTimeToFile", bLogRenderTimeToFile);
|
settings->Set("LogRenderTimeToFile", bLogRenderTimeToFile);
|
||||||
settings->Set("OverlayStats", bOverlayStats);
|
settings->Set("OverlayStats", bOverlayStats);
|
||||||
settings->Set("OverlayProjStats", bOverlayProjStats);
|
settings->Set("OverlayProjStats", bOverlayProjStats);
|
||||||
|
@ -82,6 +82,8 @@ struct VideoConfig final
|
|||||||
|
|
||||||
// Information
|
// Information
|
||||||
bool bShowFPS;
|
bool bShowFPS;
|
||||||
|
bool bShowNetPlayPing;
|
||||||
|
bool bShowNetPlayMessages;
|
||||||
bool bOverlayStats;
|
bool bOverlayStats;
|
||||||
bool bOverlayProjStats;
|
bool bOverlayProjStats;
|
||||||
bool bTexFmtOverlayEnable;
|
bool bTexFmtOverlayEnable;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user