2021-06-11 19:24:52 +02:00
// MassBuilderSaveTool
2023-09-02 18:30:29 +02:00
// Copyright (C) 2021-2023 Guillaume Jacquemin
2021-06-11 19:24:52 +02:00
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
2021-07-21 14:36:49 +02:00
# include <Corrade/Containers/ScopeGuard.h>
2021-06-11 19:24:52 +02:00
# include <Corrade/Utility/Unicode.h>
2021-08-18 17:16:10 +02:00
# include <Magnum/GL/DebugOutput.h>
2021-06-11 19:24:52 +02:00
# include <Magnum/GL/DefaultFramebuffer.h>
2021-08-18 17:16:10 +02:00
# include <Magnum/GL/Extensions.h>
2021-06-11 19:24:52 +02:00
# include <Magnum/GL/Renderer.h>
# include <Magnum/ImGuiIntegration/Integration.h>
# include <Magnum/ImGuiIntegration/Context.hpp>
2022-11-21 09:49:01 +01:00
# include <SDL.h>
2023-10-29 11:32:17 +01:00
# include <wtypesbase.h>
2021-06-11 19:24:52 +02:00
# include <shellapi.h>
2021-07-21 14:36:49 +02:00
# include <wtsapi32.h>
2021-06-11 19:24:52 +02:00
# include "../FontAwesome/IconsFontAwesome5.h"
2022-12-01 23:42:39 +01:00
# include "../Configuration/Configuration.h"
2022-11-22 10:34:25 +01:00
# include "../Logger/Logger.h"
2021-06-11 19:24:52 +02:00
2023-11-29 12:33:26 +01:00
# include "Application.h"
2022-03-04 21:18:55 +01:00
using namespace Containers : : Literals ;
2021-06-11 19:24:52 +02:00
extern const ImVec2 center_pivot = { 0.5f , 0.5f } ;
2021-07-13 18:35:23 +02:00
# ifdef SAVETOOL_DEBUG_BUILD
2021-06-11 19:24:52 +02:00
Utility : : Tweakable tweak ;
# endif
2023-11-29 12:33:26 +01:00
namespace mbst {
Application : : Application ( const Arguments & arguments ) :
2021-06-11 19:24:52 +02:00
Platform : : Sdl2Application { arguments ,
2023-10-29 10:40:02 +01:00
Configuration { } . setTitle ( " M.A.S.S. Builder Save Tool " SAVETOOL_VERSION_STRING " ( \" " SAVETOOL_CODENAME " \" ) " )
2021-06-11 19:24:52 +02:00
. setSize ( { 960 , 720 } ) }
{
2022-11-21 20:37:28 +01:00
# ifdef SAVETOOL_DEBUG_BUILD
2022-12-01 23:38:54 +01:00
tweak . enable ( " " , " ../../ " ) ;
2022-11-21 20:37:28 +01:00
# endif
2021-06-11 19:24:52 +02:00
2023-09-02 14:28:28 +02:00
LOG_INFO_FORMAT ( " Framebuffer size: {}x{} " , framebufferSize ( ) . x ( ) , framebufferSize ( ) . y ( ) ) ;
LOG_INFO_FORMAT ( " Window size: {}x{} " , windowSize ( ) . x ( ) , windowSize ( ) . y ( ) ) ;
LOG_INFO_FORMAT ( " DPI scaling: {}x{} " , dpiScaling ( ) . x ( ) , dpiScaling ( ) . y ( ) ) ;
2022-11-22 10:34:25 +01:00
LOG_INFO ( " Configuring OpenGL renderer. " ) ;
2021-06-11 19:24:52 +02:00
GL : : Renderer : : enable ( GL : : Renderer : : Feature : : Blending ) ;
GL : : Renderer : : enable ( GL : : Renderer : : Feature : : ScissorTest ) ;
GL : : Renderer : : setBlendFunction ( GL : : Renderer : : BlendFunction : : SourceAlpha ,
GL : : Renderer : : BlendFunction : : OneMinusSourceAlpha ) ;
GL : : Renderer : : setBlendEquation ( GL : : Renderer : : BlendEquation : : Add ,
GL : : Renderer : : BlendEquation : : Add ) ;
2022-11-22 10:34:25 +01:00
LOG_INFO ( " Configuring SDL2. " ) ;
2022-11-25 11:46:47 +01:00
# if SDL_VERSION_ATLEAST(2,0,5)
if ( SDL_SetHintWithPriority ( SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH , " 1 " , SDL_HINT_OVERRIDE ) = = SDL_TRUE ) {
LOG_INFO ( " Clickthrough is enabled. " ) ;
2022-03-30 14:18:08 +02:00
}
2022-11-22 10:34:25 +01:00
else {
2022-11-25 11:46:47 +01:00
LOG_WARNING ( " Clickthrough is disabled. " ) ;
2022-11-22 10:34:25 +01:00
}
2022-11-25 11:46:47 +01:00
# else
LOG_WARNING_FORMAT ( " Clickthrough is disabled: SDL2 version is too old ({}.{}.{}) " ,
SDL_MAJOR_VERSION , SDL_MINOR_VERSION , SDL_PATCHLEVEL ) ;
# endif
2021-06-11 19:24:52 +02:00
2022-11-22 10:34:25 +01:00
LOG_INFO ( " Registering custom events. " ) ;
2022-12-05 11:32:18 +01:00
if ( ( _initEventId = SDL_RegisterEvents ( 3 ) ) = = std : : uint32_t ( - 1 ) ) {
2021-06-11 19:24:52 +02:00
SDL_ShowSimpleMessageBox ( SDL_MESSAGEBOX_ERROR , " Error " ,
2023-11-29 12:33:26 +01:00
" SDL_RegisterEvents() failed in Application::SaveTool(). Exiting... " , window ( ) ) ;
2021-07-21 14:36:49 +02:00
exit ( EXIT_FAILURE ) ;
2021-07-22 11:39:53 +02:00
return ;
2021-07-21 14:36:49 +02:00
}
2021-07-22 11:39:53 +02:00
_updateEventId = _initEventId + 1 ;
2022-03-09 13:27:45 +01:00
_fileEventId = _initEventId + 2 ;
2021-07-22 11:39:53 +02:00
2022-11-22 10:34:25 +01:00
LOG_INFO ( " Initialising the timer subsystem. " ) ;
2022-03-30 14:18:08 +02:00
if ( SDL_InitSubSystem ( SDL_INIT_TIMER ) ! = 0 ) {
2022-11-22 10:34:25 +01:00
LOG_ERROR ( SDL_GetError ( ) ) ;
SDL_ShowSimpleMessageBox ( SDL_MESSAGEBOX_ERROR , " Error initialising the app " ,
SDL_GetError ( ) , window ( ) ) ;
2022-03-30 14:18:08 +02:00
exit ( EXIT_FAILURE ) ;
return ;
}
initialiseGui ( ) ;
if ( ! initialiseToolDirectories ( ) ) {
2022-11-22 10:34:25 +01:00
SDL_ShowSimpleMessageBox ( SDL_MESSAGEBOX_ERROR , " Error initialising the app " ,
_lastError . data ( ) , window ( ) ) ;
2021-07-21 14:36:49 +02:00
exit ( EXIT_FAILURE ) ;
2021-07-22 11:39:53 +02:00
return ;
2021-07-21 14:36:49 +02:00
}
2022-03-30 14:18:08 +02:00
if ( ! findGameDataDirectory ( ) ) {
2022-11-22 10:34:25 +01:00
SDL_ShowSimpleMessageBox ( SDL_MESSAGEBOX_ERROR , " Error initialising the app " ,
_lastError . data ( ) , window ( ) ) ;
2021-07-21 14:36:49 +02:00
exit ( EXIT_FAILURE ) ;
2021-07-22 11:39:53 +02:00
return ;
2021-07-21 14:36:49 +02:00
}
checkGameState ( ) ;
_gameCheckTimerId = SDL_AddTimer ( 2000 ,
2022-12-05 11:32:18 +01:00
[ ] ( std : : uint32_t interval , void * param ) - > std : : uint32_t {
2023-11-29 12:33:26 +01:00
static_cast < Application * > ( param ) - > checkGameState ( ) ;
2021-07-21 14:36:49 +02:00
return interval ;
2022-03-04 21:18:55 +01:00
} , this ) ;
2021-07-21 14:36:49 +02:00
if ( _gameCheckTimerId = = 0 ) {
2022-11-22 10:34:25 +01:00
LOG_ERROR ( SDL_GetError ( ) ) ;
2021-07-21 14:36:49 +02:00
SDL_ShowSimpleMessageBox ( SDL_MESSAGEBOX_ERROR , " Error " , SDL_GetError ( ) , window ( ) ) ;
2021-06-11 19:24:52 +02:00
exit ( EXIT_FAILURE ) ;
2021-07-22 11:39:53 +02:00
return ;
2021-06-11 19:24:52 +02:00
}
2021-07-23 14:17:42 +02:00
initialiseConfiguration ( ) ;
2021-07-28 14:17:21 +02:00
2022-12-01 23:42:39 +01:00
if ( conf ( ) . checkUpdatesOnStartup ( ) ) {
2022-03-04 21:18:55 +01:00
_queue . addToast ( Toast : : Type : : Default , " Checking for updates... " _s ) ;
2022-03-31 17:57:53 +02:00
_updateThread = std : : thread { [ this ] { checkForUpdates ( ) ; } } ;
2021-07-28 14:17:21 +02:00
}
2021-08-18 17:16:10 +02:00
if ( GL : : Context : : current ( ) . isExtensionSupported < GL : : Extensions : : KHR : : debug > ( ) & &
GL : : Context : : current ( ) . detectedDriver ( ) = = GL : : Context : : DetectedDriver : : NVidia )
{
GL : : DebugOutput : : setEnabled ( GL : : DebugOutput : : Source : : Api , GL : : DebugOutput : : Type : : Other , { 131185 } , false ) ;
}
2021-08-18 20:09:22 +02:00
2022-12-01 23:42:39 +01:00
if ( conf ( ) . skipDisclaimer ( ) ) {
2021-08-18 20:09:22 +02:00
_uiState = UiState : : Initialising ;
_initThread = std : : thread { [ this ] { initialiseManager ( ) ; } } ;
}
2022-11-30 10:03:45 +01:00
_timeline . start ( ) ;
2021-06-11 19:24:52 +02:00
}
2023-11-29 12:33:26 +01:00
Application : : ~ Application ( ) {
2022-11-22 10:34:25 +01:00
LOG_INFO ( " Cleaning up. " ) ;
2022-03-30 14:18:08 +02:00
2021-06-11 19:24:52 +02:00
SDL_RemoveTimer ( _gameCheckTimerId ) ;
2021-07-23 14:17:42 +02:00
2022-11-22 10:34:25 +01:00
LOG_INFO ( " Saving the configuration. " ) ;
2022-03-30 14:18:08 +02:00
2022-12-01 23:42:39 +01:00
conf ( ) . save ( ) ;
2022-03-30 14:18:08 +02:00
2022-11-22 10:34:25 +01:00
LOG_INFO ( " Exiting. " ) ;
2021-06-11 19:24:52 +02:00
}
2022-12-03 16:49:39 +01:00
void
2023-11-29 12:33:26 +01:00
Application : : drawEvent ( ) {
2022-11-21 20:37:28 +01:00
# ifdef SAVETOOL_DEBUG_BUILD
2021-06-11 19:24:52 +02:00
tweak . update ( ) ;
2022-11-21 20:37:28 +01:00
# endif
2021-06-11 19:24:52 +02:00
GL : : defaultFramebuffer . clear ( GL : : FramebufferClear : : Color ) ;
drawImGui ( ) ;
swapBuffers ( ) ;
2022-11-30 10:03:45 +01:00
2022-12-01 23:42:39 +01:00
if ( conf ( ) . swapInterval ( ) = = 0 & & conf ( ) . fpsCap ( ) < 301.0f ) {
while ( _timeline . currentFrameDuration ( ) < ( 1.0f / conf ( ) . fpsCap ( ) ) ) ;
2022-11-30 10:03:45 +01:00
}
2021-06-11 19:24:52 +02:00
redraw ( ) ;
2022-11-30 10:03:45 +01:00
_timeline . nextFrame ( ) ;
2021-06-11 19:24:52 +02:00
}
2022-12-03 16:49:39 +01:00
void
2023-11-29 12:33:26 +01:00
Application : : viewportEvent ( ViewportEvent & event ) {
2021-06-11 19:24:52 +02:00
GL : : defaultFramebuffer . setViewport ( { { } , event . framebufferSize ( ) } ) ;
2022-11-25 11:46:14 +01:00
const Vector2 size = Vector2 { windowSize ( ) } / dpiScaling ( ) ;
_imgui . relayout ( size , windowSize ( ) , framebufferSize ( ) ) ;
2021-06-11 19:24:52 +02:00
}
2022-12-03 16:49:39 +01:00
void
2023-11-29 12:33:26 +01:00
Application : : keyPressEvent ( KeyEvent & event ) {
2021-06-11 19:24:52 +02:00
if ( _imgui . handleKeyPressEvent ( event ) ) return ;
}
2022-12-03 16:49:39 +01:00
void
2023-11-29 12:33:26 +01:00
Application : : keyReleaseEvent ( KeyEvent & event ) {
2021-06-11 19:24:52 +02:00
if ( _imgui . handleKeyReleaseEvent ( event ) ) return ;
}
2022-12-03 16:49:39 +01:00
void
2023-11-29 12:33:26 +01:00
Application : : mousePressEvent ( MouseEvent & event ) {
2021-06-11 19:24:52 +02:00
if ( _imgui . handleMousePressEvent ( event ) ) return ;
}
2022-12-03 16:49:39 +01:00
void
2023-11-29 12:33:26 +01:00
Application : : mouseReleaseEvent ( MouseEvent & event ) {
2021-06-11 19:24:52 +02:00
if ( _imgui . handleMouseReleaseEvent ( event ) ) return ;
}
2022-12-03 16:49:39 +01:00
void
2023-11-29 12:33:26 +01:00
Application : : mouseMoveEvent ( MouseMoveEvent & event ) {
2021-06-11 19:24:52 +02:00
if ( _imgui . handleMouseMoveEvent ( event ) ) return ;
}
2022-12-03 16:49:39 +01:00
void
2023-11-29 12:33:26 +01:00
Application : : mouseScrollEvent ( MouseScrollEvent & event ) {
2021-06-11 19:24:52 +02:00
if ( _imgui . handleMouseScrollEvent ( event ) ) {
event . setAccepted ( ) ;
return ;
}
}
2022-12-03 16:49:39 +01:00
void
2023-11-29 12:33:26 +01:00
Application : : textInputEvent ( TextInputEvent & event ) {
2021-06-11 19:24:52 +02:00
if ( _imgui . handleTextInputEvent ( event ) ) return ;
}
2022-12-03 16:49:39 +01:00
void
2023-11-29 12:33:26 +01:00
Application : : anyEvent ( SDL_Event & event ) {
2021-06-11 19:24:52 +02:00
if ( event . type = = _initEventId ) {
initEvent ( event ) ;
}
2021-07-22 11:39:53 +02:00
else if ( event . type = = _updateEventId ) {
updateCheckEvent ( event ) ;
}
2022-03-09 13:27:45 +01:00
else if ( event . type = = _fileEventId ) {
fileUpdateEvent ( event ) ;
}
2021-06-11 19:24:52 +02:00
}
2022-12-03 16:49:39 +01:00
void
2023-11-29 12:33:26 +01:00
Application : : drawImGui ( ) {
2021-06-11 19:24:52 +02:00
_imgui . newFrame ( ) ;
if ( ImGui : : GetIO ( ) . WantTextInput & & ! isTextInputActive ( ) ) {
startTextInput ( ) ;
}
else if ( ! ImGui : : GetIO ( ) . WantTextInput & & isTextInputActive ( ) ) {
stopTextInput ( ) ;
}
drawGui ( ) ;
_imgui . updateApplicationCursor ( * this ) ;
_imgui . drawFrame ( ) ;
}
2022-12-03 16:49:39 +01:00
void
2023-11-29 12:33:26 +01:00
Application : : drawGui ( ) {
2021-06-11 19:24:52 +02:00
drawMainMenu ( ) ;
2021-06-20 23:49:30 +02:00
switch ( _uiState ) {
case UiState : : Disclaimer :
drawDisclaimer ( ) ;
break ;
case UiState : : Initialising :
drawInitialisation ( ) ;
break ;
case UiState : : ProfileManager :
drawProfileManager ( ) ;
break ;
case UiState : : MainManager :
drawManager ( ) ;
break ;
2021-08-19 20:35:00 +02:00
case UiState : : MassViewer :
drawMassViewer ( ) ;
break ;
2021-06-11 19:24:52 +02:00
}
if ( _aboutPopup ) {
drawAbout ( ) ;
}
2022-11-21 20:37:28 +01:00
# ifdef SAVETOOL_DEBUG_BUILD
2021-06-11 19:24:52 +02:00
if ( _demoWindow ) {
ImGui : : ShowDemoWindow ( & _demoWindow ) ;
}
if ( _styleEditor ) {
ImGui : : ShowStyleEditor ( & ImGui : : GetStyle ( ) ) ;
}
if ( _metricsWindow ) {
ImGui : : ShowMetricsWindow ( & _metricsWindow ) ;
}
2022-11-21 20:37:28 +01:00
# endif
2021-07-25 10:52:54 +02:00
_queue . draw ( windowSize ( ) ) ;
2021-06-11 19:24:52 +02:00
}
2022-12-03 16:49:39 +01:00
void
2023-11-29 12:33:26 +01:00
Application : : drawDisclaimer ( ) {
2023-09-02 14:28:28 +02:00
ImGui : : SetNextWindowPos ( ImVec2 { Vector2 { windowSize ( ) / 2.0f } / dpiScaling ( ) } , ImGuiCond_Always , center_pivot ) ;
2021-06-11 19:24:52 +02:00
if ( ImGui : : Begin ( " Disclaimer##DisclaimerWindow " , nullptr ,
2021-07-25 10:52:54 +02:00
ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBringToFrontOnFocus |
2021-06-11 19:24:52 +02:00
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_MenuBar ) )
{
if ( ImGui : : BeginMenuBar ( ) ) {
ImGui : : TextUnformatted ( " Disclaimer " ) ;
ImGui : : EndMenuBar ( ) ;
}
ImGui : : TextUnformatted ( " Before you start using the app, there are a few things you should know: " ) ;
2022-11-21 20:37:28 +01:00
ImGui : : PushTextWrapPos ( float ( windowSize ( ) . x ( ) ) * 0.67f ) ;
2021-06-11 19:24:52 +02:00
ImGui : : Bullet ( ) ;
ImGui : : SameLine ( ) ;
2022-11-21 20:37:28 +01:00
ImGui : : TextUnformatted ( R " (For this application to work properly, it is recommended to disable Steam Cloud syncing for the game. To disable it, right-click the game in your Steam library, click " Properties " , go to the " General " tab, and uncheck " Keep game saves in the Steam Cloud for M . A . S . S . Builder " .) " ) ;
2021-06-11 19:24:52 +02:00
ImGui : : Bullet ( ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextUnformatted ( " The developer of this application (Guillaume Jacquemin) isn't associated with Vermillion Digital, and both parties cannot be held responsible for data loss or corruption this app might cause. PLEASE USE AT YOUR OWN RISK! " ) ;
ImGui : : Bullet ( ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextUnformatted ( " This application is released under the terms of the GNU General Public Licence version 3. Please see the COPYING file for more details, or the About screen if you somehow didn't get that file with your download of the program. " ) ;
ImGui : : Bullet ( ) ;
ImGui : : SameLine ( ) ;
2023-10-29 10:40:02 +01:00
ImGui : : TextUnformatted ( " This version of the application was tested on M.A.S.S. Builder early access version " SAVETOOL_SUPPORTED_GAME_VERSION " . It may or may not work with other versions of the game. " ) ;
2021-06-11 19:24:52 +02:00
2023-08-31 12:34:34 +02:00
if ( conf ( ) . isRunningInWine ( ) ) {
ImGui : : Bullet ( ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextUnformatted ( " You are currently running this application in Wine/Proton. It hasn't been fully tested, so some issues may arise. Furthermore, features may be unavailable. " ) ;
}
2021-06-11 19:24:52 +02:00
ImGui : : PopTextWrapPos ( ) ;
if ( ImGui : : BeginTable ( " ##DisclaimerLayoutTable " , 3 ) ) {
ImGui : : TableSetupColumn ( " ##Empty1 " , ImGuiTableColumnFlags_WidthStretch ) ;
ImGui : : TableSetupColumn ( " ##Button " , ImGuiTableColumnFlags_WidthFixed ) ;
ImGui : : TableSetupColumn ( " ##Empty2 " , ImGuiTableColumnFlags_WidthStretch ) ;
ImGui : : TableNextRow ( ) ;
2021-08-18 20:09:22 +02:00
ImGui : : TableSetColumnIndex ( 0 ) ;
ImGui : : Dummy ( { 0.0f , 5.0f } ) ;
ImGui : : Dummy ( { 4.0f , 0.0f } ) ;
ImGui : : SameLine ( ) ;
2022-12-01 23:42:39 +01:00
if ( drawCheckbox ( " Don't show next time " , conf ( ) . skipDisclaimer ( ) ) ) {
conf ( ) . setSkipDisclaimer ( ! conf ( ) . skipDisclaimer ( ) ) ;
}
2021-06-11 19:24:52 +02:00
ImGui : : TableSetColumnIndex ( 1 ) ;
ImGui : : PushStyleVar ( ImGuiStyleVar_FramePadding , { 24.0f , 12.0f } ) ;
if ( ImGui : : Button ( " I understand the risks " ) ) {
_uiState = UiState : : Initialising ;
2021-08-18 20:09:22 +02:00
_initThread = std : : thread { [ this ] { initialiseManager ( ) ; } } ;
2021-06-11 19:24:52 +02:00
}
ImGui : : PopStyleVar ( ) ;
ImGui : : EndTable ( ) ;
}
}
ImGui : : End ( ) ;
}
2022-12-03 16:49:39 +01:00
void
2023-11-29 12:33:26 +01:00
Application : : drawInitialisation ( ) {
2023-09-02 14:28:28 +02:00
ImGui : : SetNextWindowPos ( ImVec2 { Vector2 { windowSize ( ) / 2.0f } / dpiScaling ( ) } , ImGuiCond_Always , center_pivot ) ;
2021-06-11 19:24:52 +02:00
if ( ImGui : : BeginPopupModal ( " ##InitPopup " , nullptr ,
ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar ) )
{
ImGui : : TextUnformatted ( " Initialising the manager. Please wait... " ) ;
ImGui : : EndPopup ( ) ;
}
ImGui : : OpenPopup ( " ##InitPopup " ) ;
}
2022-12-03 16:49:39 +01:00
void
2023-11-29 12:33:26 +01:00
Application : : drawGameState ( ) {
2021-06-11 19:24:52 +02:00
ImGui : : TextUnformatted ( " Game state: " ) ;
ImGui : : SameLine ( ) ;
{
2021-07-21 14:36:49 +02:00
switch ( _gameState ) {
2021-06-11 19:24:52 +02:00
case GameState : : Unknown :
2021-06-20 19:36:42 +02:00
ImGui : : TextColored ( ImColor { 0xff00a5ff } , ICON_FA_CIRCLE ) ;
drawTooltip ( " unknown " ) ;
2021-06-11 19:24:52 +02:00
break ;
case GameState : : NotRunning :
2021-06-20 19:36:42 +02:00
ImGui : : TextColored ( ImColor { 0xff32cd32 } , ICON_FA_CIRCLE ) ;
drawTooltip ( " not running " ) ;
2021-06-11 19:24:52 +02:00
break ;
case GameState : : Running :
2021-06-20 19:36:42 +02:00
ImGui : : TextColored ( ImColor { 0xff0000ff } , ICON_FA_CIRCLE ) ;
drawTooltip ( " running " ) ;
2021-06-11 19:24:52 +02:00
break ;
}
}
}
2022-12-03 16:49:39 +01:00
void
2023-11-29 12:33:26 +01:00
Application : : drawHelpMarker ( Containers : : StringView text , float wrap_pos ) {
2021-06-11 19:24:52 +02:00
ImGui : : TextUnformatted ( ICON_FA_QUESTION_CIRCLE ) ;
drawTooltip ( text , wrap_pos ) ;
}
2022-12-03 16:49:39 +01:00
void
2023-11-29 12:33:26 +01:00
Application : : drawTooltip ( Containers : : StringView text , float wrap_pos ) {
2021-06-11 19:24:52 +02:00
if ( ImGui : : IsItemHovered ( ) ) {
ImGui : : BeginTooltip ( ) ;
if ( wrap_pos > 0.0f ) {
ImGui : : PushTextWrapPos ( wrap_pos ) ;
}
2024-02-08 11:08:14 +01:00
ImGui : : TextUnformatted ( text . cbegin ( ) , text . cend ( ) ) ;
2021-06-11 19:24:52 +02:00
if ( wrap_pos > 0.0f ) {
ImGui : : PopTextWrapPos ( ) ;
}
ImGui : : EndTooltip ( ) ;
}
}
2022-12-01 23:41:34 +01:00
bool
2023-11-29 12:33:26 +01:00
Application : : drawCheckbox ( Containers : : StringView label , bool value ) {
2022-12-01 23:41:34 +01:00
return ImGui : : Checkbox ( label . data ( ) , & value ) ;
}
2022-12-03 16:49:39 +01:00
void
2023-11-29 12:33:26 +01:00
Application : : openUri ( Containers : : StringView uri ) {
2023-08-31 12:34:34 +02:00
if ( ! conf ( ) . isRunningInWine ( ) ) {
ShellExecuteA ( nullptr , nullptr , uri . data ( ) , nullptr , nullptr , SW_SHOWDEFAULT ) ;
}
else {
std : : system ( Utility : : format ( " winebrowser.exe {} " , uri ) . cbegin ( ) ) ;
}
2021-06-11 19:24:52 +02:00
}
2021-07-21 14:36:49 +02:00
2022-12-03 16:49:39 +01:00
void
2023-11-29 12:33:26 +01:00
Application : : checkGameState ( ) {
2021-07-21 14:36:49 +02:00
WTS_PROCESS_INFOW * process_infos = nullptr ;
unsigned long process_count = 0 ;
if ( WTSEnumerateProcessesW ( WTS_CURRENT_SERVER_HANDLE , 0 , 1 , & process_infos , & process_count ) ) {
Containers : : ScopeGuard guard { process_infos , WTSFreeMemory } ;
for ( unsigned long i = 0 ; i < process_count ; + + i ) {
if ( std : : wcscmp ( process_infos [ i ] . pProcessName , L " MASS_Builder-Win64-Shipping.exe " ) = = 0 ) {
_gameState = GameState : : Running ;
break ;
}
else {
_gameState = GameState : : NotRunning ;
}
}
}
else {
_gameState = GameState : : Unknown ;
}
}
2023-11-29 12:33:26 +01:00
}