2019-08-01 04:21:02 +08:00
|
|
|
#ifndef __INCLUDED_STEAM_OVERLAY_H__
|
|
|
|
#define __INCLUDED_STEAM_OVERLAY_H__
|
2019-07-26 05:33:07 +08:00
|
|
|
|
2023-12-27 15:15:10 +08:00
|
|
|
#include "dll/base.h"
|
2019-08-02 17:16:30 +08:00
|
|
|
#include <map>
|
2019-08-02 19:02:20 +08:00
|
|
|
#include <queue>
|
2019-07-26 05:33:07 +08:00
|
|
|
|
2024-03-13 03:21:09 +08:00
|
|
|
#ifdef EMU_OVERLAY
|
|
|
|
|
|
|
|
#include <future>
|
|
|
|
#include <atomic>
|
|
|
|
#include <memory>
|
|
|
|
#include "InGameOverlay/RendererHook.h"
|
2024-06-04 18:39:38 +08:00
|
|
|
#include "InGameOverlay/ImGui/imgui.h"
|
2024-03-13 03:21:09 +08:00
|
|
|
|
2019-08-03 18:58:48 +08:00
|
|
|
static constexpr size_t max_chat_len = 768;
|
|
|
|
|
2019-08-02 19:02:20 +08:00
|
|
|
enum window_state
|
2019-08-01 04:21:02 +08:00
|
|
|
{
|
2019-08-17 00:31:56 +08:00
|
|
|
window_state_none = 0,
|
|
|
|
window_state_show = 1<<0,
|
|
|
|
window_state_invite = 1<<1,
|
|
|
|
window_state_join = 1<<2,
|
|
|
|
window_state_lobby_invite = 1<<3,
|
|
|
|
window_state_rich_invite = 1<<4,
|
|
|
|
window_state_send_message = 1<<5,
|
|
|
|
window_state_need_attention = 1<<6,
|
2024-04-25 09:17:36 +08:00
|
|
|
|
2019-08-01 04:21:02 +08:00
|
|
|
};
|
2019-07-26 05:33:07 +08:00
|
|
|
|
2019-08-02 19:02:20 +08:00
|
|
|
struct friend_window_state
|
2019-08-02 17:16:30 +08:00
|
|
|
{
|
2019-10-11 19:10:48 +08:00
|
|
|
int id;
|
2019-08-02 19:02:20 +08:00
|
|
|
uint8 window_state;
|
2019-10-14 22:35:36 +08:00
|
|
|
std::string window_title;
|
2019-08-03 18:58:48 +08:00
|
|
|
union // The invitation (if any)
|
2019-08-02 17:16:30 +08:00
|
|
|
{
|
|
|
|
uint64 lobbyId;
|
|
|
|
char connect[k_cchMaxRichPresenceValueLength];
|
|
|
|
};
|
2019-08-03 18:58:48 +08:00
|
|
|
std::string chat_history;
|
|
|
|
char chat_input[max_chat_len];
|
2020-01-26 22:46:57 +08:00
|
|
|
|
2020-02-03 08:07:30 +08:00
|
|
|
bool joinable;
|
2019-08-02 17:16:30 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct Friend_Less
|
|
|
|
{
|
|
|
|
bool operator()(const Friend& lhs, const Friend& rhs) const
|
|
|
|
{
|
|
|
|
return lhs.id() < rhs.id();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2024-04-25 09:17:36 +08:00
|
|
|
enum class notification_type
|
2019-11-08 22:52:38 +08:00
|
|
|
{
|
2024-06-20 10:57:30 +08:00
|
|
|
message,
|
2024-04-25 09:17:36 +08:00
|
|
|
invite,
|
|
|
|
achievement,
|
2024-06-07 02:07:15 +08:00
|
|
|
achievement_progress,
|
2024-04-25 09:17:36 +08:00
|
|
|
auto_accept_invite,
|
2019-11-08 22:52:38 +08:00
|
|
|
};
|
|
|
|
|
2022-08-05 14:09:43 +08:00
|
|
|
struct Overlay_Achievement
|
|
|
|
{
|
2024-08-18 08:28:51 +08:00
|
|
|
std::string name{}; // internal schema name
|
|
|
|
std::string title{}; // displayName
|
|
|
|
std::string description{}; // description
|
2024-06-23 05:30:49 +08:00
|
|
|
uint32 progress{};
|
|
|
|
uint32 max_progress{};
|
2024-04-25 09:17:36 +08:00
|
|
|
bool hidden{};
|
|
|
|
bool achieved{};
|
|
|
|
uint32 unlock_time{};
|
2024-11-18 01:33:21 +08:00
|
|
|
InGameOverlay::RendererResource_t* icon{};
|
|
|
|
InGameOverlay::RendererResource_t* icon_gray{};
|
2024-08-21 06:50:47 +08:00
|
|
|
int icon_handle = Settings::UNLOADED_IMAGE_HANDLE;
|
|
|
|
int icon_gray_handle = Settings::UNLOADED_IMAGE_HANDLE;
|
2022-08-05 14:09:43 +08:00
|
|
|
};
|
2019-08-14 20:55:31 +08:00
|
|
|
|
2024-06-07 02:07:15 +08:00
|
|
|
struct Notification
|
|
|
|
{
|
|
|
|
static constexpr float width_percent = 0.25f; // percentage from total width
|
2024-06-20 10:57:30 +08:00
|
|
|
static constexpr std::chrono::milliseconds default_show_time = std::chrono::milliseconds(6000);
|
2024-06-07 02:07:15 +08:00
|
|
|
|
|
|
|
int id{};
|
|
|
|
uint8 type{};
|
2024-06-20 10:57:30 +08:00
|
|
|
bool expired = false;
|
2024-06-07 02:07:15 +08:00
|
|
|
std::chrono::milliseconds start_time{};
|
|
|
|
std::string message{};
|
|
|
|
std::pair<const Friend, friend_window_state>* frd{};
|
|
|
|
std::optional<Overlay_Achievement> ach{};
|
|
|
|
};
|
|
|
|
|
2024-04-30 08:16:16 +08:00
|
|
|
// notification coordinates { x, y }
|
|
|
|
struct NotificationsCoords
|
2024-03-07 08:57:48 +08:00
|
|
|
{
|
2024-04-30 08:16:16 +08:00
|
|
|
std::pair<float, float> top_left{}, top_center{}, top_right{};
|
|
|
|
std::pair<float, float> bot_left{}, bot_center{}, bot_right{};
|
2024-01-26 11:49:03 +08:00
|
|
|
};
|
|
|
|
|
2019-07-26 05:33:07 +08:00
|
|
|
class Steam_Overlay
|
|
|
|
{
|
2024-04-11 05:49:01 +08:00
|
|
|
constexpr static const char ACH_SOUNDS_FOLDER[] = "sounds";
|
2024-06-04 18:39:38 +08:00
|
|
|
constexpr static const int renderer_detector_polling_ms = 100;
|
|
|
|
|
2024-04-10 03:00:19 +08:00
|
|
|
class Settings* settings;
|
|
|
|
class Local_Storage* local_storage;
|
|
|
|
class SteamCallResults* callback_results;
|
|
|
|
class SteamCallBacks* callbacks;
|
|
|
|
class RunEveryRunCB* run_every_runcb;
|
|
|
|
class Networking* network;
|
2019-08-01 04:21:02 +08:00
|
|
|
|
2019-08-02 17:16:30 +08:00
|
|
|
// friend id, show client window (to chat and accept invite maybe)
|
2024-03-15 01:23:39 +08:00
|
|
|
std::map<Friend, friend_window_state, Friend_Less> friends{};
|
2019-07-26 05:33:07 +08:00
|
|
|
|
2024-03-04 08:39:50 +08:00
|
|
|
bool is_ready = false;
|
2024-03-15 01:23:39 +08:00
|
|
|
|
|
|
|
ENotificationPosition notif_position = ENotificationPosition::k_EPositionBottomLeft;
|
|
|
|
int h_inset = 0;
|
|
|
|
int v_inset = 0;
|
|
|
|
std::string show_url{};
|
|
|
|
|
|
|
|
std::vector<Overlay_Achievement> achievements{};
|
2024-08-21 06:50:47 +08:00
|
|
|
size_t last_loaded_ach_icon{};
|
2024-03-15 01:23:39 +08:00
|
|
|
|
|
|
|
bool show_overlay = false;
|
2024-06-07 00:24:58 +08:00
|
|
|
bool show_user_info = false;
|
2024-03-15 01:23:39 +08:00
|
|
|
bool show_achievements = false;
|
|
|
|
bool show_settings = false;
|
2022-08-05 14:09:43 +08:00
|
|
|
|
2023-12-29 09:55:11 +08:00
|
|
|
// warn when using local save
|
2024-03-15 01:23:39 +08:00
|
|
|
bool warn_local_save = false;
|
2023-12-29 09:55:11 +08:00
|
|
|
// warn when app ID = 0
|
2024-03-15 01:23:39 +08:00
|
|
|
bool warn_bad_appid = false;
|
2022-08-05 14:09:43 +08:00
|
|
|
|
2024-03-15 01:23:39 +08:00
|
|
|
char username_text[256]{};
|
|
|
|
std::atomic<bool> save_settings = false;
|
2022-08-05 14:09:43 +08:00
|
|
|
|
2024-03-09 03:33:13 +08:00
|
|
|
int current_language = 0;
|
2022-08-05 14:09:43 +08:00
|
|
|
|
2024-03-09 03:33:13 +08:00
|
|
|
std::string warning_message{};
|
2019-07-26 05:33:07 +08:00
|
|
|
|
2019-08-01 04:21:02 +08:00
|
|
|
// Callback infos
|
2024-03-09 03:33:13 +08:00
|
|
|
std::queue<Friend> has_friend_action{};
|
|
|
|
std::vector<Notification> notifications{};
|
2024-01-22 07:31:02 +08:00
|
|
|
// used when the button "Invite all" is clicked
|
|
|
|
std::atomic<bool> invite_all_friends_clicked = false;
|
2020-01-27 06:24:16 +08:00
|
|
|
|
2024-03-15 01:23:39 +08:00
|
|
|
bool overlay_state_changed = false;
|
|
|
|
|
|
|
|
std::atomic<bool> i_have_lobby = false;
|
2019-08-01 04:21:02 +08:00
|
|
|
|
2024-03-15 01:23:39 +08:00
|
|
|
// some stuff has to be initialized once the renderer hook is ready
|
|
|
|
std::atomic<bool> late_init_imgui = false;
|
2024-03-12 05:55:19 +08:00
|
|
|
|
|
|
|
// changed each time a notification is posted or overlay is shown/hidden
|
|
|
|
std::atomic_uint32_t renderer_frame_processing_requests = 0;
|
|
|
|
// changed only when overlay is shown/hidden, true means overlay is shown
|
2024-03-12 06:25:47 +08:00
|
|
|
std::atomic_uint32_t obscure_cursor_requests = 0;
|
2024-03-09 03:33:13 +08:00
|
|
|
|
|
|
|
std::future<InGameOverlay::RendererHook_t *> future_renderer{};
|
|
|
|
InGameOverlay::RendererHook_t *_renderer{};
|
2020-01-21 00:47:12 +08:00
|
|
|
|
2024-06-04 18:39:38 +08:00
|
|
|
common_helpers::KillableWorker renderer_detector_delay_thread{};
|
|
|
|
common_helpers::KillableWorker renderer_hook_init_thread{};
|
|
|
|
int renderer_hook_timeout_ctr{};
|
|
|
|
|
|
|
|
// font stuff
|
|
|
|
ImFontAtlas fonts_atlas{};
|
|
|
|
ImFont *font_default{};
|
|
|
|
ImFont *font_notif{};
|
|
|
|
ImFontConfig font_cfg{};
|
|
|
|
ImFontGlyphRangesBuilder font_builder{};
|
|
|
|
ImVector<ImWchar> ranges{};
|
|
|
|
|
|
|
|
std::recursive_mutex overlay_mutex{};
|
|
|
|
std::atomic<bool> setup_overlay_called = false;
|
|
|
|
|
|
|
|
std::map<std::string, std::vector<char>> wav_files{
|
|
|
|
{ "overlay_achievement_notification.wav", std::vector<char>{} },
|
|
|
|
{ "overlay_friend_notification.wav", std::vector<char>{} },
|
|
|
|
};
|
|
|
|
|
2019-07-26 05:33:07 +08:00
|
|
|
Steam_Overlay(Steam_Overlay const&) = delete;
|
|
|
|
Steam_Overlay(Steam_Overlay&&) = delete;
|
|
|
|
Steam_Overlay& operator=(Steam_Overlay const&) = delete;
|
|
|
|
Steam_Overlay& operator=(Steam_Overlay&&) = delete;
|
|
|
|
|
2024-06-07 02:07:15 +08:00
|
|
|
bool submit_notification(
|
|
|
|
notification_type type,
|
|
|
|
const std::string &msg,
|
|
|
|
std::pair<const Friend, friend_window_state> *frd = nullptr,
|
|
|
|
Overlay_Achievement *ach = nullptr
|
|
|
|
);
|
2024-03-04 08:39:50 +08:00
|
|
|
|
2024-03-07 08:57:48 +08:00
|
|
|
void notify_sound_user_invite(friend_window_state& friend_state);
|
|
|
|
void notify_sound_user_achievement();
|
|
|
|
void notify_sound_auto_accept_friend_invite();
|
2019-09-05 01:31:31 +08:00
|
|
|
|
2019-08-02 21:26:16 +08:00
|
|
|
// Right click on friend
|
2024-03-07 08:57:48 +08:00
|
|
|
void build_friend_context_menu(Friend const& frd, friend_window_state &state);
|
2019-08-02 21:26:16 +08:00
|
|
|
// Double click on friend
|
2024-03-07 08:57:48 +08:00
|
|
|
void build_friend_window(Friend const& frd, friend_window_state &state);
|
2024-06-20 10:57:30 +08:00
|
|
|
std::chrono::milliseconds get_notification_duration(notification_type type);
|
2019-08-27 01:36:07 +08:00
|
|
|
// Notifications like achievements, chat and invitations
|
2024-06-20 10:57:30 +08:00
|
|
|
void set_next_notification_pos(std::pair<float, float> scrn_size, std::chrono::milliseconds elapsed, std::chrono::milliseconds duration, const Notification ¬i, struct NotificationsCoords &coords);
|
2024-04-28 02:17:20 +08:00
|
|
|
// factor controlling the amount of sliding during the animation, 0 means disabled
|
2024-06-20 10:57:30 +08:00
|
|
|
float animate_factor(std::chrono::milliseconds elapsed, std::chrono::milliseconds duration);
|
2024-06-07 02:07:15 +08:00
|
|
|
void add_ach_progressbar(const Overlay_Achievement &ach);
|
2024-06-20 07:57:39 +08:00
|
|
|
ImVec4 get_notification_bg_rgba_safe();
|
2024-06-04 18:39:38 +08:00
|
|
|
void build_notifications(float width, float height);
|
2024-08-21 06:50:47 +08:00
|
|
|
|
2024-03-09 03:33:13 +08:00
|
|
|
void request_renderer_detector();
|
2024-06-04 18:39:38 +08:00
|
|
|
void set_renderer_hook_timeout();
|
|
|
|
void cleanup_renderer_hook();
|
|
|
|
bool renderer_hook_proc();
|
2024-03-06 04:59:17 +08:00
|
|
|
|
2024-04-04 08:47:12 +08:00
|
|
|
// note: make sure to load all relevant strings before creating the font(s), otherwise some glyphs ranges will be missing
|
2024-03-07 08:57:48 +08:00
|
|
|
void create_fonts();
|
|
|
|
void load_audio();
|
2024-03-15 01:23:39 +08:00
|
|
|
void load_achievements_data();
|
2024-03-06 04:59:17 +08:00
|
|
|
|
2024-03-07 08:57:48 +08:00
|
|
|
void overlay_state_hook(bool ready);
|
2024-03-12 05:55:19 +08:00
|
|
|
void allow_renderer_frame_processing(bool state, bool cleaning_up_overlay = false);
|
2024-03-15 01:23:39 +08:00
|
|
|
void obscure_game_input(bool state);
|
2024-03-07 08:57:48 +08:00
|
|
|
|
|
|
|
void add_auto_accept_invite_notification();
|
2024-03-09 09:45:21 +08:00
|
|
|
void add_invite_notification(std::pair<const Friend, friend_window_state> &wnd_state);
|
2024-06-07 02:07:15 +08:00
|
|
|
void post_achievement_notification(Overlay_Achievement &ach, bool for_progress);
|
2024-03-07 08:57:48 +08:00
|
|
|
void add_chat_message_notification(std::string const& message);
|
2024-06-07 00:24:58 +08:00
|
|
|
void show_test_achievement();
|
2024-03-07 08:57:48 +08:00
|
|
|
|
|
|
|
bool open_overlay_hook(bool toggle);
|
|
|
|
|
2024-08-21 06:50:47 +08:00
|
|
|
bool try_load_ach_icon(Overlay_Achievement &ach, bool achieved, bool upload_new_icon_to_gpu);
|
2024-03-13 03:21:09 +08:00
|
|
|
|
2024-03-15 01:23:39 +08:00
|
|
|
void overlay_render_proc();
|
2024-08-21 06:50:47 +08:00
|
|
|
void load_next_ach_icon();
|
2024-06-07 02:00:42 +08:00
|
|
|
uint32 apply_global_style_color();
|
2024-03-20 04:07:43 +08:00
|
|
|
void render_main_window();
|
2024-08-21 06:50:47 +08:00
|
|
|
|
|
|
|
|
|
|
|
void steam_run_callback_update_my_lobby();
|
|
|
|
bool is_friend_joinable(std::pair<const Friend, friend_window_state> &f);
|
|
|
|
// invite a single friend
|
|
|
|
void invite_friend(uint64 friend_id, class Steam_Friends* steamFriends, class Steam_Matchmaking* steamMatchmaking);
|
|
|
|
void steam_run_callback_friends_actions();
|
2024-03-15 01:23:39 +08:00
|
|
|
void steam_run_callback();
|
|
|
|
|
2024-08-21 06:50:47 +08:00
|
|
|
void networking_msg_received(Common_Message* msg);
|
|
|
|
|
|
|
|
|
|
|
|
static void overlay_run_callback(void* object);
|
|
|
|
static void overlay_networking_callback(void* object, Common_Message* msg);
|
|
|
|
|
2019-07-26 05:33:07 +08:00
|
|
|
public:
|
2024-04-10 03:00:19 +08:00
|
|
|
Steam_Overlay(Settings* settings, Local_Storage *local_storage, SteamCallResults* callback_results, SteamCallBacks* callbacks, RunEveryRunCB* run_every_runcb, Networking *network);
|
2019-07-26 05:33:07 +08:00
|
|
|
|
2019-08-01 04:21:02 +08:00
|
|
|
~Steam_Overlay();
|
2019-07-26 05:33:07 +08:00
|
|
|
|
2019-08-01 04:21:02 +08:00
|
|
|
bool Ready() const;
|
2019-07-26 05:33:07 +08:00
|
|
|
|
2019-08-01 04:21:02 +08:00
|
|
|
bool NeedPresent() const;
|
2019-07-26 05:33:07 +08:00
|
|
|
|
2019-08-01 04:21:02 +08:00
|
|
|
void SetNotificationPosition(ENotificationPosition eNotificationPosition);
|
2019-07-26 05:33:07 +08:00
|
|
|
|
2019-08-01 04:21:02 +08:00
|
|
|
void SetNotificationInset(int nHorizontalInset, int nVerticalInset);
|
|
|
|
void SetupOverlay();
|
2022-08-08 11:11:21 +08:00
|
|
|
void UnSetupOverlay();
|
2019-07-26 05:33:07 +08:00
|
|
|
|
2019-08-01 04:21:02 +08:00
|
|
|
void OpenOverlayInvite(CSteamID lobbyId);
|
|
|
|
void OpenOverlay(const char* pchDialog);
|
2022-08-05 14:09:43 +08:00
|
|
|
void OpenOverlayWebpage(const char* pchURL);
|
2019-07-26 05:33:07 +08:00
|
|
|
|
2019-08-18 22:22:07 +08:00
|
|
|
bool ShowOverlay() const;
|
2019-08-01 04:21:02 +08:00
|
|
|
void ShowOverlay(bool state);
|
2019-08-02 17:16:30 +08:00
|
|
|
|
2019-08-03 05:01:24 +08:00
|
|
|
void SetLobbyInvite(Friend friendId, uint64 lobbyId);
|
|
|
|
void SetRichInvite(Friend friendId, const char* connect_str);
|
2019-08-02 17:16:30 +08:00
|
|
|
|
|
|
|
void FriendConnect(Friend _friend);
|
|
|
|
void FriendDisconnect(Friend _friend);
|
2019-09-05 01:31:31 +08:00
|
|
|
|
2024-06-07 02:07:15 +08:00
|
|
|
void AddAchievementNotification(const std::string &ach_name, nlohmann::json const& ach, bool for_progress);
|
2019-08-01 04:21:02 +08:00
|
|
|
};
|
2019-07-26 05:33:07 +08:00
|
|
|
|
2024-05-03 06:29:57 +08:00
|
|
|
#else // EMU_OVERLAY
|
2019-08-14 20:55:31 +08:00
|
|
|
|
|
|
|
class Steam_Overlay
|
|
|
|
{
|
|
|
|
public:
|
2024-04-10 03:00:19 +08:00
|
|
|
Steam_Overlay(Settings* settings, Local_Storage *local_storage, SteamCallResults* callback_results, SteamCallBacks* callbacks, RunEveryRunCB* run_every_runcb, Networking* network) {}
|
2019-08-15 00:11:00 +08:00
|
|
|
~Steam_Overlay() {}
|
2019-08-14 20:55:31 +08:00
|
|
|
|
2019-08-15 00:11:00 +08:00
|
|
|
bool Ready() const { return false; }
|
2019-08-14 20:55:31 +08:00
|
|
|
|
|
|
|
bool NeedPresent() const { return false; }
|
|
|
|
|
|
|
|
void SetNotificationPosition(ENotificationPosition eNotificationPosition) {}
|
|
|
|
|
|
|
|
void SetNotificationInset(int nHorizontalInset, int nVerticalInset) {}
|
|
|
|
void SetupOverlay() {}
|
2022-08-08 11:11:21 +08:00
|
|
|
void UnSetupOverlay() {}
|
2019-08-14 20:55:31 +08:00
|
|
|
|
|
|
|
void OpenOverlayInvite(CSteamID lobbyId) {}
|
|
|
|
void OpenOverlay(const char* pchDialog) {}
|
2022-08-05 14:09:43 +08:00
|
|
|
void OpenOverlayWebpage(const char* pchURL) {}
|
2019-08-14 20:55:31 +08:00
|
|
|
|
2023-12-21 09:28:21 +08:00
|
|
|
bool ShowOverlay() const { return false; }
|
2019-08-14 20:55:31 +08:00
|
|
|
void ShowOverlay(bool state) {}
|
|
|
|
|
|
|
|
void SetLobbyInvite(Friend friendId, uint64 lobbyId) {}
|
|
|
|
void SetRichInvite(Friend friendId, const char* connect_str) {}
|
|
|
|
|
|
|
|
void FriendConnect(Friend _friend) {}
|
|
|
|
void FriendDisconnect(Friend _friend) {}
|
2019-10-16 01:08:14 +08:00
|
|
|
|
2024-06-07 02:39:31 +08:00
|
|
|
void AddAchievementNotification(const std::string &ach_name, nlohmann::json const& ach, bool for_progress) {}
|
2019-08-14 20:55:31 +08:00
|
|
|
};
|
|
|
|
|
2024-05-03 06:29:57 +08:00
|
|
|
#endif // EMU_OVERLAY
|
2019-08-14 20:55:31 +08:00
|
|
|
|
2024-05-03 06:29:57 +08:00
|
|
|
#endif //__INCLUDED_STEAM_OVERLAY_H__
|