diff --git a/GlosSITarget/AppLauncher.cpp b/GlosSITarget/AppLauncher.cpp index 06c7f7b..fb1d452 100644 --- a/GlosSITarget/AppLauncher.cpp +++ b/GlosSITarget/AppLauncher.cpp @@ -21,6 +21,8 @@ limitations under the License. #include #include #endif +#include "Settings.h" + #include AppLauncher::AppLauncher(std::function shutdown) : shutdown_(std::move(shutdown)) @@ -32,7 +34,17 @@ AppLauncher::AppLauncher(std::function shutdown) : shutdown_(std::move(s void AppLauncher::launchApp(const std::wstring& path, const std::wstring& args) { - launchWin32App(path, args); +#ifdef _WIN32 + std::wsmatch m; + if (!std::regex_search(path, m, std::wregex(L"^.{1,3}:"))) { + spdlog::info("LaunchApp is UWP, launching..."); + launchUWPApp(path.data()); + } + else { + spdlog::info("LaunchApp is Win32, launching..."); + launchWin32App(path, args); + } +#endif } void AppLauncher::update() @@ -41,12 +53,20 @@ void AppLauncher::update() #ifdef _WIN32 if (process_info.dwProcessId > 0) { if (!IsProcessRunning(process_info.dwProcessId)) { - shutdown_(); + spdlog::info("Launched App with PID \"{}\" died", process_info.dwProcessId); + if (Settings::launch.closeOnExit) { + spdlog::info("Configured to close on exit. Shutting down.."); + shutdown_(); + } } } if (uwp_pid_ > 0) { if (!IsProcessRunning(uwp_pid_)) { - shutdown_(); + spdlog::info("Launched App with PID \"{}\" died", uwp_pid_); + if (Settings::launch.closeOnExit) { + spdlog::info("Configured to close on exit. Shutting down..."); + shutdown_(); + } } } #endif @@ -124,10 +144,10 @@ void AppLauncher::launchWin32App(const std::wstring& path, const std::wstring& a launch_dir.empty() ? nullptr : launch_dir.data(), &info, &process_info)) { - spdlog::info(L"Started Program: \"{}\" in directory: {}", native_seps_path, launch_dir); + spdlog::info(L"Started Program: \"{}\" in directory: \"{}\"", native_seps_path, launch_dir); } else { - spdlog::error(L"Couldn't start program: \"{}\" in directory: {}", native_seps_path, launch_dir); + spdlog::error(L"Couldn't start program: \"{}\" in directory: \"{}\"", native_seps_path, launch_dir); } } diff --git a/GlosSITarget/GlosSITarget.vcxproj b/GlosSITarget/GlosSITarget.vcxproj index 1943438..de01efe 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;..\deps\imgui;..\deps\imgui-sfml;$(ExternalIncludePath) + ..\deps\SFML\include;..\deps\WinReg;..\deps\spdlog\include;..\deps\ValveFileVDF;..\deps\subhook;..\deps\ViGEmClient\include;..\deps\imgui;..\deps\imgui-sfml;..\deps\json\include;$(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;..\deps\imgui;..\deps\imgui-sfml;$(ExternalIncludePath) + ..\deps\SFML\include;..\deps\WinReg;..\deps\spdlog\include;..\deps\ValveFileVDF;..\deps\subhook;..\deps\ViGEmClient\include;..\deps\imgui;..\deps\imgui-sfml;..\deps\json\include;$(ExternalIncludePath) ..\deps\SFML\out\build\x64-Release\lib;..\deps\ViGEmClient\lib\release\x64;$(LibraryPath) @@ -182,6 +182,7 @@ + @@ -198,6 +199,7 @@ true + diff --git a/GlosSITarget/GlosSITarget.vcxproj.filters b/GlosSITarget/GlosSITarget.vcxproj.filters index 14718e6..7356fef 100644 --- a/GlosSITarget/GlosSITarget.vcxproj.filters +++ b/GlosSITarget/GlosSITarget.vcxproj.filters @@ -116,11 +116,17 @@ Header Files + + Header Files + + + Source Files + \ No newline at end of file diff --git a/GlosSITarget/HidHide.cpp b/GlosSITarget/HidHide.cpp index 3d09bf7..b96cc3b 100644 --- a/GlosSITarget/HidHide.cpp +++ b/GlosSITarget/HidHide.cpp @@ -31,6 +31,7 @@ limitations under the License. #include // #include "Overlay.h" +#include "Settings.h" #include #include @@ -122,20 +123,24 @@ void HidHide::hideDevices(const std::filesystem::path& steam_path) } } } - // TODO: remove all vigem controllers added by GlosSI - setBlacklistDevices(blacklisted_devices_); - setActive(true); + if (Settings::devices.hideDevices) { + // TODO: MAXBE: remove all vigem controllers added by GlosSI + setBlacklistDevices(blacklisted_devices_); + setActive(true); + spdlog::info("Hid Gaming Devices; Enabling Overlay element..."); + enableOverlayElement(); + } closeCtrlDevice(); - spdlog::info("Hid Gaming Devices; Enabling Overlay element..."); - enableOverlayElement(); } void HidHide::disableHidHide() { - openCtrlDevice(); - setActive(false); - closeCtrlDevice(); - spdlog::info("Un-hid Gaming Devices"); + openCtrlDevice(); + if (getActive()) { + setActive(false); + spdlog::info("Un-hid Gaming Devices"); + } + closeCtrlDevice(); } void HidHide::UnPatchValveHooks() diff --git a/GlosSITarget/Settings.h b/GlosSITarget/Settings.h new file mode 100644 index 0000000..809cb1f --- /dev/null +++ b/GlosSITarget/Settings.h @@ -0,0 +1,100 @@ +/* +Copyright 2021 Peter Repukat - FlatspotSoftware + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +#pragma once + +#include +#include +#include +#include + +namespace Settings { + + +inline struct Launch { + bool launch = false; + std::wstring launchPath; + std::wstring launchAppArgs; + bool closeOnExit = true; +} launch; + +inline struct Devices { + bool hideDevices = true; +} devices; + +inline struct Window { + bool windowMode = false; + int maxFps = 0; + float scale = 0.f; +} window; + +inline void Parse(const std::string& arg1) +{ + std::ifstream json_file; + json_file.open(arg1); + if (!json_file.is_open()) { + spdlog::error("Couldn't open settings file {}", arg1); + return; + } + const auto json = nlohmann::json::parse(json_file); + if (json["version"] != 1) { // TODO: versioning stuff + spdlog::warn("Config version doesn't match application version."); + } + + // TODO: make this as much generic as fits in about the same amount of code if one would parse every value separately. + + auto safeParseValue = [](const auto& object, const auto& key, auto& value) { + try { + if (object[key].is_null()) { + return; + } + value = object[key]; + } catch (const nlohmann::json::exception& e) { + spdlog::error("Err parsing \"{}\"; {}", key, e.what()); + } + }; + + auto safeWStringParse = [&safeParseValue](const auto& object, const auto& key, std::wstring& value) { + std::string meh; + safeParseValue(object, key, meh); + if (!meh.empty()) { + value.clear(); + std::ranges::transform(meh, std::back_inserter(value), [](const auto& ch) { + return static_cast(ch); + }); + } + }; + + if (auto launchconf = json["launch"]; launchconf.is_object()) { + safeParseValue(launchconf, "launch", launch.launch); + safeWStringParse(launchconf, "launchPath", launch.launchPath); + safeWStringParse(launchconf, "launchAppArgs", launch.launchAppArgs); + safeParseValue(launchconf, "closeOnExit", launch.closeOnExit); + } + + if (auto devconf = json["devices"]; devconf.is_object()) { + safeParseValue(devconf, "hideDevices", devices.hideDevices); + } + + if (auto winconf = json["window"]; winconf.is_object()) { + safeParseValue(winconf, "windowMode", window.windowMode); + safeParseValue(winconf, "maxFps", window.maxFps); + safeParseValue(winconf, "scale", window.scale); + } + + json_file.close(); +} + +} // namespace Settings diff --git a/GlosSITarget/SteamTarget.cpp b/GlosSITarget/SteamTarget.cpp index 3da13b5..e1688e1 100644 --- a/GlosSITarget/SteamTarget.cpp +++ b/GlosSITarget/SteamTarget.cpp @@ -15,6 +15,7 @@ limitations under the License. */ #include "SteamTarget.h" +#include "Settings.h" #include "steam_sf_keymap.h" #include @@ -24,12 +25,14 @@ limitations under the License. #include #include - SteamTarget::SteamTarget(int argc, char* argv[]) : window_([this] { run_ = false; }, getScreenshotHotkey()), overlay_(window_.getOverlay()), detector_([this](bool overlay_open) { onOverlayChanged(overlay_open); }), - launcher_([this] { run_ = false; }) + launcher_([this] { + delayed_shutdown_ = true; + delay_shutdown_clock_.restart(); + }) { target_window_handle_ = window_.getSystemHandle(); } @@ -58,14 +61,23 @@ Application will not function!"); input_redirector_.run(); #endif - // launcher_.launchApp(L"1234"); // TODO + if (Settings::launch.launch) { + launcher_.launchApp(Settings::launch.launchPath, Settings::launch.launchAppArgs); + } keepControllerConfig(true); while (run_) { detector_.update(); window_.update(); overlayHotkeyWorkaround(); - launcher_.update(); + // 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) { + run_ = false; + } + } else { + launcher_.update(); + } } #ifdef _WIN32 diff --git a/GlosSITarget/SteamTarget.h b/GlosSITarget/SteamTarget.h index 2f1d7e0..161e7dc 100644 --- a/GlosSITarget/SteamTarget.h +++ b/GlosSITarget/SteamTarget.h @@ -85,6 +85,9 @@ class SteamTarget { uint32_t overlay_trigger_max_seconds_ = 4; bool overlay_trigger_flag_ = false; + bool delayed_shutdown_ = false; + sf::Clock delay_shutdown_clock_; + static constexpr std::wstring_view user_data_path_ = L"/userdata/"; static constexpr std::wstring_view config_file_name_ = L"/config/localconfig.vdf"; diff --git a/GlosSITarget/TargetWindow.cpp b/GlosSITarget/TargetWindow.cpp index 3bd817d..bd55d40 100644 --- a/GlosSITarget/TargetWindow.cpp +++ b/GlosSITarget/TargetWindow.cpp @@ -28,6 +28,8 @@ limitations under the License. #include #include +#include "Settings.h" + #if !defined(WM_DPICHANGED) #define WM_DPICHANGED 0x02E0 #endif @@ -40,14 +42,17 @@ TargetWindow::TargetWindow(std::function on_close, std::vector on_close, std::vector 0) { + setFpsLimit(Settings::window.maxFps); + } + if (Settings::window.scale > 0.3f) { // Now that's just getting ridicoulus + ImGuiIO& io = ImGui::GetIO(); + io.FontGlobalScale = Settings::window.scale; + ImGui::SFML::UpdateFontTexture(); + } + } void TargetWindow::setFpsLimit(unsigned int fps_limit) @@ -94,7 +109,9 @@ void TargetWindow::setFpsLimit(unsigned int fps_limit) void TargetWindow::setClickThrough(bool click_through) { - + if (Settings::window.windowMode) { + return; + } #ifdef _WIN32 HWND hwnd = window_.getSystemHandle(); if (click_through) { diff --git a/GlosSITarget/example_conf.json b/GlosSITarget/example_conf.json new file mode 100644 index 0000000..df5033d --- /dev/null +++ b/GlosSITarget/example_conf.json @@ -0,0 +1,17 @@ +{ + "version": 1, + "launch": { + "launch": true, + "launchPath": "C:\\Users\\Alia5\\AppData\\Local\\Programs\\Microsoft VS Code\\Code.exe", + "launchAppArgs": "--new-window", + "closeOnExit": true + }, + "devices": { + "hideDevices": true + }, + "window": { + "windowMode": false, + "maxFps": null, + "scale": null + } +} \ No newline at end of file diff --git a/GlosSITarget/main.cpp b/GlosSITarget/main.cpp index a31d386..b2e2588 100644 --- a/GlosSITarget/main.cpp +++ b/GlosSITarget/main.cpp @@ -24,6 +24,7 @@ limitations under the License. #include #include #include "OverlayLogSink.h" +#include "Settings.h" #ifdef _WIN32 @@ -62,8 +63,10 @@ int main(int argc, char* argv[]) logger->flush_on(spdlog::level::info); spdlog::set_default_logger(logger); #ifdef _WIN32 + Settings::Parse(__argv[1]); SteamTarget target(__argc, __argv); #else + Settings::Parse(argv[1]); SteamTarget target(argc, argv); #endif const auto exit = target.run();