mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 02:32:36 +01:00
overlays: add friends list to home menu
This commit is contained in:
parent
73fe420d09
commit
0a57c459b6
@ -512,6 +512,7 @@ target_sources(rpcs3_emu PRIVATE
|
|||||||
RSX/NV47/HW/nv308a.cpp
|
RSX/NV47/HW/nv308a.cpp
|
||||||
RSX/NV47/HW/nv406e.cpp
|
RSX/NV47/HW/nv406e.cpp
|
||||||
RSX/NV47/HW/nv4097.cpp
|
RSX/NV47/HW/nv4097.cpp
|
||||||
|
RSX/Overlays/FriendsList/overlay_friends_list_dialog.cpp
|
||||||
RSX/Overlays/HomeMenu/overlay_home_menu.cpp
|
RSX/Overlays/HomeMenu/overlay_home_menu.cpp
|
||||||
RSX/Overlays/HomeMenu/overlay_home_menu_components.cpp
|
RSX/Overlays/HomeMenu/overlay_home_menu_components.cpp
|
||||||
RSX/Overlays/HomeMenu/overlay_home_menu_main_menu.cpp
|
RSX/Overlays/HomeMenu/overlay_home_menu_main_menu.cpp
|
||||||
|
@ -768,7 +768,7 @@ namespace np
|
|||||||
if (g_cfg.net.psn_status >= np_psn_status::psn_fake)
|
if (g_cfg.net.psn_status >= np_psn_status::psn_fake)
|
||||||
{
|
{
|
||||||
g_cfg_rpcn.load(); // Ensures config is loaded even if rpcn is not running for simulated
|
g_cfg_rpcn.load(); // Ensures config is loaded even if rpcn is not running for simulated
|
||||||
std::string s_npid = g_cfg_rpcn.get_npid();
|
const std::string s_npid = g_cfg_rpcn.get_npid();
|
||||||
ensure(!s_npid.empty()); // It should have been generated before this
|
ensure(!s_npid.empty()); // It should have been generated before this
|
||||||
|
|
||||||
string_to_npid(s_npid, npid);
|
string_to_npid(s_npid, npid);
|
||||||
|
@ -75,7 +75,7 @@ namespace rpcn
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void overlay_friend_callback(void* param, rpcn::NotificationType ntype, const std::string& username, bool status)
|
void overlay_friend_callback(void* /*param*/, rpcn::NotificationType ntype, const std::string& username, bool status)
|
||||||
{
|
{
|
||||||
if (!g_cfg.misc.show_rpcn_popups)
|
if (!g_cfg.misc.show_rpcn_popups)
|
||||||
return;
|
return;
|
||||||
@ -88,6 +88,7 @@ namespace rpcn
|
|||||||
case rpcn::NotificationType::FriendNew: loc_id = localized_string_id::RPCN_FRIEND_ADDED; break;
|
case rpcn::NotificationType::FriendNew: loc_id = localized_string_id::RPCN_FRIEND_ADDED; break;
|
||||||
case rpcn::NotificationType::FriendLost: loc_id = localized_string_id::RPCN_FRIEND_LOST; break;
|
case rpcn::NotificationType::FriendLost: loc_id = localized_string_id::RPCN_FRIEND_LOST; break;
|
||||||
case rpcn::NotificationType::FriendStatus: loc_id = status ? localized_string_id::RPCN_FRIEND_LOGGED_IN : localized_string_id::RPCN_FRIEND_LOGGED_OUT; break;
|
case rpcn::NotificationType::FriendStatus: loc_id = status ? localized_string_id::RPCN_FRIEND_LOGGED_IN : localized_string_id::RPCN_FRIEND_LOGGED_OUT; break;
|
||||||
|
case rpcn::NotificationType::FriendPresenceChanged: return;
|
||||||
default: rpcn_log.fatal("An unhandled notification type was received by the overlay friend callback!"); break;
|
default: rpcn_log.fatal("An unhandled notification type was received by the overlay friend callback!"); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2572,6 +2573,12 @@ namespace rpcn
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rpcn_client::get_friends(friend_data& friend_infos)
|
||||||
|
{
|
||||||
|
std::lock_guard lock(mutex_friends);
|
||||||
|
friend_infos = this->friend_infos;
|
||||||
|
}
|
||||||
|
|
||||||
void rpcn_client::get_friends_and_register_cb(friend_data& friend_infos, friend_cb_func cb_func, void* cb_param)
|
void rpcn_client::get_friends_and_register_cb(friend_data& friend_infos, friend_cb_func cb_func, void* cb_param)
|
||||||
{
|
{
|
||||||
std::lock_guard lock(mutex_friends);
|
std::lock_guard lock(mutex_friends);
|
||||||
@ -2619,7 +2626,7 @@ namespace rpcn
|
|||||||
{
|
{
|
||||||
case NotificationType::FriendQuery: // Other user sent a friend request
|
case NotificationType::FriendQuery: // Other user sent a friend request
|
||||||
{
|
{
|
||||||
std::string username = vdata.get_string(false);
|
const std::string username = vdata.get_string(false);
|
||||||
if (vdata.is_error())
|
if (vdata.is_error())
|
||||||
{
|
{
|
||||||
rpcn_log.error("Error parsing FriendQuery notification");
|
rpcn_log.error("Error parsing FriendQuery notification");
|
||||||
@ -2632,8 +2639,8 @@ namespace rpcn
|
|||||||
}
|
}
|
||||||
case NotificationType::FriendNew: // Add a friend to the friendlist(either accepted a friend request or friend accepted it)
|
case NotificationType::FriendNew: // Add a friend to the friendlist(either accepted a friend request or friend accepted it)
|
||||||
{
|
{
|
||||||
bool online = !!vdata.get<u8>();
|
const bool online = !!vdata.get<u8>();
|
||||||
std::string username = vdata.get_string(false);
|
const std::string username = vdata.get_string(false);
|
||||||
if (vdata.is_error())
|
if (vdata.is_error())
|
||||||
{
|
{
|
||||||
rpcn_log.error("Error parsing FriendNew notification");
|
rpcn_log.error("Error parsing FriendNew notification");
|
||||||
@ -2649,22 +2656,24 @@ namespace rpcn
|
|||||||
}
|
}
|
||||||
case NotificationType::FriendLost: // Remove friend from the friendlist(user removed friend or friend removed friend)
|
case NotificationType::FriendLost: // Remove friend from the friendlist(user removed friend or friend removed friend)
|
||||||
{
|
{
|
||||||
std::string username = vdata.get_string(false);
|
const std::string username = vdata.get_string(false);
|
||||||
if (vdata.is_error())
|
if (vdata.is_error())
|
||||||
{
|
{
|
||||||
rpcn_log.error("Error parsing FriendLost notification");
|
rpcn_log.error("Error parsing FriendLost notification");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
friend_infos.requests_received.erase(username);
|
||||||
|
friend_infos.requests_sent.erase(username);
|
||||||
friend_infos.friends.erase(username);
|
friend_infos.friends.erase(username);
|
||||||
call_callbacks(ntype, username, false);
|
call_callbacks(ntype, username, false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NotificationType::FriendStatus: // Set status of friend to Offline or Online
|
case NotificationType::FriendStatus: // Set status of friend to Offline or Online
|
||||||
{
|
{
|
||||||
bool online = !!vdata.get<u8>();
|
const bool online = !!vdata.get<u8>();
|
||||||
u64 timestamp = vdata.get<u64>();
|
const u64 timestamp = vdata.get<u64>();
|
||||||
std::string username = vdata.get_string(false);
|
const std::string username = vdata.get_string(false);
|
||||||
if (vdata.is_error())
|
if (vdata.is_error())
|
||||||
{
|
{
|
||||||
rpcn_log.error("Error parsing FriendStatus notification");
|
rpcn_log.error("Error parsing FriendStatus notification");
|
||||||
@ -2692,7 +2701,7 @@ namespace rpcn
|
|||||||
}
|
}
|
||||||
case NotificationType::FriendPresenceChanged:
|
case NotificationType::FriendPresenceChanged:
|
||||||
{
|
{
|
||||||
std::string npid = vdata.get_string(true);
|
const std::string username = vdata.get_string(true);
|
||||||
SceNpCommunicationId pr_com_id = vdata.get_com_id();
|
SceNpCommunicationId pr_com_id = vdata.get_com_id();
|
||||||
std::string pr_title = fmt::truncate(vdata.get_string(true), SCE_NP_BASIC_PRESENCE_TITLE_SIZE_MAX - 1);
|
std::string pr_title = fmt::truncate(vdata.get_string(true), SCE_NP_BASIC_PRESENCE_TITLE_SIZE_MAX - 1);
|
||||||
std::string pr_status = fmt::truncate(vdata.get_string(true), SCE_NP_BASIC_PRESENCE_EXTENDED_STATUS_SIZE_MAX - 1);
|
std::string pr_status = fmt::truncate(vdata.get_string(true), SCE_NP_BASIC_PRESENCE_EXTENDED_STATUS_SIZE_MAX - 1);
|
||||||
@ -2709,7 +2718,7 @@ namespace rpcn
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto u = friend_infos.friends.find(npid); u != friend_infos.friends.end())
|
if (auto u = friend_infos.friends.find(username); u != friend_infos.friends.end())
|
||||||
{
|
{
|
||||||
u->second.pr_com_id = std::move(pr_com_id);
|
u->second.pr_com_id = std::move(pr_com_id);
|
||||||
u->second.pr_title = std::move(pr_title);
|
u->second.pr_title = std::move(pr_title);
|
||||||
@ -2718,9 +2727,10 @@ namespace rpcn
|
|||||||
u->second.pr_data = std::move(pr_data);
|
u->second.pr_data = std::move(pr_data);
|
||||||
|
|
||||||
std::lock_guard lock(mutex_presence_updates);
|
std::lock_guard lock(mutex_presence_updates);
|
||||||
presence_updates.insert_or_assign(std::move(npid), u->second);
|
presence_updates.insert_or_assign(username, u->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
call_callbacks(ntype, username, false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -439,6 +439,7 @@ namespace rpcn
|
|||||||
rpcn_state wait_for_authentified();
|
rpcn_state wait_for_authentified();
|
||||||
bool terminate_connection();
|
bool terminate_connection();
|
||||||
|
|
||||||
|
void get_friends(friend_data& friend_infos);
|
||||||
void get_friends_and_register_cb(friend_data& friend_infos, friend_cb_func cb_func, void* cb_param);
|
void get_friends_and_register_cb(friend_data& friend_infos, friend_cb_func cb_func, void* cb_param);
|
||||||
void register_friend_cb(friend_cb_func, void* cb_param);
|
void register_friend_cb(friend_cb_func, void* cb_param);
|
||||||
void remove_friend_cb(friend_cb_func, void* cb_param);
|
void remove_friend_cb(friend_cb_func, void* cb_param);
|
||||||
|
@ -0,0 +1,679 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
#include "../overlay_manager.h"
|
||||||
|
#include "overlay_friends_list_dialog.h"
|
||||||
|
#include "Emu/System.h"
|
||||||
|
#include "Emu/NP/rpcn_config.h"
|
||||||
|
#include "Emu/vfs_config.h"
|
||||||
|
|
||||||
|
namespace rsx
|
||||||
|
{
|
||||||
|
namespace overlays
|
||||||
|
{
|
||||||
|
void friend_callback(void* param, rpcn::NotificationType ntype, const std::string& username, bool status)
|
||||||
|
{
|
||||||
|
auto* dlg = static_cast<friends_list_dialog*>(param);
|
||||||
|
dlg->callback_handler(ntype, username, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
friends_list_dialog::friends_list_entry::friends_list_entry(friends_list_dialog_page page, const std::string& username, const rpcn::friend_online_data& data)
|
||||||
|
{
|
||||||
|
std::unique_ptr<overlay_element> image = std::make_unique<image_view>();
|
||||||
|
image->set_size(160, 110);
|
||||||
|
image->set_padding(36, 36, 11, 11); // Square image, 88x88
|
||||||
|
|
||||||
|
std::string avatar_path = g_cfg_vfs.get_dev_flash() + "vsh/resource/explore/user/";
|
||||||
|
std::string text;
|
||||||
|
|
||||||
|
switch (page)
|
||||||
|
{
|
||||||
|
case friends_list_dialog_page::friends:
|
||||||
|
{
|
||||||
|
avatar_path += data.online ? "013.png" : "009.png";
|
||||||
|
text = get_localized_string(data.online ? localized_string_id::HOME_MENU_FRIENDS_STATUS_ONLINE : localized_string_id::HOME_MENU_FRIENDS_STATUS_OFFLINE);
|
||||||
|
|
||||||
|
if (data.online)
|
||||||
|
{
|
||||||
|
if (!data.pr_title.empty())
|
||||||
|
{
|
||||||
|
fmt::append(text, " - %s", data.pr_title);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data.pr_status.empty())
|
||||||
|
{
|
||||||
|
fmt::append(text, " - %s", data.pr_status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case friends_list_dialog_page::invites:
|
||||||
|
{
|
||||||
|
// We use "online" to show whether an invite was sent or received
|
||||||
|
avatar_path += data.online ? "012.png" : "011.png";
|
||||||
|
text = get_localized_string(data.online ? localized_string_id::HOME_MENU_FRIENDS_REQUEST_RECEIVED : localized_string_id::HOME_MENU_FRIENDS_REQUEST_SENT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case friends_list_dialog_page::blocked:
|
||||||
|
{
|
||||||
|
avatar_path += "010.png";
|
||||||
|
text = get_localized_string(localized_string_id::HOME_MENU_FRIENDS_STATUS_BLOCKED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fs::exists(avatar_path))
|
||||||
|
{
|
||||||
|
icon_data = std::make_unique<image_info>(avatar_path.c_str());
|
||||||
|
static_cast<image_view*>(image.get())->set_raw_image(icon_data.get());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Fallback
|
||||||
|
// TODO: use proper icon
|
||||||
|
static_cast<image_view*>(image.get())->set_image_resource(resource_config::standard_image_resource::square);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<overlay_element> text_stack = std::make_unique<vertical_layout>();
|
||||||
|
std::unique_ptr<overlay_element> padding = std::make_unique<spacer>();
|
||||||
|
std::unique_ptr<overlay_element> header_text = std::make_unique<label>(username);
|
||||||
|
std::unique_ptr<overlay_element> subtext = std::make_unique<label>(text);
|
||||||
|
|
||||||
|
padding->set_size(1, 1);
|
||||||
|
header_text->set_size(800, 40);
|
||||||
|
header_text->set_font("Arial", 16);
|
||||||
|
header_text->set_wrap_text(true);
|
||||||
|
|
||||||
|
subtext->set_size(800, 0);
|
||||||
|
subtext->set_font("Arial", 14);
|
||||||
|
subtext->set_wrap_text(true);
|
||||||
|
static_cast<label*>(subtext.get())->auto_resize(true);
|
||||||
|
|
||||||
|
// Make back color transparent for text
|
||||||
|
header_text->back_color.a = 0.f;
|
||||||
|
subtext->back_color.a = 0.f;
|
||||||
|
|
||||||
|
static_cast<vertical_layout*>(text_stack.get())->pack_padding = 5;
|
||||||
|
static_cast<vertical_layout*>(text_stack.get())->add_element(padding);
|
||||||
|
static_cast<vertical_layout*>(text_stack.get())->add_element(header_text);
|
||||||
|
static_cast<vertical_layout*>(text_stack.get())->add_element(subtext);
|
||||||
|
|
||||||
|
if (text_stack->h > image->h)
|
||||||
|
{
|
||||||
|
std::unique_ptr<overlay_element> padding2 = std::make_unique<spacer>();
|
||||||
|
padding2->set_size(1, 5);
|
||||||
|
static_cast<vertical_layout*>(text_stack.get())->add_element(padding2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pack
|
||||||
|
this->pack_padding = 15;
|
||||||
|
add_element(image);
|
||||||
|
add_element(text_stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
friends_list_dialog::friends_list_dialog()
|
||||||
|
: m_page_btn(120, 30)
|
||||||
|
, m_extra_btn(120, 30)
|
||||||
|
{
|
||||||
|
m_dim_background = std::make_unique<overlay_element>();
|
||||||
|
m_dim_background->set_size(virtual_width, virtual_height);
|
||||||
|
m_dim_background->back_color.a = 0.5f;
|
||||||
|
|
||||||
|
m_list = std::make_unique<list_view>(virtual_width - 2 * 20, 540);
|
||||||
|
m_list->set_pos(20, 85);
|
||||||
|
|
||||||
|
m_message_box = std::make_shared<home_menu_message_box>(20, 85, virtual_width - 2 * 20, 540);
|
||||||
|
|
||||||
|
m_description = std::make_unique<label>();
|
||||||
|
m_description->set_font("Arial", 20);
|
||||||
|
m_description->set_pos(20, 37);
|
||||||
|
m_description->set_text("Select user"); // Fallback. I don't think this will ever be used, so I won't localize it.
|
||||||
|
m_description->auto_resize();
|
||||||
|
m_description->back_color.a = 0.f;
|
||||||
|
|
||||||
|
fade_animation.duration_sec = 0.15f;
|
||||||
|
|
||||||
|
return_code = selection_code::canceled;
|
||||||
|
|
||||||
|
m_extra_btn.set_image_resource(resource_config::standard_image_resource::triangle);
|
||||||
|
m_extra_btn.set_pos(330, m_list->y + m_list->h + 20);
|
||||||
|
m_extra_btn.set_text("");
|
||||||
|
m_extra_btn.set_font("Arial", 16);
|
||||||
|
|
||||||
|
m_page_btn.set_image_resource(resource_config::standard_image_resource::square);
|
||||||
|
m_page_btn.set_pos(m_list->x + m_list->w - (30 + 120), m_list->y + m_list->h + 20);
|
||||||
|
m_page_btn.set_text(get_localized_string(localized_string_id::HOME_MENU_FRIENDS_NEXT_LIST));
|
||||||
|
m_page_btn.set_font("Arial", 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
void friends_list_dialog::update(u64 timestamp_us)
|
||||||
|
{
|
||||||
|
if (fade_animation.active)
|
||||||
|
{
|
||||||
|
fade_animation.update(timestamp_us);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void friends_list_dialog::on_button_pressed(pad_button button_press, bool is_auto_repeat)
|
||||||
|
{
|
||||||
|
if (fade_animation.active) return;
|
||||||
|
|
||||||
|
if (m_message_box && m_message_box->visible())
|
||||||
|
{
|
||||||
|
const page_navigation navigation = m_message_box->handle_button_press(button_press);
|
||||||
|
if (navigation != page_navigation::stay)
|
||||||
|
{
|
||||||
|
m_message_box->hide();
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard lock(m_list_mutex);
|
||||||
|
bool close_dialog = false;
|
||||||
|
|
||||||
|
switch (button_press)
|
||||||
|
{
|
||||||
|
case pad_button::cross:
|
||||||
|
case pad_button::triangle:
|
||||||
|
{
|
||||||
|
if (!m_list || m_list->m_items.empty())
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (button_press == pad_button::triangle && m_current_page != friends_list_dialog_page::invites)
|
||||||
|
break;
|
||||||
|
|
||||||
|
const usz index = static_cast<usz>(m_list->get_selected_index());
|
||||||
|
|
||||||
|
switch (m_current_page)
|
||||||
|
{
|
||||||
|
case friends_list_dialog_page::friends:
|
||||||
|
{
|
||||||
|
// Get selected user
|
||||||
|
usz user_index = 0;
|
||||||
|
std::string selected_username;
|
||||||
|
for (const auto& [username, data] : m_friend_data.friends)
|
||||||
|
{
|
||||||
|
if (data.online && user_index++ == index)
|
||||||
|
{
|
||||||
|
selected_username = username;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const auto& [username, data] : m_friend_data.friends)
|
||||||
|
{
|
||||||
|
if (!selected_username.empty())
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!data.online && user_index++ == index)
|
||||||
|
{
|
||||||
|
selected_username = username;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!selected_username.empty() && m_message_box && !m_message_box->visible())
|
||||||
|
{
|
||||||
|
m_message_box->show(get_localized_string(localized_string_id::HOME_MENU_FRIENDS_REMOVE_USER_MSG, selected_username.c_str()), [this, selected_username]()
|
||||||
|
{
|
||||||
|
m_rpcn->remove_friend(selected_username);
|
||||||
|
});
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case friends_list_dialog_page::invites:
|
||||||
|
{
|
||||||
|
// Get selected user
|
||||||
|
usz user_index = 0;
|
||||||
|
std::string selected_username;
|
||||||
|
for (const std::string& username : m_friend_data.requests_received)
|
||||||
|
{
|
||||||
|
if (user_index == index)
|
||||||
|
{
|
||||||
|
selected_username = username;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
user_index++;
|
||||||
|
}
|
||||||
|
for (const std::string& username : m_friend_data.requests_sent)
|
||||||
|
{
|
||||||
|
if (!selected_username.empty())
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (user_index == index)
|
||||||
|
{
|
||||||
|
selected_username = username;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
user_index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!selected_username.empty() && m_message_box && !m_message_box->visible())
|
||||||
|
{
|
||||||
|
if (user_index < m_friend_data.requests_received.size())
|
||||||
|
{
|
||||||
|
if (button_press == pad_button::triangle)
|
||||||
|
{
|
||||||
|
m_message_box->show(get_localized_string(localized_string_id::HOME_MENU_FRIENDS_REJECT_REQUEST_MSG, selected_username.c_str()), [this, selected_username]()
|
||||||
|
{
|
||||||
|
m_rpcn->remove_friend(selected_username);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_message_box->show(get_localized_string(localized_string_id::HOME_MENU_FRIENDS_ACCEPT_REQUEST_MSG, selected_username.c_str()), [this, selected_username]()
|
||||||
|
{
|
||||||
|
m_rpcn->add_friend(selected_username);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_message_box->show(get_localized_string(localized_string_id::HOME_MENU_FRIENDS_CANCEL_REQUEST_MSG, selected_username.c_str()), [this, selected_username]()
|
||||||
|
{
|
||||||
|
m_rpcn->remove_friend(selected_username);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case friends_list_dialog_page::blocked:
|
||||||
|
{
|
||||||
|
// Get selected user
|
||||||
|
usz user_index = 0;
|
||||||
|
std::string selected_username;
|
||||||
|
for (const std::string& username : m_friend_data.blocked)
|
||||||
|
{
|
||||||
|
if (user_index++ == index)
|
||||||
|
{
|
||||||
|
selected_username = username;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!selected_username.empty() && m_message_box && !m_message_box->visible())
|
||||||
|
{
|
||||||
|
m_message_box->show(get_localized_string(localized_string_id::HOME_MENU_FRIENDS_UNBLOCK_USER_MSG, selected_username.c_str()), []()
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_decide.wav");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case pad_button::circle:
|
||||||
|
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cancel.wav");
|
||||||
|
close_dialog = true;
|
||||||
|
break;
|
||||||
|
case pad_button::square:
|
||||||
|
switch (m_current_page)
|
||||||
|
{
|
||||||
|
case friends_list_dialog_page::friends: m_current_page = friends_list_dialog_page::invites; break;
|
||||||
|
case friends_list_dialog_page::invites: m_current_page = friends_list_dialog_page::blocked; break;
|
||||||
|
case friends_list_dialog_page::blocked: m_current_page = friends_list_dialog_page::friends; break;
|
||||||
|
}
|
||||||
|
m_list_dirty = true;
|
||||||
|
break;
|
||||||
|
case pad_button::dpad_up:
|
||||||
|
case pad_button::ls_up:
|
||||||
|
if (m_list)
|
||||||
|
m_list->select_previous();
|
||||||
|
break;
|
||||||
|
case pad_button::dpad_down:
|
||||||
|
case pad_button::ls_down:
|
||||||
|
if (m_list)
|
||||||
|
m_list->select_next();
|
||||||
|
break;
|
||||||
|
case pad_button::L1:
|
||||||
|
if (m_list)
|
||||||
|
m_list->select_previous(10);
|
||||||
|
break;
|
||||||
|
case pad_button::R1:
|
||||||
|
if (m_list)
|
||||||
|
m_list->select_next(10);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rsx_log.trace("[ui] Button %d pressed", static_cast<u8>(button_press));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (close_dialog)
|
||||||
|
{
|
||||||
|
fade_animation.current = color4f(1.f);
|
||||||
|
fade_animation.end = color4f(0.f);
|
||||||
|
fade_animation.active = true;
|
||||||
|
|
||||||
|
fade_animation.on_finish = [this]
|
||||||
|
{
|
||||||
|
close(true, true);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// Play a sound unless this is a fast auto repeat which would induce a nasty noise
|
||||||
|
else if (!is_auto_repeat || m_auto_repeat_ms_interval >= m_auto_repeat_ms_interval_default)
|
||||||
|
{
|
||||||
|
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cursor.wav");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compiled_resource friends_list_dialog::get_compiled()
|
||||||
|
{
|
||||||
|
if (!visible)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
compiled_resource result;
|
||||||
|
result.add(m_dim_background->get_compiled());
|
||||||
|
{
|
||||||
|
std::lock_guard lock(m_list_mutex);
|
||||||
|
|
||||||
|
if (m_list_dirty.exchange(false))
|
||||||
|
{
|
||||||
|
if (m_current_page != m_last_page)
|
||||||
|
{
|
||||||
|
localized_string_id title_id = localized_string_id::INVALID;
|
||||||
|
switch (m_current_page)
|
||||||
|
{
|
||||||
|
case friends_list_dialog_page::friends: title_id = localized_string_id::HOME_MENU_FRIENDS; break;
|
||||||
|
case friends_list_dialog_page::invites: title_id = localized_string_id::HOME_MENU_FRIENDS_REQUESTS; break;
|
||||||
|
case friends_list_dialog_page::blocked: title_id = localized_string_id::HOME_MENU_FRIENDS_BLOCKED; break;
|
||||||
|
}
|
||||||
|
m_description->set_text(get_localized_string(title_id));
|
||||||
|
m_description->auto_resize();
|
||||||
|
}
|
||||||
|
|
||||||
|
reload();
|
||||||
|
|
||||||
|
m_last_page.store(m_current_page);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_message_box && m_message_box->visible())
|
||||||
|
{
|
||||||
|
result.add(m_message_box->get_compiled());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (m_list)
|
||||||
|
{
|
||||||
|
result.add(m_list->get_compiled());
|
||||||
|
|
||||||
|
if (!m_list->m_items.empty() && m_current_page == friends_list_dialog_page::invites)
|
||||||
|
{
|
||||||
|
// Get selected user
|
||||||
|
const usz index = static_cast<usz>(m_list->get_selected_index());
|
||||||
|
|
||||||
|
if (index < m_friend_data.requests_received.size())
|
||||||
|
{
|
||||||
|
m_extra_btn.set_text(get_localized_string(localized_string_id::HOME_MENU_FRIENDS_REJECT_REQUEST));
|
||||||
|
result.add(m_extra_btn.get_compiled());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.add(m_page_btn.get_compiled());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.add(m_description->get_compiled());
|
||||||
|
|
||||||
|
fade_animation.apply(result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void friends_list_dialog::callback_handler(rpcn::NotificationType ntype, const std::string& /*username*/, bool /*status*/)
|
||||||
|
{
|
||||||
|
switch (ntype)
|
||||||
|
{
|
||||||
|
case rpcn::NotificationType::FriendNew: // Add a friend to the friendlist(either accepted a friend request or friend accepted it)
|
||||||
|
case rpcn::NotificationType::FriendStatus: // Set status of friend to Offline or Online
|
||||||
|
case rpcn::NotificationType::FriendQuery: // Other user sent a friend request
|
||||||
|
case rpcn::NotificationType::FriendLost: // Remove friend from the friendlist(user removed friend or friend removed friend)
|
||||||
|
case rpcn::NotificationType::FriendPresenceChanged:
|
||||||
|
{
|
||||||
|
m_list_dirty = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
rsx_log.fatal("An unhandled notification type was received by the RPCN friends dialog callback!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void friends_list_dialog::reload()
|
||||||
|
{
|
||||||
|
std::vector<std::unique_ptr<overlay_element>> entries;
|
||||||
|
std::string selected_user;
|
||||||
|
s32 selected_index = 0;
|
||||||
|
|
||||||
|
// Get selected user name
|
||||||
|
if (m_list && m_current_page == m_last_page)
|
||||||
|
{
|
||||||
|
const s32 old_index = m_list->get_selected_index();
|
||||||
|
s32 i = 0;
|
||||||
|
|
||||||
|
switch (m_current_page)
|
||||||
|
{
|
||||||
|
case friends_list_dialog_page::friends:
|
||||||
|
{
|
||||||
|
for (const auto& [username, data] : m_friend_data.friends)
|
||||||
|
{
|
||||||
|
if (i++ == old_index)
|
||||||
|
{
|
||||||
|
selected_user = username;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case friends_list_dialog_page::invites:
|
||||||
|
{
|
||||||
|
for (const std::string& username : m_friend_data.requests_received)
|
||||||
|
{
|
||||||
|
if (i++ == old_index)
|
||||||
|
{
|
||||||
|
selected_user = username;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const std::string& username : m_friend_data.requests_sent)
|
||||||
|
{
|
||||||
|
if (!selected_user.empty())
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (i++ == old_index)
|
||||||
|
{
|
||||||
|
selected_user = username;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case friends_list_dialog_page::blocked:
|
||||||
|
{
|
||||||
|
for (const std::string& username : m_friend_data.blocked)
|
||||||
|
{
|
||||||
|
if (i++ == old_index)
|
||||||
|
{
|
||||||
|
selected_user = username;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto res = m_rpcn->wait_for_connection(); res != rpcn::rpcn_state::failure_no_failure)
|
||||||
|
{
|
||||||
|
rsx_log.error("Failed to connect to RPCN: %s", rpcn::rpcn_state_to_string(res));
|
||||||
|
status_flags |= status_bits::invalidate_image_cache;
|
||||||
|
m_list.reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto res = m_rpcn->wait_for_authentified(); res != rpcn::rpcn_state::failure_no_failure)
|
||||||
|
{
|
||||||
|
rsx_log.error("Failed to authentify to RPCN: %s", rpcn::rpcn_state_to_string(res));
|
||||||
|
status_flags |= status_bits::invalidate_image_cache;
|
||||||
|
m_list.reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get friends, setup callback and setup comboboxes
|
||||||
|
m_rpcn->get_friends(m_friend_data);
|
||||||
|
|
||||||
|
switch (m_current_page)
|
||||||
|
{
|
||||||
|
case friends_list_dialog_page::friends:
|
||||||
|
{
|
||||||
|
// Sort users by online status
|
||||||
|
std::vector<std::pair<const std::string&, const rpcn::friend_online_data&>> friends_online;
|
||||||
|
std::vector<std::pair<const std::string&, const rpcn::friend_online_data&>> friends_offline;
|
||||||
|
for (const auto& [username, data] : m_friend_data.friends)
|
||||||
|
{
|
||||||
|
if (data.online)
|
||||||
|
{
|
||||||
|
friends_online.push_back({ username, data });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
friends_offline.push_back({ username, data });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add users and try to find the old selected user again
|
||||||
|
for (const auto& [username, data] : friends_online)
|
||||||
|
{
|
||||||
|
if (username == selected_user)
|
||||||
|
{
|
||||||
|
selected_index = ::size32(entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<overlay_element> entry = std::make_unique<friends_list_entry>(m_current_page, username, data);
|
||||||
|
entries.emplace_back(std::move(entry));
|
||||||
|
}
|
||||||
|
for (const auto& [username, data] : friends_offline)
|
||||||
|
{
|
||||||
|
if (username == selected_user)
|
||||||
|
{
|
||||||
|
selected_index = ::size32(entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<overlay_element> entry = std::make_unique<friends_list_entry>(m_current_page, username, data);
|
||||||
|
entries.emplace_back(std::move(entry));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case friends_list_dialog_page::invites:
|
||||||
|
{
|
||||||
|
for (const std::string& username : m_friend_data.requests_received)
|
||||||
|
{
|
||||||
|
if (username == selected_user)
|
||||||
|
{
|
||||||
|
selected_index = ::size32(entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<overlay_element> entry = std::make_unique<friends_list_entry>(m_current_page, username, rpcn::friend_online_data(true, 0));
|
||||||
|
entries.emplace_back(std::move(entry));
|
||||||
|
}
|
||||||
|
for (const std::string& username : m_friend_data.requests_sent)
|
||||||
|
{
|
||||||
|
if (username == selected_user)
|
||||||
|
{
|
||||||
|
selected_index = ::size32(entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<overlay_element> entry = std::make_unique<friends_list_entry>(m_current_page, username, rpcn::friend_online_data(false, 0));
|
||||||
|
entries.emplace_back(std::move(entry));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case friends_list_dialog_page::blocked:
|
||||||
|
{
|
||||||
|
for (const std::string& username : m_friend_data.blocked)
|
||||||
|
{
|
||||||
|
if (username == selected_user)
|
||||||
|
{
|
||||||
|
selected_index = ::size32(entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<overlay_element> entry = std::make_unique<friends_list_entry>(m_current_page, username, rpcn::friend_online_data(false, 0));
|
||||||
|
entries.emplace_back(std::move(entry));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recreate list
|
||||||
|
if (m_list)
|
||||||
|
{
|
||||||
|
status_flags |= status_bits::invalidate_image_cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_list = std::make_unique<list_view>(virtual_width - 2 * 20, 540);
|
||||||
|
m_list->set_pos(20, 85);
|
||||||
|
|
||||||
|
for (auto& entry : entries)
|
||||||
|
{
|
||||||
|
m_list->add_entry(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_list->m_items.empty())
|
||||||
|
{
|
||||||
|
// Only select an entry if there are entries available
|
||||||
|
m_list->select_entry(selected_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
error_code friends_list_dialog::show(bool enable_overlay, std::function<void(s32 status)> on_close)
|
||||||
|
{
|
||||||
|
visible = false;
|
||||||
|
|
||||||
|
if (enable_overlay)
|
||||||
|
{
|
||||||
|
m_dim_background->back_color.a = 0.9f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_dim_background->back_color.a = 0.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_cfg_rpcn.load(); // Ensures config is loaded even if rpcn is not running for simulated
|
||||||
|
|
||||||
|
m_rpcn = rpcn::rpcn_client::get_instance();
|
||||||
|
|
||||||
|
m_rpcn->register_friend_cb(friend_callback, this);
|
||||||
|
|
||||||
|
m_description->set_text(get_localized_string(localized_string_id::HOME_MENU_FRIENDS));
|
||||||
|
m_description->auto_resize();
|
||||||
|
|
||||||
|
fade_animation.current = color4f(0.f);
|
||||||
|
fade_animation.end = color4f(1.f);
|
||||||
|
fade_animation.active = true;
|
||||||
|
|
||||||
|
this->on_close = std::move(on_close);
|
||||||
|
visible = true;
|
||||||
|
|
||||||
|
const auto notify = std::make_shared<atomic_t<u32>>(0);
|
||||||
|
auto& overlayman = g_fxo->get<display_manager>();
|
||||||
|
|
||||||
|
overlayman.attach_thread_input(
|
||||||
|
uid, "Friends list dialog",
|
||||||
|
[notify]() { *notify = true; notify->notify_one(); }
|
||||||
|
);
|
||||||
|
|
||||||
|
while (!Emu.IsStopped() && !*notify)
|
||||||
|
{
|
||||||
|
notify->wait(0, atomic_wait_timeout{1'000'000});
|
||||||
|
}
|
||||||
|
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
|
} // namespace overlays
|
||||||
|
} // namespace RSX
|
@ -0,0 +1,64 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../overlays.h"
|
||||||
|
#include "../overlay_list_view.hpp"
|
||||||
|
#include "../HomeMenu/overlay_home_menu_message_box.h"
|
||||||
|
#include "Emu/Cell/ErrorCodes.h"
|
||||||
|
#include "Emu/NP/rpcn_client.h"
|
||||||
|
|
||||||
|
namespace rsx
|
||||||
|
{
|
||||||
|
namespace overlays
|
||||||
|
{
|
||||||
|
enum class friends_list_dialog_page
|
||||||
|
{
|
||||||
|
friends,
|
||||||
|
invites,
|
||||||
|
blocked
|
||||||
|
};
|
||||||
|
|
||||||
|
struct friends_list_dialog : public user_interface
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
struct friends_list_entry : horizontal_layout
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::unique_ptr<image_info> icon_data;
|
||||||
|
|
||||||
|
public:
|
||||||
|
friends_list_entry(friends_list_dialog_page page, const std::string& username, const rpcn::friend_online_data& data);
|
||||||
|
};
|
||||||
|
|
||||||
|
std::mutex m_list_mutex;
|
||||||
|
std::vector<u32> m_entry_ids;
|
||||||
|
std::unique_ptr<overlay_element> m_dim_background;
|
||||||
|
std::unique_ptr<list_view> m_list;
|
||||||
|
std::unique_ptr<label> m_description;
|
||||||
|
image_button m_page_btn;
|
||||||
|
image_button m_extra_btn;
|
||||||
|
std::shared_ptr<home_menu_message_box> m_message_box;
|
||||||
|
|
||||||
|
animation_color_interpolate fade_animation;
|
||||||
|
|
||||||
|
std::shared_ptr<rpcn::rpcn_client> m_rpcn;
|
||||||
|
rpcn::friend_data m_friend_data;
|
||||||
|
atomic_t<bool> m_list_dirty { true };
|
||||||
|
atomic_t<friends_list_dialog_page> m_current_page { friends_list_dialog_page::friends };
|
||||||
|
atomic_t<friends_list_dialog_page> m_last_page { friends_list_dialog_page::friends };
|
||||||
|
|
||||||
|
void reload();
|
||||||
|
|
||||||
|
public:
|
||||||
|
friends_list_dialog();
|
||||||
|
|
||||||
|
void update(u64 timestamp_us) override;
|
||||||
|
void on_button_pressed(pad_button button_press, bool is_auto_repeat) override;
|
||||||
|
|
||||||
|
compiled_resource get_compiled() override;
|
||||||
|
|
||||||
|
error_code show(bool enable_overlay, std::function<void(s32 status)> on_close);
|
||||||
|
|
||||||
|
void callback_handler(rpcn::NotificationType ntype, const std::string& username, bool status);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "overlay_home_menu_main_menu.h"
|
#include "overlay_home_menu_main_menu.h"
|
||||||
#include "overlay_home_menu_components.h"
|
#include "overlay_home_menu_components.h"
|
||||||
|
#include "Emu/RSX/Overlays/FriendsList/overlay_friends_list_dialog.h"
|
||||||
|
#include "Emu/RSX/Overlays/overlay_manager.h"
|
||||||
#include "Emu/System.h"
|
#include "Emu/System.h"
|
||||||
#include "Emu/system_config.h"
|
#include "Emu/system_config.h"
|
||||||
|
|
||||||
@ -31,6 +33,27 @@ namespace rsx
|
|||||||
|
|
||||||
add_page(std::make_shared<home_menu_settings>(x, y, width, height, use_separators, this));
|
add_page(std::make_shared<home_menu_settings>(x, y, width, height, use_separators, this));
|
||||||
|
|
||||||
|
std::unique_ptr<overlay_element> friends = std::make_unique<home_menu_entry>(get_localized_string(localized_string_id::HOME_MENU_FRIENDS));
|
||||||
|
add_item(friends, [](pad_button btn) -> page_navigation
|
||||||
|
{
|
||||||
|
if (btn != pad_button::cross) return page_navigation::stay;
|
||||||
|
|
||||||
|
rsx_log.notice("User selected friends in home menu");
|
||||||
|
Emu.CallFromMainThread([]()
|
||||||
|
{
|
||||||
|
if (auto manager = g_fxo->try_get<rsx::overlays::display_manager>())
|
||||||
|
{
|
||||||
|
const error_code result = manager->create<rsx::overlays::friends_list_dialog>()->show(true, [](s32 status)
|
||||||
|
{
|
||||||
|
rsx_log.notice("Closing friends list with status %d", status);
|
||||||
|
});
|
||||||
|
|
||||||
|
(result ? rsx_log.error : rsx_log.notice)("Opened friends list with result %d", s32{result});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return page_navigation::stay;
|
||||||
|
});
|
||||||
|
|
||||||
std::unique_ptr<overlay_element> screenshot = std::make_unique<home_menu_entry>(get_localized_string(localized_string_id::HOME_MENU_SCREENSHOT));
|
std::unique_ptr<overlay_element> screenshot = std::make_unique<home_menu_entry>(get_localized_string(localized_string_id::HOME_MENU_SCREENSHOT));
|
||||||
add_item(screenshot, [](pad_button btn) -> page_navigation
|
add_item(screenshot, [](pad_button btn) -> page_navigation
|
||||||
{
|
{
|
||||||
|
@ -412,6 +412,7 @@ namespace rsx
|
|||||||
switch (ntype)
|
switch (ntype)
|
||||||
{
|
{
|
||||||
case rpcn::NotificationType::FriendQuery: // Other user sent a friend request
|
case rpcn::NotificationType::FriendQuery: // Other user sent a friend request
|
||||||
|
case rpcn::NotificationType::FriendPresenceChanged:
|
||||||
break;
|
break;
|
||||||
case rpcn::NotificationType::FriendNew: // Add a friend to the friendlist(either accepted a friend request or friend accepted it)
|
case rpcn::NotificationType::FriendNew: // Add a friend to the friendlist(either accepted a friend request or friend accepted it)
|
||||||
{
|
{
|
||||||
|
@ -648,8 +648,8 @@ namespace rsx
|
|||||||
|
|
||||||
void layout_container::set_pos(s16 _x, s16 _y)
|
void layout_container::set_pos(s16 _x, s16 _y)
|
||||||
{
|
{
|
||||||
s16 dx = _x - x;
|
const s16 dx = _x - x;
|
||||||
s16 dy = _y - y;
|
const s16 dy = _y - y;
|
||||||
translate(dx, dy);
|
translate(dx, dy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,6 +180,22 @@ enum class localized_string_id
|
|||||||
HOME_MENU_EXIT_GAME,
|
HOME_MENU_EXIT_GAME,
|
||||||
HOME_MENU_RESTART,
|
HOME_MENU_RESTART,
|
||||||
HOME_MENU_RESUME,
|
HOME_MENU_RESUME,
|
||||||
|
HOME_MENU_FRIENDS,
|
||||||
|
HOME_MENU_FRIENDS_REQUESTS,
|
||||||
|
HOME_MENU_FRIENDS_BLOCKED,
|
||||||
|
HOME_MENU_FRIENDS_STATUS_ONLINE,
|
||||||
|
HOME_MENU_FRIENDS_STATUS_OFFLINE,
|
||||||
|
HOME_MENU_FRIENDS_STATUS_BLOCKED,
|
||||||
|
HOME_MENU_FRIENDS_REQUEST_SENT,
|
||||||
|
HOME_MENU_FRIENDS_REQUEST_RECEIVED,
|
||||||
|
HOME_MENU_FRIENDS_BLOCK_USER_MSG,
|
||||||
|
HOME_MENU_FRIENDS_UNBLOCK_USER_MSG,
|
||||||
|
HOME_MENU_FRIENDS_REMOVE_USER_MSG,
|
||||||
|
HOME_MENU_FRIENDS_ACCEPT_REQUEST_MSG,
|
||||||
|
HOME_MENU_FRIENDS_CANCEL_REQUEST_MSG,
|
||||||
|
HOME_MENU_FRIENDS_REJECT_REQUEST_MSG,
|
||||||
|
HOME_MENU_FRIENDS_REJECT_REQUEST,
|
||||||
|
HOME_MENU_FRIENDS_NEXT_LIST,
|
||||||
HOME_MENU_SETTINGS,
|
HOME_MENU_SETTINGS,
|
||||||
HOME_MENU_SETTINGS_SAVE,
|
HOME_MENU_SETTINGS_SAVE,
|
||||||
HOME_MENU_SETTINGS_SAVE_BUTTON,
|
HOME_MENU_SETTINGS_SAVE_BUTTON,
|
||||||
|
@ -112,6 +112,7 @@
|
|||||||
<ClCompile Include="Emu\RSX\NV47\HW\nv308a.cpp" />
|
<ClCompile Include="Emu\RSX\NV47\HW\nv308a.cpp" />
|
||||||
<ClCompile Include="Emu\RSX\NV47\HW\nv406e.cpp" />
|
<ClCompile Include="Emu\RSX\NV47\HW\nv406e.cpp" />
|
||||||
<ClCompile Include="Emu\RSX\NV47\HW\nv4097.cpp" />
|
<ClCompile Include="Emu\RSX\NV47\HW\nv4097.cpp" />
|
||||||
|
<ClCompile Include="Emu\RSX\Overlays\FriendsList\overlay_friends_list_dialog.cpp" />
|
||||||
<ClCompile Include="Emu\RSX\Overlays\HomeMenu\overlay_home_menu.cpp" />
|
<ClCompile Include="Emu\RSX\Overlays\HomeMenu\overlay_home_menu.cpp" />
|
||||||
<ClCompile Include="Emu\RSX\Overlays\HomeMenu\overlay_home_menu_components.cpp" />
|
<ClCompile Include="Emu\RSX\Overlays\HomeMenu\overlay_home_menu_components.cpp" />
|
||||||
<ClCompile Include="Emu\RSX\Overlays\HomeMenu\overlay_home_menu_message_box.cpp" />
|
<ClCompile Include="Emu\RSX\Overlays\HomeMenu\overlay_home_menu_message_box.cpp" />
|
||||||
@ -631,6 +632,7 @@
|
|||||||
<ClInclude Include="Emu\RSX\NV47\HW\nv47.h" />
|
<ClInclude Include="Emu\RSX\NV47\HW\nv47.h" />
|
||||||
<ClInclude Include="Emu\RSX\NV47\HW\common.h" />
|
<ClInclude Include="Emu\RSX\NV47\HW\common.h" />
|
||||||
<ClInclude Include="Emu\RSX\NV47\HW\nv47_sync.hpp" />
|
<ClInclude Include="Emu\RSX\NV47\HW\nv47_sync.hpp" />
|
||||||
|
<ClInclude Include="Emu\RSX\Overlays\FriendsList\overlay_friends_list_dialog.h" />
|
||||||
<ClInclude Include="Emu\RSX\Overlays\HomeMenu\overlay_home_menu.h" />
|
<ClInclude Include="Emu\RSX\Overlays\HomeMenu\overlay_home_menu.h" />
|
||||||
<ClInclude Include="Emu\RSX\Overlays\HomeMenu\overlay_home_menu_components.h" />
|
<ClInclude Include="Emu\RSX\Overlays\HomeMenu\overlay_home_menu_components.h" />
|
||||||
<ClInclude Include="Emu\RSX\Overlays\HomeMenu\overlay_home_menu_message_box.h" />
|
<ClInclude Include="Emu\RSX\Overlays\HomeMenu\overlay_home_menu_message_box.h" />
|
||||||
|
@ -112,6 +112,9 @@
|
|||||||
<Filter Include="Emu\CPU\Backends\AArch64">
|
<Filter Include="Emu\CPU\Backends\AArch64">
|
||||||
<UniqueIdentifier>{73650043-acf8-4890-9f84-5bfa7a8c946b}</UniqueIdentifier>
|
<UniqueIdentifier>{73650043-acf8-4890-9f84-5bfa7a8c946b}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="Emu\GPU\RSX\Overlays\FriendsList">
|
||||||
|
<UniqueIdentifier>{a9d2ff9f-b5cd-4fd4-afca-424e876aa656}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
<Filter Include="Emu\GPU\RSX\Decoders">
|
<Filter Include="Emu\GPU\RSX\Decoders">
|
||||||
<UniqueIdentifier>{40f6640a-ed40-4096-b79b-995ae5be3052}</UniqueIdentifier>
|
<UniqueIdentifier>{40f6640a-ed40-4096-b79b-995ae5be3052}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
@ -1258,6 +1261,9 @@
|
|||||||
<ClCompile Include="Emu\NP\rpcn_countries.cpp">
|
<ClCompile Include="Emu\NP\rpcn_countries.cpp">
|
||||||
<Filter>Emu\NP</Filter>
|
<Filter>Emu\NP</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Emu\RSX\Overlays\FriendsList\overlay_friends_list_dialog.cpp">
|
||||||
|
<Filter>Emu\GPU\RSX\Overlays\FriendsList</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="Emu\RSX\RSXTexture.cpp">
|
<ClCompile Include="Emu\RSX\RSXTexture.cpp">
|
||||||
<Filter>Emu\GPU\RSX\Decoders</Filter>
|
<Filter>Emu\GPU\RSX\Decoders</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -2557,6 +2563,9 @@
|
|||||||
<ClInclude Include="Emu\Cell\Modules\cellSysutilAvc.h">
|
<ClInclude Include="Emu\Cell\Modules\cellSysutilAvc.h">
|
||||||
<Filter>Emu\Cell\Modules</Filter>
|
<Filter>Emu\Cell\Modules</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Emu\RSX\Overlays\FriendsList\overlay_friends_list_dialog.h">
|
||||||
|
<Filter>Emu\GPU\RSX\Overlays\FriendsList</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="Emu\RSX\RSXTexture.h">
|
<ClInclude Include="Emu\RSX\RSXTexture.h">
|
||||||
<Filter>Emu\GPU\RSX\Decoders</Filter>
|
<Filter>Emu\GPU\RSX\Decoders</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -129,6 +129,7 @@ EmuCallbacks main_application::CreateCallbacks()
|
|||||||
case keyboard_handler::basic:
|
case keyboard_handler::basic:
|
||||||
{
|
{
|
||||||
basic_keyboard_handler* ret = g_fxo->init<KeyboardHandlerBase, basic_keyboard_handler>(Emu.DeserialManager());
|
basic_keyboard_handler* ret = g_fxo->init<KeyboardHandlerBase, basic_keyboard_handler>(Emu.DeserialManager());
|
||||||
|
ensure(ret);
|
||||||
ret->moveToThread(get_thread());
|
ret->moveToThread(get_thread());
|
||||||
ret->SetTargetWindow(m_game_window);
|
ret->SetTargetWindow(m_game_window);
|
||||||
break;
|
break;
|
||||||
@ -165,6 +166,7 @@ EmuCallbacks main_application::CreateCallbacks()
|
|||||||
case mouse_handler::basic:
|
case mouse_handler::basic:
|
||||||
{
|
{
|
||||||
basic_mouse_handler* ret = g_fxo->init<MouseHandlerBase, basic_mouse_handler>(Emu.DeserialManager());
|
basic_mouse_handler* ret = g_fxo->init<MouseHandlerBase, basic_mouse_handler>(Emu.DeserialManager());
|
||||||
|
ensure(ret);
|
||||||
ret->moveToThread(get_thread());
|
ret->moveToThread(get_thread());
|
||||||
ret->SetTargetWindow(m_game_window);
|
ret->SetTargetWindow(m_game_window);
|
||||||
break;
|
break;
|
||||||
|
@ -200,6 +200,22 @@ private:
|
|||||||
case localized_string_id::HOME_MENU_TITLE: return tr("Home Menu");
|
case localized_string_id::HOME_MENU_TITLE: return tr("Home Menu");
|
||||||
case localized_string_id::HOME_MENU_EXIT_GAME: return tr("Exit Game");
|
case localized_string_id::HOME_MENU_EXIT_GAME: return tr("Exit Game");
|
||||||
case localized_string_id::HOME_MENU_RESUME: return tr("Resume Game");
|
case localized_string_id::HOME_MENU_RESUME: return tr("Resume Game");
|
||||||
|
case localized_string_id::HOME_MENU_FRIENDS: return tr("Friends");
|
||||||
|
case localized_string_id::HOME_MENU_FRIENDS_REQUESTS: return tr("Pending Friend Requests");
|
||||||
|
case localized_string_id::HOME_MENU_FRIENDS_BLOCKED: return tr("Blocked Users");
|
||||||
|
case localized_string_id::HOME_MENU_FRIENDS_STATUS_ONLINE: return tr("Online");
|
||||||
|
case localized_string_id::HOME_MENU_FRIENDS_STATUS_OFFLINE: return tr("Offline");
|
||||||
|
case localized_string_id::HOME_MENU_FRIENDS_STATUS_BLOCKED: return tr("Blocked");
|
||||||
|
case localized_string_id::HOME_MENU_FRIENDS_REQUEST_SENT: return tr("You sent a friend request");
|
||||||
|
case localized_string_id::HOME_MENU_FRIENDS_REQUEST_RECEIVED: return tr("Sent you a friend request");
|
||||||
|
case localized_string_id::HOME_MENU_FRIENDS_BLOCK_USER_MSG: return tr("Block this user?\n\n%0").arg(std::forward<Args>(args)...);
|
||||||
|
case localized_string_id::HOME_MENU_FRIENDS_UNBLOCK_USER_MSG: return tr("Unblock this user?\n\n%0").arg(std::forward<Args>(args)...);
|
||||||
|
case localized_string_id::HOME_MENU_FRIENDS_REMOVE_USER_MSG: return tr("Remove this user?\n\n%0").arg(std::forward<Args>(args)...);
|
||||||
|
case localized_string_id::HOME_MENU_FRIENDS_ACCEPT_REQUEST_MSG: return tr("Accept Request?\n\n%0").arg(std::forward<Args>(args)...);
|
||||||
|
case localized_string_id::HOME_MENU_FRIENDS_CANCEL_REQUEST_MSG: return tr("Cancel Request?\n\n%0").arg(std::forward<Args>(args)...);
|
||||||
|
case localized_string_id::HOME_MENU_FRIENDS_REJECT_REQUEST_MSG: return tr("Reject Request?\n\n%0").arg(std::forward<Args>(args)...);
|
||||||
|
case localized_string_id::HOME_MENU_FRIENDS_REJECT_REQUEST: return tr("Reject Request");
|
||||||
|
case localized_string_id::HOME_MENU_FRIENDS_NEXT_LIST: return tr("Next list");
|
||||||
case localized_string_id::HOME_MENU_RESTART: return tr("Restart Game");
|
case localized_string_id::HOME_MENU_RESTART: return tr("Restart Game");
|
||||||
case localized_string_id::HOME_MENU_SETTINGS: return tr("Settings");
|
case localized_string_id::HOME_MENU_SETTINGS: return tr("Settings");
|
||||||
case localized_string_id::HOME_MENU_SETTINGS_SAVE: return tr("Save custom configuration?");
|
case localized_string_id::HOME_MENU_SETTINGS_SAVE: return tr("Save custom configuration?");
|
||||||
|
@ -1054,9 +1054,9 @@ rpcn_friends_dialog::rpcn_friends_dialog(QWidget* parent)
|
|||||||
rpcn::friend_data data;
|
rpcn::friend_data data;
|
||||||
m_rpcn->get_friends_and_register_cb(data, friend_callback, this);
|
m_rpcn->get_friends_and_register_cb(data, friend_callback, this);
|
||||||
|
|
||||||
for (const auto& fr : data.friends)
|
for (const auto& [username, data] : data.friends)
|
||||||
{
|
{
|
||||||
add_update_list(m_lst_friends, QString::fromStdString(fr.first), fr.second.online ? m_icon_online : m_icon_offline, fr.second.online);
|
add_update_list(m_lst_friends, QString::fromStdString(username), data.online ? m_icon_online : m_icon_offline, data.online);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& fr_req : data.requests_sent)
|
for (const auto& fr_req : data.requests_sent)
|
||||||
@ -1297,27 +1297,27 @@ void rpcn_friends_dialog::remove_list(QListWidget* list, const QString& name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpcn_friends_dialog::add_update_friend(QString name, bool status)
|
void rpcn_friends_dialog::add_update_friend(const QString& name, bool status)
|
||||||
{
|
{
|
||||||
add_update_list(m_lst_friends, name, status ? m_icon_online : m_icon_offline, status);
|
add_update_list(m_lst_friends, name, status ? m_icon_online : m_icon_offline, status);
|
||||||
remove_list(m_lst_requests, name);
|
remove_list(m_lst_requests, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpcn_friends_dialog::remove_friend(QString name)
|
void rpcn_friends_dialog::remove_friend(const QString& name)
|
||||||
{
|
{
|
||||||
remove_list(m_lst_friends, name);
|
remove_list(m_lst_friends, name);
|
||||||
remove_list(m_lst_requests, name);
|
remove_list(m_lst_requests, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpcn_friends_dialog::add_query(QString name)
|
void rpcn_friends_dialog::add_query(const QString& name)
|
||||||
{
|
{
|
||||||
add_update_list(m_lst_requests, name, m_icon_request_received, QVariant(true));
|
add_update_list(m_lst_requests, name, m_icon_request_received, QVariant(true));
|
||||||
remove_list(m_lst_history, name);
|
remove_list(m_lst_history, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpcn_friends_dialog::callback_handler(rpcn::NotificationType ntype, std::string username, bool status)
|
void rpcn_friends_dialog::callback_handler(rpcn::NotificationType ntype, const std::string& username, bool status)
|
||||||
{
|
{
|
||||||
QString qtr_username = QString::fromStdString(username);
|
const QString qtr_username = QString::fromStdString(username);
|
||||||
switch (ntype)
|
switch (ntype)
|
||||||
{
|
{
|
||||||
case rpcn::NotificationType::FriendQuery: // Other user sent a friend request
|
case rpcn::NotificationType::FriendQuery: // Other user sent a friend request
|
||||||
@ -1340,6 +1340,10 @@ void rpcn_friends_dialog::callback_handler(rpcn::NotificationType ntype, std::st
|
|||||||
Q_EMIT signal_add_update_friend(qtr_username, status);
|
Q_EMIT signal_add_update_friend(qtr_username, status);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case rpcn::NotificationType::FriendPresenceChanged:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
rpcn_settings_log.fatal("An unhandled notification type was received by the RPCN friends dialog callback!");
|
rpcn_settings_log.fatal("An unhandled notification type was received by the RPCN friends dialog callback!");
|
||||||
|
@ -106,7 +106,7 @@ class rpcn_friends_dialog : public QDialog
|
|||||||
public:
|
public:
|
||||||
rpcn_friends_dialog(QWidget* parent = nullptr);
|
rpcn_friends_dialog(QWidget* parent = nullptr);
|
||||||
~rpcn_friends_dialog();
|
~rpcn_friends_dialog();
|
||||||
void callback_handler(rpcn::NotificationType ntype, std::string username, bool status);
|
void callback_handler(rpcn::NotificationType ntype, const std::string& username, bool status);
|
||||||
bool is_ok() const;
|
bool is_ok() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -114,14 +114,14 @@ private:
|
|||||||
void remove_list(QListWidget* list, const QString& name);
|
void remove_list(QListWidget* list, const QString& name);
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void add_update_friend(QString name, bool status);
|
void add_update_friend(const QString& name, bool status);
|
||||||
void remove_friend(QString name);
|
void remove_friend(const QString& name);
|
||||||
void add_query(QString name);
|
void add_query(const QString& name);
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void signal_add_update_friend(QString name, bool status);
|
void signal_add_update_friend(const QString& name, bool status);
|
||||||
void signal_remove_friend(QString name);
|
void signal_remove_friend(const QString& name);
|
||||||
void signal_add_query(QString name);
|
void signal_add_query(const QString& name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QIcon m_icon_online;
|
QIcon m_icon_online;
|
||||||
|
@ -161,6 +161,7 @@ void sendmessage_dialog_frame::callback_handler(u16 ntype, const std::string& us
|
|||||||
switch (ntype)
|
switch (ntype)
|
||||||
{
|
{
|
||||||
case rpcn::NotificationType::FriendQuery: // Other user sent a friend request
|
case rpcn::NotificationType::FriendQuery: // Other user sent a friend request
|
||||||
|
case rpcn::NotificationType::FriendPresenceChanged:
|
||||||
break;
|
break;
|
||||||
case rpcn::NotificationType::FriendNew: // Add a friend to the friendlist(either accepted a friend request or friend accepted it)
|
case rpcn::NotificationType::FriendNew: // Add a friend to the friendlist(either accepted a friend request or friend accepted it)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user