From 9ccc46088addc3d02df95028ae0354aff6c9bd7c Mon Sep 17 00:00:00 2001 From: Peter Repukat Date: Fri, 22 Oct 2021 12:17:46 +0200 Subject: [PATCH] Add WIP GlosSI Overlay --- GlosSITarget/GlosSITarget.vcxproj | 19 ++- GlosSITarget/GlosSITarget.vcxproj.filters | 63 +++++++++- GlosSITarget/Overlay.cpp | 142 ++++++++++++++++++++++ GlosSITarget/Overlay.h | 23 ++++ GlosSITarget/SteamTarget.cpp | 32 ++++- GlosSITarget/SteamTarget.h | 8 ++ GlosSITarget/TargetWindow.cpp | 47 ++++--- GlosSITarget/TargetWindow.h | 6 + GlosSITarget/imconfig.h | 30 +++++ 9 files changed, 333 insertions(+), 37 deletions(-) create mode 100644 GlosSITarget/Overlay.cpp create mode 100644 GlosSITarget/Overlay.h create mode 100644 GlosSITarget/imconfig.h diff --git a/GlosSITarget/GlosSITarget.vcxproj b/GlosSITarget/GlosSITarget.vcxproj index 5b4ff25..1b6fbec 100644 --- a/GlosSITarget/GlosSITarget.vcxproj +++ b/GlosSITarget/GlosSITarget.vcxproj @@ -80,14 +80,14 @@ true - ..\deps\SFML\include;..\deps\WinReg;..\deps\spdlog\include;..\deps\ValveFileVDF;..\deps\subhook;..\deps\ViGEmClient\include;$(ExternalIncludePath) + ..\deps\SFML\include;..\deps\WinReg;..\deps\spdlog\include;..\deps\ValveFileVDF;..\deps\subhook;..\deps\ViGEmClient\include;..\deps\imgui;..\deps\imgui-sfml;$(ExternalIncludePath) ..\deps\SFML\out\build\x64-Debug\lib;..\deps\ViGEmClient\lib\debug\x64;$(LibraryPath) false true false - ..\deps\SFML\include;..\deps\WinReg;..\deps\spdlog\include;..\deps\ValveFileVDF;..\deps\subhook;..\deps\ViGEmClient\include;$(ExternalIncludePath) + ..\deps\SFML\include;..\deps\WinReg;..\deps\spdlog\include;..\deps\ValveFileVDF;..\deps\subhook;..\deps\ViGEmClient\include;..\deps\imgui;..\deps\imgui-sfml;$(ExternalIncludePath) ..\deps\SFML\out\build\x64-Release\lib;..\deps\ViGEmClient\lib\release\x64;$(LibraryPath) @@ -129,7 +129,7 @@ Console true - hid.lib;Cfgmgr32.lib;sfml-window-d.lib;sfml-system-d.lib;sfml-graphics-d.lib;dwmapi.lib;xinput9_1_0.lib;setupapi.lib;ViGEmClient.lib;%(AdditionalDependencies) + hid.lib;Cfgmgr32.lib;opengl32.lib;sfml-window-d.lib;sfml-system-d.lib;sfml-graphics-d.lib;dwmapi.lib;xinput9_1_0.lib;setupapi.lib;ViGEmClient.lib;%(AdditionalDependencies) @@ -147,22 +147,33 @@ true true true - hid.lib;Cfgmgr32.lib;xinput9_1_0.lib;setupapi.lib;ViGEmClient.lib;%(AdditionalDependencies) + hid.lib;Cfgmgr32.lib;opengl32.lib;xinput9_1_0.lib;setupapi.lib;ViGEmClient.lib;%(AdditionalDependencies) + + + + + + + + + + + diff --git a/GlosSITarget/GlosSITarget.vcxproj.filters b/GlosSITarget/GlosSITarget.vcxproj.filters index 65c0eef..f0ce82a 100644 --- a/GlosSITarget/GlosSITarget.vcxproj.filters +++ b/GlosSITarget/GlosSITarget.vcxproj.filters @@ -13,6 +13,24 @@ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + {2c3e6fba-dedb-4076-b773-ef773c7773fd} + + + {c54f210b-d322-4887-8bc4-403e6235e7cd} + + + {5923a6d8-ec50-409b-a004-5566024d25d6} + + + {2b9ce4e5-3909-4902-bac0-b68210377d54} + + + {70a0a051-1ecd-4e98-9da4-7ecc5fefb467} + + + {5e050d12-af62-455e-afb1-d8a253f06ab8} + @@ -27,15 +45,36 @@ Source Files - - Source Files - Source Files Source Files + + Source Files + + + Source Files\imgui + + + Source Files\imgui + + + Source Files\imgui + + + Source Files\imgui + + + Source Files\subhook + + + Source Files\imgui-sfml + + + Source Files\imgui + @@ -50,15 +89,27 @@ Header Files - - Header Files - Header Files Header Files + + Header Files + + + Header Files + + + Header Files\imgui + + + Header Files\subhook + + + Header Files\imgui-sfml + diff --git a/GlosSITarget/Overlay.cpp b/GlosSITarget/Overlay.cpp new file mode 100644 index 0000000..62a24fa --- /dev/null +++ b/GlosSITarget/Overlay.cpp @@ -0,0 +1,142 @@ +#include "Overlay.h" + +#define IMGUI_USER_CONFIG "imconfig.h" +#include "imgui.h" +#include "imgui-SFML.h" + + +Overlay::Overlay(sf::RenderWindow& window, std::function on_close) : window_(window), on_close_(on_close) +{ + ImGui::SFML::Init(window_); + ImGuiIO& io = ImGui::GetIO(); + io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; + io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; + + window.resetGLStates(); + + auto& style = ImGui::GetStyle(); + style.WindowBorderSize = 0; + style.WindowRounding = 12; + style.ScrollbarRounding = 12; + style.PopupRounding = 12; + style.ChildRounding = 5; + style.ScrollbarRounding = 12; + style.GrabRounding = 5; + + ImVec4* colors = ImGui::GetStyle().Colors; + colors[ImGuiCol_Text] = ImVec4(0.95f, 0.96f, 0.98f, 1.00f); + colors[ImGuiCol_TextDisabled] = ImVec4(0.36f, 0.42f, 0.47f, 1.00f); + colors[ImGuiCol_WindowBg] = ImVec4(0.10f, 0.13f, 0.14f, 0.95f); + colors[ImGuiCol_ChildBg] = ImVec4(0.15f, 0.18f, 0.22f, 1.00f); + colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.08f, 0.94f); + colors[ImGuiCol_Border] = ImVec4(0.08f, 0.10f, 0.12f, 1.00f); + colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); + colors[ImGuiCol_FrameBg] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f); + colors[ImGuiCol_FrameBgHovered] = ImVec4(0.12f, 0.20f, 0.28f, 1.00f); + colors[ImGuiCol_FrameBgActive] = ImVec4(0.09f, 0.12f, 0.14f, 1.00f); + colors[ImGuiCol_TitleBg] = ImVec4(0.18f, 0.21f, 0.24f, 0.94f); + colors[ImGuiCol_TitleBgActive] = ImVec4(0.26f, 0.29f, 0.34f, 0.93f); + colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 0.51f); + colors[ImGuiCol_MenuBarBg] = ImVec4(0.15f, 0.18f, 0.22f, 1.00f); + colors[ImGuiCol_ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.39f); + colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f); + colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.18f, 0.22f, 0.25f, 1.00f); + colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.09f, 0.21f, 0.31f, 1.00f); + colors[ImGuiCol_CheckMark] = ImVec4(0.28f, 0.56f, 1.00f, 1.00f); + colors[ImGuiCol_SliderGrab] = ImVec4(0.28f, 0.56f, 1.00f, 1.00f); + colors[ImGuiCol_SliderGrabActive] = ImVec4(0.37f, 0.61f, 1.00f, 1.00f); + colors[ImGuiCol_Button] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f); + colors[ImGuiCol_ButtonHovered] = ImVec4(0.28f, 0.56f, 1.00f, 1.00f); + colors[ImGuiCol_ButtonActive] = ImVec4(0.06f, 0.53f, 0.98f, 1.00f); + colors[ImGuiCol_Header] = ImVec4(0.15f, 0.20f, 0.25f, 0.95f); + colors[ImGuiCol_HeaderHovered] = ImVec4(0.29f, 0.54f, 0.83f, 0.96f); + colors[ImGuiCol_HeaderActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); + colors[ImGuiCol_Separator] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f); + colors[ImGuiCol_SeparatorHovered] = ImVec4(0.10f, 0.40f, 0.75f, 0.78f); + colors[ImGuiCol_SeparatorActive] = ImVec4(0.10f, 0.40f, 0.75f, 1.00f); + colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.59f, 0.98f, 0.25f); + colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); + colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); + colors[ImGuiCol_Tab] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f); + colors[ImGuiCol_TabHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.80f); + colors[ImGuiCol_TabActive] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f); + colors[ImGuiCol_TabUnfocused] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f); + colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f); + colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f); + colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f); + colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); + colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); + colors[ImGuiCol_TableHeaderBg] = ImVec4(0.19f, 0.19f, 0.20f, 1.00f); + colors[ImGuiCol_TableBorderStrong] = ImVec4(0.31f, 0.31f, 0.35f, 1.00f); + colors[ImGuiCol_TableBorderLight] = ImVec4(0.23f, 0.23f, 0.25f, 1.00f); + colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); + colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.06f); + colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f); + colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f); + colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); + colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); + colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f); + colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f); +} + +void Overlay::setEnabled(bool enabled) +{ + enabled_ = enabled; +} + +bool Overlay::toggle() +{ + enabled_ = !enabled_; + return enabled_; +} + +void Overlay::update() +{ + ImGui::SFML::Update(window_, update_clock_.restart()); + + bool open = true; + if (enabled_) { + window_.clear(sf::Color(0, 0, 0, 64)); // make window slightly dim screen with overlay + ImGui::ShowDemoWindow(&open); + + if (closeButton()) { + return; + } + } + + ImGui::SFML::Render(window_); +} + +void Overlay::ProcessEvent(sf::Event evnt) +{ + ImGui::SFML::ProcessEvent(evnt); +} + +void Overlay::Shutdown() +{ + ImGui::SFML::Shutdown(); +} + +void Overlay::ShowNotification(std::string noti_text) +{} + +bool Overlay::closeButton() const +{ + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, {0, 0}); + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.0f, 0.f, 0.f, 0.0f)); + ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.6f, 0.f, 0.f, 0.9f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered,ImVec4(1.f, 0.16f, 0.16f, 1.00f)); + ImGui::Begin("##CloseButton", nullptr, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize); + ImGui::SetWindowSize({56 + 24, 32 + 24}); + ImGui::SetWindowPos({window_.getSize().x - ImGui::GetWindowWidth() + 24, -24}); + if (ImGui::Button("X##Close", {56, 48})) { + on_close_(); + return true; + } + ImGui::End(); + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + ImGui::PopStyleVar(); + return false; +} diff --git a/GlosSITarget/Overlay.h b/GlosSITarget/Overlay.h new file mode 100644 index 0000000..f8237ba --- /dev/null +++ b/GlosSITarget/Overlay.h @@ -0,0 +1,23 @@ +#pragma once +#include +#include +#include + +class Overlay { + public: + Overlay(sf::RenderWindow& window, std::function on_close); + + void setEnabled(bool enabled); + bool toggle(); + void update(); + static void ProcessEvent(sf::Event evnt); + static void Shutdown(); + static void ShowNotification(std::string noti_text); + private: + sf::RenderWindow& window_; + sf::Clock update_clock_; + bool enabled_ = true; + std::function on_close_; + + bool closeButton() const; +}; diff --git a/GlosSITarget/SteamTarget.cpp b/GlosSITarget/SteamTarget.cpp index 8e65ad5..9af15c9 100644 --- a/GlosSITarget/SteamTarget.cpp +++ b/GlosSITarget/SteamTarget.cpp @@ -27,28 +27,46 @@ limitations under the License. SteamTarget::SteamTarget(int argc, char* argv[]) : window_([this] { run_ = false; }, getScreenshotHotkey()), - detector_([this](bool overlay_open) { onOverlayChanged(overlay_open); }) + detector_([this](bool overlay_open) { onOverlayChanged(overlay_open); }), + overlay_(window_.getOverlay()) { target_window_handle_ = window_.getSystemHandle(); } int SteamTarget::run() { + // TODO: Hide GlosSI overlay not based on time, but on game launch. + sf::Clock mock_clock; + bool mock_clock_flag = SteamOverlayDetector::IsSteamInjected(); + if (!mock_clock_flag) { + spdlog::warn("Steam Overlay not detected. Keeping GlosSI Overlay!\n\ +Application will not function!"); + } + run_ = true; + #ifdef _WIN32 hidhide_.hideDevices(steam_path_); input_redirector_.run(); #endif + keepControllerConfig(true); while (run_) { + if (mock_clock_flag && mock_clock.getElapsedTime().asSeconds() > 5) { + window_.setClickThrough(true); + overlay_.setEnabled(false); + mock_clock_flag = false; + } detector_.update(); window_.update(); overlayHotkeyWorkaround(); } + #ifdef _WIN32 input_redirector_.stop(); hidhide_.disableHidHide(); #endif + return 1; } @@ -59,6 +77,18 @@ void SteamTarget::onOverlayChanged(bool overlay_open) focusWindow(target_window_handle_); } else { + + if (!overlay_trigger_flag_) { + overlay_trigger_flag_ = true; + overlay_trigger_clock_.restart(); + } + else { + if (overlay_trigger_clock_.getElapsedTime().asSeconds() <= overlay_trigger_max_seconds_) { + window_.setClickThrough(!overlay_.toggle()); + } + overlay_trigger_flag_ = false; + } + focusWindow(last_foreground_window_); } } diff --git a/GlosSITarget/SteamTarget.h b/GlosSITarget/SteamTarget.h index c5bdb91..bfd6014 100644 --- a/GlosSITarget/SteamTarget.h +++ b/GlosSITarget/SteamTarget.h @@ -25,6 +25,8 @@ limitations under the License. #include #endif +#include "Overlay.h" + #include class SteamTarget { @@ -69,10 +71,16 @@ class SteamTarget { InputRedirector input_redirector_; #endif TargetWindow window_; + Overlay& overlay_; SteamOverlayDetector detector_; WindowHandle last_foreground_window_ = nullptr; static inline WindowHandle target_window_handle_ = nullptr; + sf::Clock overlay_trigger_clock_; + uint32_t overlay_trigger_max_seconds_ = 4; + bool overlay_trigger_flag_ = false; + + static constexpr std::wstring_view user_data_path_ = L"/userdata/"; static constexpr std::wstring_view config_file_name_ = L"/config/localconfig.vdf"; static constexpr std::string_view overlay_hotkey_name_ = "InGameOverlayShortcutKey "; diff --git a/GlosSITarget/TargetWindow.cpp b/GlosSITarget/TargetWindow.cpp index 9cadc84..075d21d 100644 --- a/GlosSITarget/TargetWindow.cpp +++ b/GlosSITarget/TargetWindow.cpp @@ -28,28 +28,24 @@ limitations under the License. #include #endif -static const bool DEV_MODE = false; TargetWindow::TargetWindow(std::function on_close, std::vector screenshot_hotkey) - : on_close_(std::move(on_close)), screenshot_keys_(std::move(screenshot_hotkey)) + : on_close_(std::move(on_close)), + screenshot_keys_(std::move(screenshot_hotkey)), + overlay_(window_, [this]() { close(); }) { - if (DEV_MODE) { - window_.create(sf::VideoMode{1920, 1080}, "GlosSITarget", sf::Style::Default); - } - else { - window_.create(sf::VideoMode::getDesktopMode(), "GlosSITarget", sf::Style::None); - } + + window_.create(sf::VideoMode::getDesktopMode(), "GlosSITarget", sf::Style::None); window_.setActive(true); #ifdef _WIN32 HWND hwnd = window_.getSystemHandle(); + // transparent windows window... MARGINS margins; margins.cxLeftWidth = -1; DwmExtendFrameIntoClientArea(hwnd, &margins); - if (!DEV_MODE) { - // always on top - SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); - } + // always on top + SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); DEVMODE dev_mode = {}; dev_mode.dmSize = sizeof(DEVMODE); @@ -57,15 +53,12 @@ TargetWindow::TargetWindow(std::function on_close, std::vector #include @@ -36,6 +38,8 @@ class TargetWindow { void update(); void close(); + Overlay& getOverlay(); + /* * Run once per frame * - detects steam configured screenshot hotkey @@ -55,4 +59,6 @@ class TargetWindow { const std::function on_close_; sf::RenderWindow window_; std::vector screenshot_keys_; + + Overlay overlay_; }; diff --git a/GlosSITarget/imconfig.h b/GlosSITarget/imconfig.h new file mode 100644 index 0000000..c63f0aa --- /dev/null +++ b/GlosSITarget/imconfig.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include + +#include "imgui-SFML_export.h" + +#define IM_VEC2_CLASS_EXTRA \ + template \ + ImVec2(const sf::Vector2& v) \ + { \ + x = static_cast(v.x); \ + y = static_cast(v.y); \ + } \ + \ + template \ + operator sf::Vector2() const \ + { \ + return sf::Vector2(x, y); \ + } + +#define IM_VEC4_CLASS_EXTRA \ + ImVec4(const sf::Color& c) : x(c.r / 255.f), y(c.g / 255.f), z(c.b / 255.f), w(c.a / 255.f) {} \ + operator sf::Color() const \ + { \ + return sf::Color(static_cast(x * 255.f), static_cast(y * 255.f), \ + static_cast(z * 255.f), static_cast(w * 255.f)); \ + } + +#define ImTextureID unsigned int