From b86d548fc28a28b5baada45ab54e8952171e6fd6 Mon Sep 17 00:00:00 2001 From: Peter Repukat Date: Mon, 30 Jan 2023 18:19:36 +0100 Subject: [PATCH] Support delayed target initialization and delay init if XBox controller rebinding is disabled in Steam --- GlosSITarget/Overlay.cpp | 31 +++++- GlosSITarget/Overlay.h | 4 +- GlosSITarget/Resource.rc | 8 +- GlosSITarget/SteamTarget.cpp | 208 +++++++++++++++++++++-------------- GlosSITarget/SteamTarget.h | 3 + 5 files changed, 160 insertions(+), 94 deletions(-) diff --git a/GlosSITarget/Overlay.cpp b/GlosSITarget/Overlay.cpp index 44e0581..7455fea 100644 --- a/GlosSITarget/Overlay.cpp +++ b/GlosSITarget/Overlay.cpp @@ -163,12 +163,16 @@ void Overlay::update() const auto remain_millis = SPLASH_DURATION_S_ * 1000 - millis; if (remain_millis <= fade_millis) { showSplash(static_cast(remain_millis) / static_cast(fade_millis) * 128.f); - } else { + } + else { showSplash(128); } } if (Settings::window.disableGlosSIOverlay) { + std::ranges::for_each(FORCED_OVERLAY_ELEMS_, [this](const auto& elem) { + elem.second(window_.hasFocus(), 0); + }); ImGui::SFML::Render(window_); return; } @@ -211,6 +215,17 @@ void Overlay::update() closeOverlayButton(); } + std::ranges::for_each(FORCED_OVERLAY_ELEMS_, [this](const auto& elem) { + ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.05f, 0.07f, 0.07f, 0.95f)); + ImGui::SetNextWindowPos({ + ImGui::GetMainViewport()->Size.x * 0.5f, + ImGui::GetMainViewport()->Size.y * 0.5f + }, ImGuiCond_Always, + {0.5f, 0.5f}); + elem.second(window_.hasFocus(), 0); + ImGui::PopStyleColor(); + }); + ImGui::SFML::Render(window_); } @@ -229,9 +244,14 @@ void Overlay::AddLog(const spdlog::details::log_msg& msg) LOG_MSGS_.push_back({.time = msg.time, .level = msg.level, .payload = msg.payload.data()}); } -int Overlay::AddOverlayElem(const std::function& elem_fn) +int Overlay::AddOverlayElem(const std::function& elem_fn, bool force_show) { - OVERLAY_ELEMS_.insert({overlay_element_id_, elem_fn}); + if (force_show) { + FORCED_OVERLAY_ELEMS_.insert({overlay_element_id_, elem_fn}); + } + else { + OVERLAY_ELEMS_.insert({overlay_element_id_, elem_fn}); + } // keep this non confusing, but longer... const auto res = overlay_element_id_; overlay_element_id_++; @@ -240,7 +260,10 @@ int Overlay::AddOverlayElem(const std::function& elem_fn); + static int AddOverlayElem(const std::function& elem_fn, bool force_show_ = false); static void RemoveOverlayElem(int id); private: @@ -71,6 +71,8 @@ class Overlay { static inline int overlay_element_id_ = 0; static inline std::map> OVERLAY_ELEMS_; + static inline std::map> FORCED_OVERLAY_ELEMS_; + #ifdef _WIN32 std::string config_file_name_; #endif diff --git a/GlosSITarget/Resource.rc b/GlosSITarget/Resource.rc index 8346603..ba91c46 100644 --- a/GlosSITarget/Resource.rc +++ b/GlosSITarget/Resource.rc @@ -51,8 +51,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,1,2,0018002705604 - PRODUCTVERSION 0,1,2,0018002705604 + FILEVERSION 0,1,2,0031000204300 + PRODUCTVERSION 0,1,2,0031000204300 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -69,12 +69,12 @@ BEGIN BEGIN VALUE "CompanyName", "Peter Repukat - FlatspotSoftware" VALUE "FileDescription", "GlosSI - SteamTarget" - VALUE "FileVersion", "0.1.2.0-18-g27056b4" + VALUE "FileVersion", "0.1.2.0-31-gd2b43ff" VALUE "InternalName", "GlosSITarget" VALUE "LegalCopyright", "Copyright (C) 2021-2022 Peter Repukat - FlatspotSoftware" VALUE "OriginalFilename", "GlosSITarget.exe" VALUE "ProductName", "GlosSI" - VALUE "ProductVersion", "0.1.2.0-18-g27056b4" + VALUE "ProductVersion", "0.1.2.0-31-gd2b43ff" END END BLOCK "VarFileInfo" diff --git a/GlosSITarget/SteamTarget.cpp b/GlosSITarget/SteamTarget.cpp index 70925ed..c52ec56 100644 --- a/GlosSITarget/SteamTarget.cpp +++ b/GlosSITarget/SteamTarget.cpp @@ -46,14 +46,6 @@ SteamTarget::SteamTarget() server_(launcher_, [this] { run_ = false; }) { target_window_handle_ = window_.getSystemHandle(); -#ifdef _WIN32 - if (Settings::common.no_uwp_overlay) { - UWPOverlayEnabler::AddUwpOverlayOvWidget(); - } - else { - UWPOverlayEnabler::EnableUwpOverlay(); - } -#endif } int SteamTarget::run() @@ -67,93 +59,43 @@ int SteamTarget::run() spdlog::error("No game id set for standalone mode. Controller will use desktop-config!"); } - SetEnvironmentVariable(L"SteamAppId", L"0"); - SetEnvironmentVariable(L"SteamClientLaunch", L"0"); - SetEnvironmentVariable(L"SteamEnv", L"1"); - SetEnvironmentVariable(L"SteamPath", steam_path_.wstring().c_str()); - SetEnvironmentVariable(L"SteamTenfoot", Settings::common.standaloneUseGamepadUI ? L"1" : L"0"); - // SetEnvironmentVariable(L"SteamTenfootHybrid", L"1"); - SetEnvironmentVariable(L"SteamGamepadUI", Settings::common.standaloneUseGamepadUI ? L"1" : L"0"); - SetEnvironmentVariable(L"SteamGameId", Settings::common.standaloneModeGameId.c_str()); - SetEnvironmentVariable(L"SteamOverlayGameId", Settings::common.standaloneModeGameId.c_str()); - SetEnvironmentVariable(L"EnableConfiguratorSupport", L"15"); - SetEnvironmentVariable(L"SteamStreamingForceWindowedD3D9", L"1"); - - if (Settings::common.standaloneUseGamepadUI) { - system("start steam://open/bigpicture"); - auto steamwindow = FindWindow(L"Steam Big Picture Mode", nullptr); - auto timer = sf::Clock{}; - while (!steamwindow && timer.getElapsedTime().asSeconds() < 2) { - steamwindow = FindWindow(L"Steam Big Picture Mode", nullptr); - Sleep(50); + std::vector> end_frame_callbacks; + + if (!util::steam::getXBCRebindingEnabled(steam_path_, steam_user_id_)) { + auto overlay_id = std::make_shared(-1); + *overlay_id = Overlay::AddOverlayElem( + [this, overlay_id, &end_frame_callbacks](bool window_has_focus, ImGuiID dockspace_id) { + can_fully_initialize_ = false; + ImGui::Begin("XBox Controller configuration support Disabled", nullptr, ImGuiWindowFlags_NoSavedSettings); + ImGui::TextColored({1.f, 0.8f, 0.f, 1.f}, "XBox Controller configuration support is disabled in Steam. Please enable it in Steam Settings."); + if (ImGui::Button("OK")) { + can_fully_initialize_ = true; + if (*overlay_id != -1) { + end_frame_callbacks.emplace_back([this, overlay_id] { + Overlay::RemoveOverlayElem(*overlay_id); + }); + } } - Sleep(6000); // DIRTY HACK to wait until BPM (GamepadUI) is initialized - // TODO: find way to force BPM even if BPM is not active - LoadLibrary((steam_path_ / "GameOverlayRenderer64.dll").wstring().c_str()); - - // Overlay switches back to desktop one, once BPM is closed... Disable closing BPM for now. - // TODO: find way to force BPM even if BPM is not active - // closeBPM = true; - closeBPMTimer.restart(); - } - else { - LoadLibrary((steam_path_ / "GameOverlayRenderer64.dll").wstring().c_str()); - } - - window_.setClickThrough(true); - if (!overlay_.expired()) - overlay_.lock()->setEnabled(false); - steam_overlay_present_ = true; - } - } - else { - spdlog::info("Steam-overlay detected."); - spdlog::warn("Double press Steam- overlay key(s)/Controller button to show GlosSI-overlay"); // Just to color output and really get users attention - window_.setClickThrough(true); - if (!overlay_.expired()) - overlay_.lock()->setEnabled(false); - steam_overlay_present_ = true; - -#ifdef WIN32 - if (!Settings::common.disable_watchdog) { - wchar_t buff[MAX_PATH]; - GetModuleFileName(GetModuleHandle(NULL), buff, MAX_PATH); - std::wstring watchDogPath(buff); - watchDogPath = watchDogPath.substr(0, 1 + watchDogPath.find_last_of(L'\\')) + L"GlosSIWatchdog.dll"; - - DllInjector::injectDllInto(watchDogPath, L"explorer.exe"); - } -#endif + ImGui::End(); + }, + true); + can_fully_initialize_ = false; } - util::steam::getXBCRebindingEnabled(steam_path_, steam_user_id_); run_ = true; -#ifdef _WIN32 - hidhide_.hideDevices(steam_path_); - input_redirector_.run(); -#endif - - if (Settings::launch.launch) { - launcher_.launchApp(Settings::launch.launchPath, Settings::launch.launchAppArgs); - } - - keepControllerConfig(true); - const auto tray = createTrayMenu(); server_.run(); while (run_) { + if (!fully_initialized_ && can_fully_initialize_) { + init_FuckingRenameMe(); + } detector_.update(); overlayHotkeyWorkaround(); window_.update(); - if (closeBPM && closeBPMTimer.getElapsedTime().asSeconds() >= 3) { - system("start steam://close/bigpicture"); - closeBPM = false; - } - // Wait on shutdown; User might get confused if window closes to fast if anything with launchApp get's borked. if (delayed_shutdown_) { if (delay_shutdown_clock_.getElapsedTime().asSeconds() >= 3) { @@ -161,17 +103,25 @@ int SteamTarget::run() } } else { - launcher_.update(); + if (fully_initialized_) { + launcher_.update(); + } } + for (auto& efc : end_frame_callbacks) { + efc(); + } + end_frame_callbacks.clear(); } tray->exit(); server_.stop(); + if (fully_initialized_) { #ifdef _WIN32 - input_redirector_.stop(); - hidhide_.disableHidHide(); + input_redirector_.stop(); + hidhide_.disableHidHide(); #endif - launcher_.close(); + launcher_.close(); + } return 0; } @@ -262,6 +212,93 @@ void SteamTarget::focusWindow(WindowHandle hndl) #endif } +void SteamTarget::init_FuckingRenameMe() +{ + if (!SteamOverlayDetector::IsSteamInjected()) { + if (Settings::common.allowStandAlone) { + spdlog::warn("GlosSI not launched via Steam.\nEnabling EXPERIMENTAL global controller and overlay..."); + if (Settings::common.standaloneModeGameId == L"") { + spdlog::error("No game id set for standalone mode. Controller will use desktop-config!"); + } + + SetEnvironmentVariable(L"SteamAppId", L"0"); + SetEnvironmentVariable(L"SteamClientLaunch", L"0"); + SetEnvironmentVariable(L"SteamEnv", L"1"); + SetEnvironmentVariable(L"SteamPath", steam_path_.wstring().c_str()); + SetEnvironmentVariable(L"SteamTenfoot", Settings::common.standaloneUseGamepadUI ? L"1" : L"0"); + // SetEnvironmentVariable(L"SteamTenfootHybrid", L"1"); + SetEnvironmentVariable(L"SteamGamepadUI", Settings::common.standaloneUseGamepadUI ? L"1" : L"0"); + SetEnvironmentVariable(L"SteamGameId", Settings::common.standaloneModeGameId.c_str()); + SetEnvironmentVariable(L"SteamOverlayGameId", Settings::common.standaloneModeGameId.c_str()); + SetEnvironmentVariable(L"EnableConfiguratorSupport", L"15"); + SetEnvironmentVariable(L"SteamStreamingForceWindowedD3D9", L"1"); + + if (Settings::common.standaloneUseGamepadUI) { + system("start steam://open/bigpicture"); + auto steamwindow = FindWindow(L"Steam Big Picture Mode", nullptr); + auto timer = sf::Clock{}; + while (!steamwindow && timer.getElapsedTime().asSeconds() < 2) { + steamwindow = FindWindow(L"Steam Big Picture Mode", nullptr); + Sleep(50); + } + Sleep(6000); // DIRTY HACK to wait until BPM (GamepadUI) is initialized + // TODO: find way to force BPM even if BPM is not active + LoadLibrary((steam_path_ / "GameOverlayRenderer64.dll").wstring().c_str()); + + // Overlay switches back to desktop one, once BPM is closed... Disable closing BPM for now. + // TODO: find way to force BPM even if BPM is not active + // closeBPM = true; + // closeBPMTimer.restart(); + } + else { + LoadLibrary((steam_path_ / "GameOverlayRenderer64.dll").wstring().c_str()); + } + + window_.setClickThrough(true); + steam_overlay_present_ = true; + } + else { + spdlog::warn("Steam-overlay not detected and global mode disabled. Showing GlosSI-overlay!\n\ +Application will not function!"); + window_.setClickThrough(false); + if (!overlay_.expired()) + overlay_.lock()->setEnabled(true); + steam_overlay_present_ = false; + } + } + else { + spdlog::info("Steam-overlay detected."); + spdlog::warn("Double press Steam- overlay key(s)/Controller button to show GlosSI-overlay"); // Just to color output and really get users attention + window_.setClickThrough(true); + steam_overlay_present_ = true; + } + +#ifdef WIN32 + if (!Settings::common.disable_watchdog) { + wchar_t buff[MAX_PATH]; + GetModuleFileName(GetModuleHandle(NULL), buff, MAX_PATH); + std::wstring watchDogPath(buff); + watchDogPath = watchDogPath.substr(0, 1 + watchDogPath.find_last_of(L'\\')) + L"GlosSIWatchdog.dll"; + + DllInjector::injectDllInto(watchDogPath, L"explorer.exe"); + } + + if (Settings::common.no_uwp_overlay) { + UWPOverlayEnabler::AddUwpOverlayOvWidget(); + } + else { + UWPOverlayEnabler::EnableUwpOverlay(); + } + + hidhide_.hideDevices(steam_path_); + input_redirector_.run(); +#endif + if (Settings::launch.launch) { + launcher_.launchApp(Settings::launch.launchPath, Settings::launch.launchAppArgs); + } + keepControllerConfig(true); + fully_initialized_ = true; +} /* * The "magic" that keeps a controller-config forced (without hooking into Steam) @@ -287,6 +324,7 @@ void SteamTarget::keepControllerConfig(bool keep) spdlog::error("Couldn't un-install GetForegroundWindow hook!"); } } + #endif } diff --git a/GlosSITarget/SteamTarget.h b/GlosSITarget/SteamTarget.h index 2aea62f..70dc70b 100644 --- a/GlosSITarget/SteamTarget.h +++ b/GlosSITarget/SteamTarget.h @@ -51,6 +51,9 @@ class SteamTarget { std::wstring steam_user_id_ = util::steam::getSteamUserId(); bool steam_overlay_present_ = false; + bool fully_initialized_ = false; + bool can_fully_initialize_ = true; + void init_FuckingRenameMe(); // Keep controllerConfig even is window is switched. // On Windoze hooking "GetForeGroundWindow" is enough;