mirror of
https://gitlab.com/Mr_Goldberg/goldberg_emulator
synced 2025-07-05 03:29:05 +08:00
Overlay: Implement achievement icon display.
Display achievement icons in steam_overlay, and during achievement notifications. Add total achievement counts and progress bar to steam_overlay. Add new global settings for displaying unearned hidden achievements in the achievement list and displaying achievement descriptions in unlock notifications. (Both disabled by default.)
This commit is contained in:
parent
59b8354f2d
commit
5241fc892f
@ -334,10 +334,25 @@ uint32 create_localstorage_settings(Settings **settings_client_out, Settings **s
|
|||||||
bool disable_networking = false;
|
bool disable_networking = false;
|
||||||
bool disable_overlay = false;
|
bool disable_overlay = false;
|
||||||
bool disable_lobby_creation = false;
|
bool disable_lobby_creation = false;
|
||||||
|
bool enable_achievement_desc_on_unlock = false;
|
||||||
|
bool enable_displaying_hidden_achievements = false;
|
||||||
int build_id = 10;
|
int build_id = 10;
|
||||||
|
|
||||||
bool warn_forced = false;
|
bool warn_forced = false;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::string steam_settings_path = local_storage->get_global_settings_path();
|
||||||
|
|
||||||
|
std::vector<std::string> paths = local_storage->get_filenames_path(steam_settings_path);
|
||||||
|
for (auto & p: paths) {
|
||||||
|
if (p == "enable_achievement_desc_on_unlock.txt") {
|
||||||
|
enable_achievement_desc_on_unlock = true;
|
||||||
|
} else if (p == "enable_displaying_hidden_achievements.txt") {
|
||||||
|
enable_displaying_hidden_achievements = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
std::string steam_settings_path = Local_Storage::get_game_settings_path();
|
std::string steam_settings_path = Local_Storage::get_game_settings_path();
|
||||||
|
|
||||||
@ -352,6 +367,10 @@ uint32 create_localstorage_settings(Settings **settings_client_out, Settings **s
|
|||||||
disable_overlay = true;
|
disable_overlay = true;
|
||||||
} else if (p == "disable_lobby_creation.txt") {
|
} else if (p == "disable_lobby_creation.txt") {
|
||||||
disable_lobby_creation = true;
|
disable_lobby_creation = true;
|
||||||
|
} else if (p == "enable_achievement_desc_on_unlock.txt") {
|
||||||
|
enable_achievement_desc_on_unlock = true;
|
||||||
|
} else if (p == "enable_displaying_hidden_achievements.txt") {
|
||||||
|
enable_displaying_hidden_achievements = true;
|
||||||
} else if (p == "force_language.txt") {
|
} else if (p == "force_language.txt") {
|
||||||
int len = Local_Storage::get_file_data(steam_settings_path + "force_language.txt", language, sizeof(language) - 1);
|
int len = Local_Storage::get_file_data(steam_settings_path + "force_language.txt", language, sizeof(language) - 1);
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
@ -410,6 +429,10 @@ uint32 create_localstorage_settings(Settings **settings_client_out, Settings **s
|
|||||||
settings_server->warn_local_save = local_save;
|
settings_server->warn_local_save = local_save;
|
||||||
settings_client->supported_languages = supported_languages;
|
settings_client->supported_languages = supported_languages;
|
||||||
settings_server->supported_languages = supported_languages;
|
settings_server->supported_languages = supported_languages;
|
||||||
|
settings_client->set_show_achievement_desc_on_unlock(enable_achievement_desc_on_unlock);
|
||||||
|
settings_server->set_show_achievement_desc_on_unlock(enable_achievement_desc_on_unlock);
|
||||||
|
settings_client->set_show_achievement_hidden_unearned(enable_displaying_hidden_achievements);
|
||||||
|
settings_server->set_show_achievement_hidden_unearned(enable_displaying_hidden_achievements);
|
||||||
|
|
||||||
{
|
{
|
||||||
std::string dlc_config_path = Local_Storage::get_game_settings_path() + "DLC.txt";
|
std::string dlc_config_path = Local_Storage::get_game_settings_path() + "DLC.txt";
|
||||||
@ -666,8 +689,31 @@ uint32 create_localstorage_settings(Settings **settings_client_out, Settings **s
|
|||||||
return appid;
|
return appid;
|
||||||
}
|
}
|
||||||
|
|
||||||
void save_global_settings(Local_Storage *local_storage, char *name, char *language)
|
void save_global_settings(Local_Storage *local_storage, Settings * client_settings)
|
||||||
{
|
{
|
||||||
local_storage->store_data_settings("account_name.txt", name, strlen(name));
|
if ((local_storage != nullptr) && (client_settings != nullptr)) {
|
||||||
local_storage->store_data_settings("language.txt", language, strlen(language));
|
std::string name = client_settings->get_local_name();
|
||||||
|
std::string language = client_settings->get_language();
|
||||||
|
|
||||||
|
local_storage->store_data_settings("account_name.txt", (char*)name.c_str(), name.length());
|
||||||
|
local_storage->store_data_settings("language.txt", (char*)language.c_str(), language.length());
|
||||||
|
if (client_settings->get_show_achievement_desc_on_unlock()) {
|
||||||
|
if (local_storage->data_settings_exists("enable_achievement_desc_on_unlock.txt") != true) {
|
||||||
|
local_storage->store_data_settings("enable_achievement_desc_on_unlock.txt", " ", sizeof(" "));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (local_storage->data_settings_exists("enable_achievement_desc_on_unlock.txt") == true) {
|
||||||
|
local_storage->delete_data_settings("enable_achievement_desc_on_unlock.txt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (client_settings->get_show_achievement_hidden_unearned()) {
|
||||||
|
if (local_storage->data_settings_exists("enable_displaying_hidden_achievements.txt") != true) {
|
||||||
|
local_storage->store_data_settings("enable_displaying_hidden_achievements.txt", " ", sizeof(" "));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (local_storage->data_settings_exists("enable_displaying_hidden_achievements.txt") == true) {
|
||||||
|
local_storage->delete_data_settings("enable_displaying_hidden_achievements.txt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,6 @@
|
|||||||
|
|
||||||
//returns appid
|
//returns appid
|
||||||
uint32 create_localstorage_settings(Settings **settings_client_out, Settings **settings_server_out, Local_Storage **local_storage_out);
|
uint32 create_localstorage_settings(Settings **settings_client_out, Settings **settings_server_out, Local_Storage **local_storage_out);
|
||||||
void save_global_settings(Local_Storage *local_storage, char *name, char *language);
|
void save_global_settings(Local_Storage *local_storage, Settings *client_settings);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -100,6 +100,85 @@ int find_free_notification_id(std::vector<Notification> const& notifications)
|
|||||||
|
|
||||||
#include "notification.h"
|
#include "notification.h"
|
||||||
|
|
||||||
|
void Steam_Overlay::LoadAchievementImage(Overlay_Achievement & ach)
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("LoadAchievementImage() %s.\n", ach.name.c_str());
|
||||||
|
|
||||||
|
// Image load.
|
||||||
|
Steam_Utils* steamUtils = get_steam_client()->steam_utils;
|
||||||
|
Steam_User_Stats* steamUserStats = get_steam_client()->steam_user_stats;
|
||||||
|
int32 image_handle = steamUserStats->GetAchievementIcon(ach.name.c_str());
|
||||||
|
if (image_handle != 0) {
|
||||||
|
uint32 width = 0;
|
||||||
|
uint32 height = 0;
|
||||||
|
if ((steamUtils->GetImageSize(image_handle, &width, &height) == true) &&
|
||||||
|
(width > 0) && (height > 0)) {
|
||||||
|
|
||||||
|
PRINT_DEBUG("LoadAchievementImage() %d %d %d.\n", image_handle, width, height);
|
||||||
|
|
||||||
|
if (ach.raw_image != NULL) {
|
||||||
|
delete ach.raw_image;
|
||||||
|
ach.raw_image = NULL;
|
||||||
|
ach.raw_image_width = 0;
|
||||||
|
ach.raw_image_height = 0;
|
||||||
|
}
|
||||||
|
DestroyAchievementImageResource(ach);
|
||||||
|
|
||||||
|
uint8 * raw_image = new uint8[(width * height * sizeof(uint32))];
|
||||||
|
if ((raw_image != NULL) &&
|
||||||
|
(steamUtils->GetImageRGBA(image_handle,
|
||||||
|
raw_image,
|
||||||
|
(width * height * sizeof(uint32))) == true)) {
|
||||||
|
PRINT_DEBUG("LoadAchievementImage() %d -> %p.\n", image_handle, raw_image);
|
||||||
|
ach.raw_image = raw_image;
|
||||||
|
ach.raw_image_width = width;
|
||||||
|
ach.raw_image_height = height;
|
||||||
|
} else {
|
||||||
|
delete ach.raw_image;
|
||||||
|
PRINT_DEBUG("Image for achievement %s could not get pixel data.\n", ach.name.c_str());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PRINT_DEBUG("Image for achievement %s has an invalid size.\n", ach.name.c_str());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PRINT_DEBUG("Image for achievement %s is not loaded.\n", ach.name.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Steam_Overlay::CreateAchievementImageResource(Overlay_Achievement & ach)
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("CreateAchievementImageResource() %s. %d x %d -> %p\n", ach.name.c_str(), ach.raw_image_width, ach.raw_image_height, ach.raw_image);
|
||||||
|
|
||||||
|
if (_renderer) {
|
||||||
|
if (ach.raw_image != NULL && ach.raw_image_width > 0 && ach.raw_image_height > 0 && ach.image_resource.expired() == true) {
|
||||||
|
std::weak_ptr<uint64_t> test;
|
||||||
|
test = _renderer->CreateImageResource(ach.raw_image,
|
||||||
|
ach.raw_image_width,
|
||||||
|
ach.raw_image_height);
|
||||||
|
ach.image_resource = test;
|
||||||
|
std::shared_ptr<uint64_t> test2;
|
||||||
|
test2 = test.lock();
|
||||||
|
if (!test2) {
|
||||||
|
PRINT_DEBUG("CreateAchievementImageResource() Unable to create resource for %s.\n", ach.name.c_str());
|
||||||
|
} else {
|
||||||
|
PRINT_DEBUG("CreateAchievementImageResource() created resource for %s -> %PRIu64.\n", ach.name.c_str(), *test2);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
PRINT_DEBUG("CreateAchievementImageResource() invalid raw data for %s.\n", ach.name.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Steam_Overlay::DestroyAchievementImageResource(Overlay_Achievement & ach)
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("DestroyAchievementImageResource() %s.\n", ach.name.c_str());
|
||||||
|
|
||||||
|
if (_renderer && ach.image_resource.expired() == false) {
|
||||||
|
_renderer->ReleaseImageResource(ach.image_resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Steam_Overlay::steam_overlay_run_every_runcb(void* object)
|
void Steam_Overlay::steam_overlay_run_every_runcb(void* object)
|
||||||
{
|
{
|
||||||
Steam_Overlay* _this = reinterpret_cast<Steam_Overlay*>(object);
|
Steam_Overlay* _this = reinterpret_cast<Steam_Overlay*>(object);
|
||||||
@ -129,10 +208,14 @@ Steam_Overlay::Steam_Overlay(Settings* settings, SteamCallResults* callback_resu
|
|||||||
show_achievements(false),
|
show_achievements(false),
|
||||||
show_settings(false),
|
show_settings(false),
|
||||||
_renderer(nullptr),
|
_renderer(nullptr),
|
||||||
fonts_atlas(nullptr)
|
fonts_atlas(nullptr),
|
||||||
|
earned_achievement_count(0)
|
||||||
{
|
{
|
||||||
strncpy(username_text, settings->get_local_name(), sizeof(username_text));
|
strncpy(username_text, settings->get_local_name(), sizeof(username_text));
|
||||||
|
|
||||||
|
show_achievement_desc_on_unlock = settings->get_show_achievement_desc_on_unlock();
|
||||||
|
show_achievement_hidden_unearned = settings->get_show_achievement_hidden_unearned();
|
||||||
|
|
||||||
if (settings->warn_forced) {
|
if (settings->warn_forced) {
|
||||||
this->disable_forced = true;
|
this->disable_forced = true;
|
||||||
this->warning_forced = true;
|
this->warning_forced = true;
|
||||||
@ -167,6 +250,17 @@ Steam_Overlay::Steam_Overlay(Settings* settings, SteamCallResults* callback_resu
|
|||||||
Steam_Overlay::~Steam_Overlay()
|
Steam_Overlay::~Steam_Overlay()
|
||||||
{
|
{
|
||||||
run_every_runcb->remove(&Steam_Overlay::steam_overlay_run_every_runcb, this);
|
run_every_runcb->remove(&Steam_Overlay::steam_overlay_run_every_runcb, this);
|
||||||
|
if (achievements.size()) {
|
||||||
|
for (auto & x : achievements) {
|
||||||
|
if (x.raw_image != NULL) {
|
||||||
|
delete x.raw_image;
|
||||||
|
x.raw_image = NULL;
|
||||||
|
x.raw_image_width = 0;
|
||||||
|
x.raw_image_height = 0;
|
||||||
|
}
|
||||||
|
DestroyAchievementImageResource(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Steam_Overlay::Ready() const
|
bool Steam_Overlay::Ready() const
|
||||||
@ -422,8 +516,28 @@ void Steam_Overlay::AddAchievementNotification(nlohmann::json const& ach)
|
|||||||
Notification notif;
|
Notification notif;
|
||||||
notif.id = id;
|
notif.id = id;
|
||||||
notif.type = notification_type_achievement;
|
notif.type = notification_type_achievement;
|
||||||
// Load achievement image
|
// Achievement image
|
||||||
notif.message = ach["displayName"].get<std::string>() + "\n" + ach["description"].get<std::string>();
|
if (achievements.size() > 0) {
|
||||||
|
for (auto & x : achievements) {
|
||||||
|
if (x.name == ach["name"].get<std::string>()) {
|
||||||
|
// Reload the image due to the pop.
|
||||||
|
LoadAchievementImage(x);
|
||||||
|
DestroyAchievementImageResource(x);
|
||||||
|
// Cannot call CreateAchievementImageResource(x) here. OpenGL displays bad texture.
|
||||||
|
notif.ach_name = x.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Achievement count.
|
||||||
|
if (total_achievement_count > earned_achievement_count) {
|
||||||
|
earned_achievement_count++;
|
||||||
|
}
|
||||||
|
notif.message = "Achievement Unlocked!\n";
|
||||||
|
if (show_achievement_desc_on_unlock) {
|
||||||
|
notif.message += ach["displayName"].get<std::string>() + "\n" + ach["description"].get<std::string>();
|
||||||
|
} else {
|
||||||
|
notif.message += "\n" + ach["displayName"].get<std::string>();
|
||||||
|
}
|
||||||
notif.start_time = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch());
|
notif.start_time = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch());
|
||||||
notifications.emplace_back(notif);
|
notifications.emplace_back(notif);
|
||||||
have_notifications = true;
|
have_notifications = true;
|
||||||
@ -636,46 +750,85 @@ void Steam_Overlay::BuildNotifications(int width, int height)
|
|||||||
|
|
||||||
std::queue<Friend> friend_actions_temp;
|
std::queue<Friend> friend_actions_temp;
|
||||||
|
|
||||||
|
ImVec2 notification_rez(((Notification::width >= 1.0f) ? (width / Notification::width) : (width * Notification::width)),
|
||||||
|
((Notification::height >= 1.0f) ? (height / Notification::height) : (height * Notification::height))); // calc notification screen size.
|
||||||
|
|
||||||
{
|
{
|
||||||
std::lock_guard<std::recursive_mutex> lock(notifications_mutex);
|
std::lock_guard<std::recursive_mutex> lock(notifications_mutex);
|
||||||
|
|
||||||
for (auto it = notifications.begin(); it != notifications.end(); ++it, ++i)
|
for (auto it = notifications.begin(); it != notifications.end(); ++it, ++i)
|
||||||
{
|
{
|
||||||
auto elapsed_notif = now - it->start_time;
|
auto elapsed_notif = now - it->start_time;
|
||||||
|
float alpha = 0;
|
||||||
|
ImGuiStyle currentStyle = ImGui::GetStyle();
|
||||||
if ( elapsed_notif < Notification::fade_in)
|
if ( elapsed_notif < Notification::fade_in)
|
||||||
{
|
{
|
||||||
float alpha = Notification::max_alpha * (elapsed_notif.count() / static_cast<float>(Notification::fade_in.count()));
|
alpha = Notification::max_alpha * (elapsed_notif.count() / static_cast<float>(Notification::fade_in.count()));
|
||||||
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, alpha));
|
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, alpha));
|
||||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(Notification::r, Notification::g, Notification::b, alpha));
|
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(Notification::r, Notification::g, Notification::b, alpha));
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(255, 255, 255, alpha*2));
|
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(255, 255, 255, alpha*2));
|
||||||
}
|
}
|
||||||
else if ( elapsed_notif > Notification::fade_out_start)
|
else if ( elapsed_notif > Notification::fade_out_start)
|
||||||
{
|
{
|
||||||
float alpha = Notification::max_alpha * ((Notification::show_time - elapsed_notif).count() / static_cast<float>(Notification::fade_out.count()));
|
alpha = Notification::max_alpha * ((Notification::show_time - elapsed_notif).count() / static_cast<float>(Notification::fade_out.count()));
|
||||||
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, alpha));
|
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, alpha));
|
||||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(Notification::r, Notification::g, Notification::b, alpha));
|
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(Notification::r, Notification::g, Notification::b, alpha));
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(255, 255, 255, alpha*2));
|
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(255, 255, 255, alpha*2));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
alpha = Notification::max_alpha;
|
||||||
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, Notification::max_alpha));
|
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, Notification::max_alpha));
|
||||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(Notification::r, Notification::g, Notification::b, Notification::max_alpha));
|
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(Notification::r, Notification::g, Notification::b, Notification::max_alpha));
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(255, 255, 255, Notification::max_alpha*2));
|
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(255, 255, 255, Notification::max_alpha*2));
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::SetNextWindowPos(ImVec2((float)width - width * Notification::width, Notification::height * font_size * i ));
|
ImGui::SetNextWindowPos(ImVec2((float)width - width * Notification::width, Notification::height * font_size * i ));
|
||||||
ImGui::SetNextWindowSize(ImVec2( width * Notification::width, Notification::height * font_size ));
|
ImGui::SetNextWindowSize(ImVec2( width * Notification::width, Notification::height * font_size ));
|
||||||
ImGui::Begin(std::to_string(it->id).c_str(), nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBringToFrontOnFocus |
|
ImGui::Begin(std::to_string(it->id).c_str(), nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBringToFrontOnFocus |
|
||||||
ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoDecoration);
|
ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoDecoration);
|
||||||
|
|
||||||
|
// Notification image.
|
||||||
|
ImVec4 image_color_multipler(1, 1, 1, (alpha*2)); // fade in / out.
|
||||||
|
ImVec2 image_offset(((notification_rez.x * 0.04f) + currentStyle.FramePadding.x), ((notification_rez.y * 0.04f) + currentStyle.FramePadding.y)); // calc border.
|
||||||
|
ImVec2 image_max_resolution((notification_rez.x - image_offset.x), (notification_rez.y - image_offset.y)); // calc total space for image.
|
||||||
|
if (image_max_resolution.x > image_max_resolution.y) { // fix image aspect ratio. (square)
|
||||||
|
image_max_resolution.x = image_max_resolution.x - (image_max_resolution.x - image_max_resolution.y);
|
||||||
|
} else {
|
||||||
|
image_max_resolution.y = image_max_resolution.y - (image_max_resolution.y - image_max_resolution.x);
|
||||||
|
}
|
||||||
|
ImVec2 text_offset(image_offset.x, image_offset.y);
|
||||||
|
ImGui::SetCursorPos(image_offset);
|
||||||
|
|
||||||
switch (it->type)
|
switch (it->type)
|
||||||
{
|
{
|
||||||
case notification_type_achievement:
|
case notification_type_achievement:
|
||||||
|
for (auto &a : achievements) {
|
||||||
|
if (a.name == it->ach_name) {
|
||||||
|
CreateAchievementImageResource(a);
|
||||||
|
if ((a.image_resource.expired() == false) &&
|
||||||
|
(a.raw_image_width > 0) &&
|
||||||
|
(a.raw_image_height > 0)) {
|
||||||
|
ImVec2 image_scale(image_max_resolution.x * 0.4f,
|
||||||
|
image_max_resolution.y * 0.4f);
|
||||||
|
|
||||||
|
// Fix text offset.
|
||||||
|
text_offset.x = image_offset.x + currentStyle.ItemSpacing.x + image_scale.x;
|
||||||
|
|
||||||
|
std::shared_ptr<uint64_t> s_ptr = a.image_resource.lock();
|
||||||
|
ImGui::Image((ImTextureID)(intptr_t)*s_ptr, image_scale, ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f), image_color_multipler);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::SetCursorPos(text_offset);
|
||||||
|
ImGui::PushTextWrapPos(0.0f);
|
||||||
ImGui::TextWrapped("%s", it->message.c_str());
|
ImGui::TextWrapped("%s", it->message.c_str());
|
||||||
|
ImGui::PopTextWrapPos();
|
||||||
break;
|
break;
|
||||||
case notification_type_invite:
|
case notification_type_invite:
|
||||||
{
|
{
|
||||||
|
ImGui::SetCursorPos(text_offset);
|
||||||
ImGui::TextWrapped("%s", it->message.c_str());
|
ImGui::TextWrapped("%s", it->message.c_str());
|
||||||
if (ImGui::Button("Join"))
|
if (ImGui::Button("Join"))
|
||||||
{
|
{
|
||||||
@ -686,6 +839,7 @@ void Steam_Overlay::BuildNotifications(int width, int height)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case notification_type_message:
|
case notification_type_message:
|
||||||
|
ImGui::SetCursorPos(text_offset);
|
||||||
ImGui::TextWrapped("%s", it->message.c_str()); break;
|
ImGui::TextWrapped("%s", it->message.c_str()); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -771,6 +925,17 @@ void Steam_Overlay::CreateFonts()
|
|||||||
reset_LastError();
|
reset_LastError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Steam_Overlay::DestroyAchievementImageResources()
|
||||||
|
{
|
||||||
|
for (auto & x : achievements) {
|
||||||
|
if (x.image_resource.expired()) {
|
||||||
|
DestroyAchievementImageResource(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Try to make this function as short as possible or it might affect game's fps.
|
// Try to make this function as short as possible or it might affect game's fps.
|
||||||
void Steam_Overlay::OverlayProc()
|
void Steam_Overlay::OverlayProc()
|
||||||
{
|
{
|
||||||
@ -809,6 +974,10 @@ void Steam_Overlay::OverlayProc()
|
|||||||
|
|
||||||
ImGui::LabelText("##label", "Renderer: %s", (_renderer == nullptr ? "Unknown" : _renderer->GetLibraryName().c_str()));
|
ImGui::LabelText("##label", "Renderer: %s", (_renderer == nullptr ? "Unknown" : _renderer->GetLibraryName().c_str()));
|
||||||
|
|
||||||
|
ImGui::Text("Achievements earned: %d / %d", earned_achievement_count, total_achievement_count);
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::ProgressBar((earned_achievement_count / total_achievement_count), ImVec2((io.DisplaySize.x * 0.20f),0));
|
||||||
|
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
if (ImGui::Button("Show Achievements")) {
|
if (ImGui::Button("Show Achievements")) {
|
||||||
show_achievements = true;
|
show_achievements = true;
|
||||||
@ -854,28 +1023,66 @@ void Steam_Overlay::OverlayProc()
|
|||||||
if (ImGui::Begin("Achievement Window", &show)) {
|
if (ImGui::Begin("Achievement Window", &show)) {
|
||||||
ImGui::Text("List of achievements");
|
ImGui::Text("List of achievements");
|
||||||
ImGui::BeginChild("Achievements");
|
ImGui::BeginChild("Achievements");
|
||||||
|
ImGuiStyle currentStyle = ImGui::GetStyle();
|
||||||
|
float window_x_offset = (ImGui::GetWindowWidth() > currentStyle.ScrollbarSize) ? (ImGui::GetWindowWidth() - currentStyle.ScrollbarSize) : 0;
|
||||||
for (auto & x : achievements) {
|
for (auto & x : achievements) {
|
||||||
bool achieved = x.achieved;
|
bool achieved = x.achieved;
|
||||||
bool hidden = x.hidden && !achieved;
|
bool hidden = x.hidden && !achieved;
|
||||||
|
|
||||||
ImGui::Separator();
|
if (!hidden || show_achievement_hidden_unearned) {
|
||||||
ImGui::Text("%s", x.title.c_str());
|
|
||||||
if (hidden) {
|
|
||||||
ImGui::Text("hidden achievement");
|
|
||||||
} else {
|
|
||||||
ImGui::TextWrapped("%s", x.description.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (achieved) {
|
if (x.raw_image == NULL) {
|
||||||
char buffer[80] = {};
|
LoadAchievementImage(x);
|
||||||
time_t unlock_time = (time_t)x.unlock_time;
|
}
|
||||||
std::strftime(buffer, 80, "%Y-%m-%d at %H:%M:%S", std::localtime(&unlock_time));
|
|
||||||
|
|
||||||
ImGui::TextColored(ImVec4(0, 255, 0, 255), "achieved on %s", buffer);
|
if (x.image_resource.expired() == true) {
|
||||||
} else {
|
CreateAchievementImageResource(x);
|
||||||
ImGui::TextColored(ImVec4(255, 0, 0, 255), "not achieved");
|
}
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
// Anchor the image to the right side of the list.
|
||||||
|
ImVec2 target = ImGui::GetCursorPos();
|
||||||
|
target.x = window_x_offset;
|
||||||
|
if (target.x > (x.raw_image_width * 0.4f)) {
|
||||||
|
target.x = target.x - (x.raw_image_width * 0.4f);
|
||||||
|
} else {
|
||||||
|
target.x = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::PushTextWrapPos(target.x);
|
||||||
|
ImGui::Text("%s", x.title.c_str());
|
||||||
|
if (hidden) {
|
||||||
|
ImGui::Text("Hidden Achievement");
|
||||||
|
} else {
|
||||||
|
ImGui::Text("%s", x.description.c_str());
|
||||||
|
}
|
||||||
|
ImGui::PopTextWrapPos();
|
||||||
|
|
||||||
|
if (achieved) {
|
||||||
|
char buffer[80] = {};
|
||||||
|
time_t unlock_time = (time_t)x.unlock_time;
|
||||||
|
std::strftime(buffer, 80, "%Y-%m-%d at %H:%M:%S", std::localtime(&unlock_time));
|
||||||
|
|
||||||
|
ImGui::TextColored(ImVec4(0, 255, 0, 255), "achieved on %s", buffer);
|
||||||
|
} else {
|
||||||
|
ImGui::TextColored(ImVec4(255, 0, 0, 255), "not achieved");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set cursor for image output.
|
||||||
|
if (target.x != 0) {
|
||||||
|
ImGui::SetCursorPos(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((x.image_resource.expired() == false) &&
|
||||||
|
(x.raw_image_width > 0) &&
|
||||||
|
(x.raw_image_height > 0)) {
|
||||||
|
std::shared_ptr<uint64_t> s_ptr = x.image_resource.lock();
|
||||||
|
ImGui::Image((ImTextureID)(intptr_t)*s_ptr, ImVec2(x.raw_image_width * 0.4f, x.raw_image_height * 0.4f));
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
}
|
}
|
||||||
ImGui::Separator();
|
|
||||||
}
|
}
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
}
|
}
|
||||||
@ -905,6 +1112,11 @@ void Steam_Overlay::OverlayProc()
|
|||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
|
ImGui::Checkbox("Show achievement descriptions on unlock", &show_achievement_desc_on_unlock);
|
||||||
|
ImGui::Checkbox("Show unearned hidden achievements", &show_achievement_hidden_unearned);
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
if (!disable_forced) {
|
if (!disable_forced) {
|
||||||
ImGui::Text("You may have to restart the game for these to apply.");
|
ImGui::Text("You may have to restart the game for these to apply.");
|
||||||
if (ImGui::Button("Save")) {
|
if (ImGui::Button("Save")) {
|
||||||
@ -1004,15 +1216,16 @@ void Steam_Overlay::RunCallbacks()
|
|||||||
{
|
{
|
||||||
if (!achievements.size()) {
|
if (!achievements.size()) {
|
||||||
Steam_User_Stats* steamUserStats = get_steam_client()->steam_user_stats;
|
Steam_User_Stats* steamUserStats = get_steam_client()->steam_user_stats;
|
||||||
uint32 achievements_num = steamUserStats->GetNumAchievements();
|
total_achievement_count = steamUserStats->GetNumAchievements();
|
||||||
if (achievements_num) {
|
if (total_achievement_count) {
|
||||||
PRINT_DEBUG("POPULATE OVERLAY ACHIEVEMENTS\n");
|
PRINT_DEBUG("POPULATE OVERLAY ACHIEVEMENTS\n");
|
||||||
for (unsigned i = 0; i < achievements_num; ++i) {
|
for (unsigned i = 0; i < total_achievement_count; ++i) {
|
||||||
Overlay_Achievement ach;
|
Overlay_Achievement ach;
|
||||||
ach.name = steamUserStats->GetAchievementName(i);
|
ach.name = steamUserStats->GetAchievementName(i);
|
||||||
ach.title = steamUserStats->GetAchievementDisplayAttribute(ach.name.c_str(), "name");
|
ach.title = steamUserStats->GetAchievementDisplayAttribute(ach.name.c_str(), "name");
|
||||||
ach.description = steamUserStats->GetAchievementDisplayAttribute(ach.name.c_str(), "desc");
|
ach.description = steamUserStats->GetAchievementDisplayAttribute(ach.name.c_str(), "desc");
|
||||||
const char *hidden = steamUserStats->GetAchievementDisplayAttribute(ach.name.c_str(), "hidden");
|
const char *hidden = steamUserStats->GetAchievementDisplayAttribute(ach.name.c_str(), "hidden");
|
||||||
|
|
||||||
if (strlen(hidden) && hidden[0] == '1') {
|
if (strlen(hidden) && hidden[0] == '1') {
|
||||||
ach.hidden = true;
|
ach.hidden = true;
|
||||||
} else {
|
} else {
|
||||||
@ -1024,11 +1237,19 @@ void Steam_Overlay::RunCallbacks()
|
|||||||
if (steamUserStats->GetAchievementAndUnlockTime(ach.name.c_str(), &achieved, &unlock_time)) {
|
if (steamUserStats->GetAchievementAndUnlockTime(ach.name.c_str(), &achieved, &unlock_time)) {
|
||||||
ach.achieved = achieved;
|
ach.achieved = achieved;
|
||||||
ach.unlock_time = unlock_time;
|
ach.unlock_time = unlock_time;
|
||||||
|
if ((achieved == true) && (total_achievement_count > earned_achievement_count)) {
|
||||||
|
earned_achievement_count++;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ach.achieved = false;
|
ach.achieved = false;
|
||||||
ach.unlock_time = 0;
|
ach.unlock_time = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ach.raw_image = nullptr;
|
||||||
|
ach.raw_image_width = 0;
|
||||||
|
ach.raw_image_height = 0;
|
||||||
|
LoadAchievementImage(ach);
|
||||||
|
|
||||||
achievements.push_back(ach);
|
achievements.push_back(ach);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1062,7 +1283,7 @@ void Steam_Overlay::RunCallbacks()
|
|||||||
data.m_bUserInitiated = true;
|
data.m_bUserInitiated = true;
|
||||||
data.m_nAppID = settings->get_local_game_id().AppID();
|
data.m_nAppID = settings->get_local_game_id().AppID();
|
||||||
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
|
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
|
||||||
|
DestroyAchievementImageResources(); // Don't recreate them here. OpenGL won't display them if we do.
|
||||||
overlay_state_changed = false;
|
overlay_state_changed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1071,11 +1292,15 @@ void Steam_Overlay::RunCallbacks()
|
|||||||
|
|
||||||
if (save_settings) {
|
if (save_settings) {
|
||||||
char *language_text = valid_languages[current_language];
|
char *language_text = valid_languages[current_language];
|
||||||
save_global_settings(get_steam_client()->local_storage, username_text, language_text);
|
|
||||||
get_steam_client()->settings_client->set_local_name(username_text);
|
get_steam_client()->settings_client->set_local_name(username_text);
|
||||||
get_steam_client()->settings_server->set_local_name(username_text);
|
|
||||||
get_steam_client()->settings_client->set_language(language_text);
|
get_steam_client()->settings_client->set_language(language_text);
|
||||||
|
get_steam_client()->settings_client->set_show_achievement_desc_on_unlock(show_achievement_desc_on_unlock);
|
||||||
|
get_steam_client()->settings_client->set_show_achievement_hidden_unearned(show_achievement_hidden_unearned);
|
||||||
|
get_steam_client()->settings_server->set_local_name(username_text);
|
||||||
get_steam_client()->settings_server->set_language(language_text);
|
get_steam_client()->settings_server->set_language(language_text);
|
||||||
|
get_steam_client()->settings_server->set_show_achievement_desc_on_unlock(show_achievement_desc_on_unlock);
|
||||||
|
get_steam_client()->settings_server->set_show_achievement_hidden_unearned(show_achievement_hidden_unearned);
|
||||||
|
save_global_settings(get_steam_client()->local_storage, get_steam_client()->settings_client);
|
||||||
steamFriends->resend_friend_data();
|
steamFriends->resend_friend_data();
|
||||||
save_settings = false;
|
save_settings = false;
|
||||||
}
|
}
|
||||||
|
@ -68,6 +68,7 @@ struct Notification
|
|||||||
std::chrono::seconds start_time;
|
std::chrono::seconds start_time;
|
||||||
std::string message;
|
std::string message;
|
||||||
std::pair<const Friend, friend_window_state>* frd;
|
std::pair<const Friend, friend_window_state>* frd;
|
||||||
|
std::string ach_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Overlay_Achievement
|
struct Overlay_Achievement
|
||||||
@ -78,6 +79,10 @@ struct Overlay_Achievement
|
|||||||
bool hidden;
|
bool hidden;
|
||||||
bool achieved;
|
bool achieved;
|
||||||
uint32 unlock_time;
|
uint32 unlock_time;
|
||||||
|
uint8 * raw_image;
|
||||||
|
uint32 raw_image_width;
|
||||||
|
uint32 raw_image_height;
|
||||||
|
std::weak_ptr<uint64_t> image_resource;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef EMU_OVERLAY
|
#ifdef EMU_OVERLAY
|
||||||
@ -104,8 +109,8 @@ class Steam_Overlay
|
|||||||
bool show_achievements, show_settings;
|
bool show_achievements, show_settings;
|
||||||
void *fonts_atlas;
|
void *fonts_atlas;
|
||||||
|
|
||||||
bool disable_forced, local_save, warning_forced;
|
bool disable_forced, local_save, warning_forced, show_achievement_desc_on_unlock, show_achievement_hidden_unearned;
|
||||||
uint32_t appid;
|
uint32_t appid, total_achievement_count, earned_achievement_count;
|
||||||
|
|
||||||
char username_text[256];
|
char username_text[256];
|
||||||
std::atomic_bool save_settings;
|
std::atomic_bool save_settings;
|
||||||
@ -149,6 +154,12 @@ class Steam_Overlay
|
|||||||
void BuildFriendWindow(Friend const& frd, friend_window_state &state);
|
void BuildFriendWindow(Friend const& frd, friend_window_state &state);
|
||||||
// Notifications like achievements, chat and invitations
|
// Notifications like achievements, chat and invitations
|
||||||
void BuildNotifications(int width, int height);
|
void BuildNotifications(int width, int height);
|
||||||
|
|
||||||
|
void LoadAchievementImage(Overlay_Achievement & ach);
|
||||||
|
void CreateAchievementImageResource(Overlay_Achievement & ach);
|
||||||
|
void DestroyAchievementImageResource(Overlay_Achievement & ach);
|
||||||
|
void DestroyAchievementImageResources();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Steam_Overlay(Settings* settings, SteamCallResults* callback_results, SteamCallBacks* callbacks, RunEveryRunCB* run_every_runcb, Networking *network);
|
Steam_Overlay(Settings* settings, SteamCallResults* callback_results, SteamCallBacks* callbacks, RunEveryRunCB* run_every_runcb, Networking *network);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user