* update the steam_overlay.c/.h code to accommodate the changes in the ImGui lib & the ingame overlay project/dependency

* remove the now non-compiling (and awful) code which locks the cursor inside the overlay

* workaround for the deprecated ImGui function BeginListBox()

* formatting
This commit is contained in:
otavepto 2024-03-01 23:16:29 +02:00 committed by otavepto
parent c81842bd2f
commit 74a85fb38c
2 changed files with 52 additions and 103 deletions

View File

@ -88,7 +88,7 @@ struct Overlay_Achievement
#ifdef EMU_OVERLAY #ifdef EMU_OVERLAY
#include <future> #include <future>
#include "Renderer_Hook.h" #include "InGameOverlay/RendererHook.h"
struct NotificationsIndexes { struct NotificationsIndexes {
int top_left = 0, top_center = 0, top_right = 0; int top_left = 0, top_center = 0, top_right = 0;
@ -146,8 +146,8 @@ class Steam_Overlay
std::recursive_mutex overlay_mutex; std::recursive_mutex overlay_mutex;
std::atomic<bool> i_have_lobby; std::atomic<bool> i_have_lobby;
std::future<ingame_overlay::Renderer_Hook*> future_renderer; std::future<InGameOverlay::RendererHook_t*> future_renderer;
ingame_overlay::Renderer_Hook* _renderer; InGameOverlay::RendererHook_t* _renderer;
Steam_Overlay(Steam_Overlay const&) = delete; Steam_Overlay(Steam_Overlay const&) = delete;
Steam_Overlay(Steam_Overlay&&) = delete; Steam_Overlay(Steam_Overlay&&) = delete;

View File

@ -12,12 +12,12 @@
#include <string> #include <string>
#include <sstream> #include <sstream>
#include <cctype> #include <cctype>
#include <imgui.h> #include "InGameOverlay/ImGui/imgui.h"
#include "dll/dll.h" #include "dll/dll.h"
#include "dll/settings_parser.h" #include "dll/settings_parser.h"
#include "overlay/Renderer_Detector.h" #include "InGameOverlay/RendererDetector.h"
static constexpr int max_window_id = 10000; static constexpr int max_window_id = 10000;
static constexpr int base_notif_window_id = 0 * max_window_id; static constexpr int base_notif_window_id = 0 * max_window_id;
@ -101,10 +101,6 @@ int find_free_notification_id(std::vector<Notification> const& notifications)
return find_free_id(ids, base_friend_window_id); return find_free_id(ids, base_friend_window_id);
} }
#ifdef __WINDOWS__
#include "windows/Windows_Hook.h"
#endif
#include "overlay/notification.h" #include "overlay/notification.h"
char *notif_achievement_wav_custom; char *notif_achievement_wav_custom;
char *notif_invite_wav_custom; char *notif_invite_wav_custom;
@ -200,32 +196,31 @@ void Steam_Overlay::SetNotificationInset(int nHorizontalInset, int nVerticalInse
void Steam_Overlay::SetupOverlay() void Steam_Overlay::SetupOverlay()
{ {
PRINT_DEBUG("%s\n", __FUNCTION__); PRINT_DEBUG("Steam_Overlay::SetupOverlay\n");
std::lock_guard<std::recursive_mutex> lock(overlay_mutex); std::lock_guard<std::recursive_mutex> lock(overlay_mutex);
if (!setup_overlay_called) if (!setup_overlay_called) {
{
setup_overlay_called = true; setup_overlay_called = true;
future_renderer = ingame_overlay::DetectRenderer(); future_renderer = InGameOverlay::DetectRenderer();
} }
} }
void Steam_Overlay::UnSetupOverlay() void Steam_Overlay::UnSetupOverlay()
{ {
PRINT_DEBUG("%s\n", __FUNCTION__); PRINT_DEBUG("Steam_Overlay::UnSetupOverlay\n");
std::lock_guard<std::recursive_mutex> lock(overlay_mutex); std::lock_guard<std::recursive_mutex> lock(overlay_mutex);
ingame_overlay::StopRendererDetection(); InGameOverlay::StopRendererDetection();
if (!Ready() && future_renderer.valid()) { if (!Ready() && future_renderer.valid()) {
if (future_renderer.wait_for(std::chrono::milliseconds{500}) == std::future_status::ready) { if (future_renderer.wait_for(std::chrono::milliseconds{500}) == std::future_status::ready) {
future_renderer.get(); future_renderer.get(); // to invalidate the future object
ingame_overlay::FreeDetector(); InGameOverlay::FreeDetector();
} }
} }
} }
void Steam_Overlay::HookReady(bool ready) void Steam_Overlay::HookReady(bool ready)
{ {
PRINT_DEBUG("%s %u\n", __FUNCTION__, ready); PRINT_DEBUG("Steam_Overlay::HookReady %i\n", (int)ready);
{ {
// TODO: Uncomment this and draw our own cursor (cosmetics) // TODO: Uncomment this and draw our own cursor (cosmetics)
ImGuiIO &io = ImGui::GetIO(); ImGuiIO &io = ImGui::GetIO();
@ -282,56 +277,12 @@ void Steam_Overlay::ShowOverlay(bool state)
ImGuiIO &io = ImGui::GetIO(); ImGuiIO &io = ImGui::GetIO();
if(state) if (state) {
{
io.MouseDrawCursor = true; io.MouseDrawCursor = true;
} } else {
else
{
io.MouseDrawCursor = false; io.MouseDrawCursor = false;
} }
#ifdef __WINDOWS__
static RECT old_clip;
if (state)
{
HWND game_hwnd = Windows_Hook::Inst()->GetGameHwnd();
RECT cliRect, wndRect, clipRect;
GetClipCursor(&old_clip);
// The window rectangle has borders and menus counted in the size
GetWindowRect(game_hwnd, &wndRect);
// The client rectangle is the window without borders
GetClientRect(game_hwnd, &cliRect);
clipRect = wndRect; // Init clip rectangle
// Get Window width with borders
wndRect.right -= wndRect.left;
// Get Window height with borders & menus
wndRect.bottom -= wndRect.top;
// Compute the border width
int borderWidth = (wndRect.right - cliRect.right) / 2;
// Client top clip is the menu bar width minus bottom border
clipRect.top += wndRect.bottom - cliRect.bottom - borderWidth;
// Client left clip is the left border minus border width
clipRect.left += borderWidth;
// Here goes the same for right and bottom
clipRect.right -= borderWidth;
clipRect.bottom -= borderWidth;
ClipCursor(&clipRect);
}
else
{
ClipCursor(&old_clip);
}
#else
#endif
show_overlay = state; show_overlay = state;
overlay_state_changed = true; overlay_state_changed = true;
} }
@ -702,7 +653,7 @@ void Steam_Overlay::BuildFriendWindow(Friend const& frd, friend_window_state& st
// | \--------------------------/ | // | \--------------------------/ |
// | [__chat line__] [send] | // | [__chat line__] [send] |
// |------------------------------| // |------------------------------|
float wnd_width = ImGui::GetWindowContentRegionWidth(); float wnd_width = ImGui::GetContentRegionAvail().x;
ImGuiStyle &style = ImGui::GetStyle(); ImGuiStyle &style = ImGui::GetStyle();
wnd_width -= ImGui::CalcTextSize(translationSend[current_language]).x + style.FramePadding.x * 2 + style.ItemSpacing.x + 1; wnd_width -= ImGui::CalcTextSize(translationSend[current_language]).x + style.FramePadding.x * 2 + style.ItemSpacing.x + 1;
@ -985,7 +936,7 @@ void Steam_Overlay::CreateFonts()
font_notif = font_default = font; font_notif = font_default = font;
if (need_extra_fonts) { if (need_extra_fonts) {
PRINT_DEBUG("loading extra fonts\n"); PRINT_DEBUG("Steam_Overlay loading extra fonts\n");
fontcfg.MergeMode = true; fontcfg.MergeMode = true;
#if defined(__WINDOWS__) #if defined(__WINDOWS__)
Fonts->AddFontFromFileTTF("C:\\Windows\\Fonts\\simsun.ttc", font_size, &fontcfg); Fonts->AddFontFromFileTTF("C:\\Windows\\Fonts\\simsun.ttc", font_size, &fontcfg);
@ -1046,6 +997,14 @@ void Steam_Overlay::LoadAudio()
} }
} }
// ListBoxHeader() is deprecated and inlined inside <imgui.h>
// Helper to calculate size from items_count and height_in_items
static inline bool ImGuiHelper_BeginListBox(const char* label, int items_count) {
int min_items = items_count < 7 ? items_count : 7;
float height = ImGui::GetTextLineHeightWithSpacing() * (min_items + 0.25f) + ImGui::GetStyle().FramePadding.y * 2.0f;
return ImGui::BeginListBox(label, ImVec2(0.0f, height));
}
// 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()
{ {
@ -1141,8 +1100,7 @@ void Steam_Overlay::OverlayProc()
ImGui::LabelText("##label", translationFriends[current_language]); ImGui::LabelText("##label", translationFriends[current_language]);
std::lock_guard<std::recursive_mutex> lock(overlay_mutex); std::lock_guard<std::recursive_mutex> lock(overlay_mutex);
if (!friends.empty()) if (!friends.empty()) {
{
if (i_have_lobby) { if (i_have_lobby) {
std::string inviteAll(translationInviteAll[current_language]); std::string inviteAll(translationInviteAll[current_language]);
inviteAll.append("##PopupInviteAllFriends"); inviteAll.append("##PopupInviteAllFriends");
@ -1151,23 +1109,20 @@ void Steam_Overlay::OverlayProc()
} }
} }
if (ImGui::ListBoxHeader("##label", friends.size())) if (ImGuiHelper_BeginListBox("##label", friends.size())) {
{ std::for_each(friends.begin(), friends.end(), [this](std::pair<Friend const, friend_window_state> &i) {
std::for_each(friends.begin(), friends.end(), [this](std::pair<Friend const, friend_window_state> &i)
{
ImGui::PushID(i.second.id-base_friend_window_id+base_friend_item_id); ImGui::PushID(i.second.id-base_friend_window_id+base_friend_item_id);
ImGui::Selectable(i.second.window_title.c_str(), false, ImGuiSelectableFlags_AllowDoubleClick); ImGui::Selectable(i.second.window_title.c_str(), false, ImGuiSelectableFlags_AllowDoubleClick);
BuildContextMenu(i.first, i.second); BuildContextMenu(i.first, i.second);
if (ImGui::IsItemClicked() && ImGui::IsMouseDoubleClicked(0)) if (ImGui::IsItemClicked() && ImGui::IsMouseDoubleClicked(0)) {
{
i.second.window_state |= window_state_show; i.second.window_state |= window_state_show;
} }
ImGui::PopID(); ImGui::PopID();
BuildFriendWindow(i.first, i.second); BuildFriendWindow(i.first, i.second);
}); });
ImGui::ListBoxFooter(); ImGui::EndListBox();
} }
} }
@ -1224,9 +1179,9 @@ void Steam_Overlay::OverlayProc()
ImGui::TableSetColumnIndex(0); ImGui::TableSetColumnIndex(0);
if (achieved) { if (achieved) {
ImGui::Image((ImU64)*x.icon.lock().get(), ImVec2(settings->overlay_appearance.icon_size, settings->overlay_appearance.icon_size)); ImGui::Image((ImTextureID)*x.icon.lock().get(), ImVec2(settings->overlay_appearance.icon_size, settings->overlay_appearance.icon_size));
} else { } else {
ImGui::Image((ImU64)*x.icon_gray.lock().get(), ImVec2(settings->overlay_appearance.icon_size, settings->overlay_appearance.icon_size)); ImGui::Image((ImTextureID)*x.icon_gray.lock().get(), ImVec2(settings->overlay_appearance.icon_size, settings->overlay_appearance.icon_size));
} }
ImGui::TableSetColumnIndex(1); ImGui::TableSetColumnIndex(1);
@ -1353,18 +1308,15 @@ void Steam_Overlay::OverlayProc()
void Steam_Overlay::Callback(Common_Message *msg) void Steam_Overlay::Callback(Common_Message *msg)
{ {
std::lock_guard<std::recursive_mutex> lock(overlay_mutex); std::lock_guard<std::recursive_mutex> lock(overlay_mutex);
if (msg->has_steam_messages()) if (msg->has_steam_messages()) {
{
Friend frd; Friend frd;
frd.set_id(msg->source_id()); frd.set_id(msg->source_id());
auto friend_info = friends.find(frd); auto friend_info = friends.find(frd);
if (friend_info != friends.end()) if (friend_info != friends.end()) {
{
Steam_Messages const& steam_message = msg->steam_messages(); Steam_Messages const& steam_message = msg->steam_messages();
// Change color to cyan for friend // Change color to cyan for friend
friend_info->second.chat_history.append(friend_info->first.name() + ": " + steam_message.message()).append("\n", 1); friend_info->second.chat_history.append(friend_info->first.name() + ": " + steam_message.message()).append("\n", 1);
if (!(friend_info->second.window_state & window_state_show)) if (!(friend_info->second.window_state & window_state_show)) {
{
friend_info->second.window_state |= window_state_need_attention; friend_info->second.window_state |= window_state_need_attention;
} }
@ -1381,7 +1333,7 @@ void Steam_Overlay::RunCallbacks()
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(); uint32 achievements_num = steamUserStats->GetNumAchievements();
if (achievements_num) { if (achievements_num) {
PRINT_DEBUG("POPULATE OVERLAY ACHIEVEMENTS\n"); PRINT_DEBUG("Steam_Overlay POPULATE OVERLAY ACHIEVEMENTS\n");
for (unsigned i = 0; i < achievements_num; ++i) { for (unsigned i = 0; i < achievements_num; ++i) {
Overlay_Achievement ach; Overlay_Achievement ach;
ach.name = steamUserStats->GetAchievementName(i); ach.name = steamUserStats->GetAchievementName(i);
@ -1410,39 +1362,37 @@ void Steam_Overlay::RunCallbacks()
achievements.push_back(ach); achievements.push_back(ach);
} }
PRINT_DEBUG("POPULATE OVERLAY ACHIEVEMENTS DONE\n"); PRINT_DEBUG("Steam_Overlay POPULATE OVERLAY ACHIEVEMENTS DONE\n");
} }
} }
if (!Ready() && future_renderer.valid()) { if (!Ready() && future_renderer.valid()) {
if (future_renderer.wait_for(std::chrono::milliseconds{0}) == std::future_status::ready) { if (future_renderer.wait_for(std::chrono::milliseconds{0}) == std::future_status::ready) {
_renderer = future_renderer.get(); _renderer = future_renderer.get();
PRINT_DEBUG("got renderer %p\n", _renderer); PRINT_DEBUG("Steam_Overlay got renderer %p\n", _renderer);
CreateFonts(); CreateFonts();
LoadAudio(); LoadAudio();
} }
} }
if (!Ready() && _renderer) { if (!Ready() && _renderer) {
_renderer->OverlayHookReady = std::bind(&Steam_Overlay::HookReady, this, std::placeholders::_1); _renderer->OverlayHookReady = [this](InGameOverlay::OverlayHookState state) { HookReady(state == InGameOverlay::OverlayHookState::Ready); };
_renderer->OverlayProc = std::bind(&Steam_Overlay::OverlayProc, this); _renderer->OverlayProc = [this]() { OverlayProc(); };
auto callback = std::bind(&Steam_Overlay::OpenOverlayHook, this, std::placeholders::_1); PRINT_DEBUG("start renderer\n", _renderer);
PRINT_DEBUG("start renderer\n", _renderer); std::set<InGameOverlay::ToggleKey> keys = {InGameOverlay::ToggleKey::SHIFT, InGameOverlay::ToggleKey::TAB};
std::set<ingame_overlay::ToggleKey> keys = {ingame_overlay::ToggleKey::SHIFT, ingame_overlay::ToggleKey::TAB}; auto key_combination_callback = [this]() { OpenOverlayHook(true); };
_renderer->ImGuiFontAtlas = fonts_atlas; bool started = _renderer->StartHook(key_combination_callback, keys, fonts_atlas);
bool started = _renderer->StartHook(callback, keys); PRINT_DEBUG("Steam_Overlay tried to start renderer hook (result=%u)\n", started);
PRINT_DEBUG("tried to start renderer %u\n", started);
} }
if (overlay_state_changed) if (overlay_state_changed) {
{ overlay_state_changed = false;
GameOverlayActivated_t data = { 0 };
GameOverlayActivated_t data{};
data.m_bActive = show_overlay; data.m_bActive = show_overlay;
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));
overlay_state_changed = false;
} }
Steam_Friends* steamFriends = get_steam_client()->steam_friends; Steam_Friends* steamFriends = get_steam_client()->steam_friends;
@ -1466,8 +1416,7 @@ void Steam_Overlay::RunCallbacks()
i.second.joinable = FriendJoinable(i); i.second.joinable = FriendJoinable(i);
}); });
while (!has_friend_action.empty()) while (!has_friend_action.empty()) {
{
auto friend_info = friends.find(has_friend_action.front()); auto friend_info = friends.find(has_friend_action.front());
if (friend_info != friends.end()) { if (friend_info != friends.end()) {
uint64 friend_id = (uint64)friend_info->first.id(); uint64 friend_id = (uint64)friend_info->first.id();