2021-10-25 20:05:28 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "ZenDashboard.h"
2022-12-09 16:11:41 -05:00
# include "Experimental/ZenServerInterface.h"
2021-10-25 20:05:28 -04:00
# include "Features/IModularFeatures.h"
2022-12-06 15:38:54 -05:00
# include "Framework/Application/SlateApplication.h"
# include "Framework/MultiBox/MultiBoxBuilder.h"
2021-10-25 20:05:28 -04:00
# include "Framework/Notifications/NotificationManager.h"
2022-12-06 15:38:54 -05:00
# include "GenericPlatform/GenericPlatformFile.h"
# include "HAL/PlatformProcess.h"
2021-10-25 20:05:28 -04:00
# include "Misc/CompilationResult.h"
# include "Misc/MessageDialog.h"
2022-12-06 15:38:54 -05:00
# include "Misc/Optional.h"
2023-04-28 16:01:26 -04:00
# include "Misc/Timespan.h"
2022-12-06 15:38:54 -05:00
# include "Modules/ModuleInterface.h"
# include "Modules/ModuleManager.h"
# include "RequiredProgramMainCPPInclude.h"
# include "ServiceInstanceManager.h"
2022-12-06 19:06:55 -05:00
# include "SMessageDialog.h"
2022-12-06 15:38:54 -05:00
# include "StandaloneRenderer.h"
2021-10-25 20:05:28 -04:00
# include "SZenCacheStatistics.h"
2023-09-14 15:56:45 -04:00
# include "SZenCidStoreStatistics.h"
2023-08-31 22:30:53 -04:00
# include "SZenProjectStatistics.h"
2022-12-06 15:38:54 -05:00
# include "SZenServiceStatus.h"
2023-11-17 12:46:23 -05:00
# include "Tasks/Task.h"
2022-12-06 15:38:54 -05:00
# include "Templates/SharedPointer.h"
# include "Widgets/Input/SButton.h"
# include "Widgets/Input/SButton.h"
# include "Widgets/Input/SCheckBox.h"
# include "Widgets/Notifications/SNotificationList.h"
# include "Widgets/Text/STextBlock.h"
# include "ZenDashboardStyle.h"
2021-10-25 20:05:28 -04:00
# if PLATFORM_WINDOWS
# include "Runtime/Launch/Resources/Windows/Resource.h"
# include "Windows/WindowsApplication.h"
2023-08-10 03:34:53 -04:00
# include "Windows/AllowWindowsPlatformTypes.h"
2021-10-25 20:05:28 -04:00
# include <shellapi.h>
2023-08-10 03:34:53 -04:00
# include "Windows/HideWindowsPlatformTypes.h"
2022-12-06 15:38:54 -05:00
# elif PLATFORM_LINUX
# include "UnixCommonStartup.h"
# elif PLATFORM_MAC
# include "Mac/MacProgramDelegate.h"
# include "LaunchEngineLoop.h"
# else
# error "Unsupported platform!"
2021-10-25 20:05:28 -04:00
# endif
# define LOCTEXT_NAMESPACE "ZenDashboard"
IMPLEMENT_APPLICATION ( ZenDashboard , " ZenDashboard " ) ;
static void OnRequestExit ( )
{
RequestEngineExit ( TEXT ( " ZenDashboard Closed " ) ) ;
}
2022-12-06 15:38:54 -05:00
static void HideOnCloseOverride ( const TSharedRef < SWindow > & WindowBeingClosed )
{
WindowBeingClosed - > HideWindow ( ) ;
}
2024-03-07 13:44:59 -05:00
// Controls whether we want the ZenDashboard app to behave as a systray app. Currently only supported for windows.
# define UE_ZENDASHBOARD_SYSTRAY 0
# if UE_ZENDASHBOARD_SYSTRAY && PLATFORM_WINDOWS
2021-10-25 20:05:28 -04:00
# define WM_TRAYICON (WM_USER + 1000)
2022-12-06 15:38:54 -05:00
# define CMD_USER 400
# define CMD_SHOWDASHBOARD (CMD_USER + 1)
# define CMD_STARTZENSERVER (CMD_USER + 2)
# define CMD_STOPZENSERVER (CMD_USER + 3)
# define CMD_RESTARTZENSERVER (CMD_USER + 4)
# define CMD_EXITDASHBOARD (CMD_USER + 5)
2021-10-25 20:05:28 -04:00
# endif
class FZenDashboardApp
2024-03-07 13:44:59 -05:00
# if UE_ZENDASHBOARD_SYSTRAY && PLATFORM_WINDOWS
2021-10-25 20:05:28 -04:00
: IWindowsMessageHandler
# endif
{
FCriticalSection CriticalSection ;
FSlateApplication & Slate ;
TSharedPtr < SWindow > Window ;
TSharedPtr < SNotificationItem > CompileNotification ;
2022-12-06 15:38:54 -05:00
TSharedPtr < UE : : Zen : : FServiceInstanceManager > ServiceInstanceManager ;
2021-10-25 20:05:28 -04:00
TArray < FSimpleDelegate > MainThreadTasks ;
2023-11-17 12:46:23 -05:00
std : : atomic < bool > bLatentExclusiveOperationActive = false ;
2024-03-07 13:44:59 -05:00
# if UE_ZENDASHBOARD_SYSTRAY && PLATFORM_WINDOWS
2021-10-25 20:05:28 -04:00
bool ProcessMessage ( HWND hwnd , uint32 msg , WPARAM wParam , LPARAM lParam , int32 & OutResult ) override
{
2022-12-06 15:38:54 -05:00
switch ( msg )
2021-10-25 20:05:28 -04:00
{
2022-12-06 15:38:54 -05:00
case WM_TRAYICON :
if ( LOWORD ( lParam ) = = WM_LBUTTONDBLCLK )
{
Window - > ShowWindow ( ) ;
return true ;
}
else if ( LOWORD ( lParam ) = = WM_RBUTTONUP )
{
HMENU Menu = CreatePopupMenu ( ) ;
auto AddMenuItem = [ Menu ] ( const wchar_t * Text , uint32 Id )
{
MENUITEMINFOW MenuItemInfo = {
sizeof ( MenuItemInfo ) ,
MIIM_TYPE | MIIM_STATE | MIIM_ID ,
MFT_STRING ,
MFS_ENABLED ,
Id ,
} ;
MenuItemInfo . dwTypeData = LPWSTR ( Text ) ;
InsertMenuItemW ( Menu , 999 , true , & MenuItemInfo ) ;
} ;
AddMenuItem ( * LOCTEXT ( " Show_ZenDashboard " , " Zen Dashboard " ) . ToString ( ) , CMD_SHOWDASHBOARD ) ;
AddMenuItem ( * LOCTEXT ( " Start_ZenServer " , " Start Zen Server " ) . ToString ( ) , CMD_STARTZENSERVER ) ;
AddMenuItem ( * LOCTEXT ( " Stop_ZenServer " , " Stop Zen Server " ) . ToString ( ) , CMD_STOPZENSERVER ) ;
AddMenuItem ( * LOCTEXT ( " Restart_ZenServer " , " Restart Zen Server " ) . ToString ( ) , CMD_RESTARTZENSERVER ) ;
AddMenuItem ( * LOCTEXT ( " Exit " , " Exit " ) . ToString ( ) , CMD_EXITDASHBOARD ) ;
POINT MousePos ;
GetCursorPos ( & MousePos ) ;
BOOL Ret = TrackPopupMenu (
Menu , TPM_RIGHTALIGN | TPM_BOTTOMALIGN ,
MousePos . x , MousePos . y ,
0 , hwnd , nullptr ) ;
DestroyMenu ( Menu ) ;
}
break ;
case WM_COMMAND :
switch ( LOWORD ( wParam ) )
{
case CMD_SHOWDASHBOARD :
Window - > ShowWindow ( ) ;
break ;
case CMD_STARTZENSERVER :
2023-11-17 12:46:23 -05:00
if ( CanExecuteExclusiveAction ( ) )
{
StartZenServer ( ) ;
}
2022-12-06 15:38:54 -05:00
break ;
case CMD_STOPZENSERVER :
2023-11-17 12:46:23 -05:00
if ( CanExecuteExclusiveAction ( ) )
{
StopZenServer ( ) ;
}
2022-12-06 15:38:54 -05:00
break ;
case CMD_RESTARTZENSERVER :
2023-11-17 12:46:23 -05:00
if ( CanExecuteExclusiveAction ( ) )
{
RestartZenServer ( ) ;
}
2022-12-06 15:38:54 -05:00
break ;
case CMD_EXITDASHBOARD :
2023-11-17 12:46:23 -05:00
if ( CanExecuteExclusiveAction ( ) )
{
ExitDashboard ( ) ;
}
2022-12-06 15:38:54 -05:00
break ;
}
break ;
2021-10-25 20:05:28 -04:00
}
2022-12-06 15:38:54 -05:00
2021-10-25 20:05:28 -04:00
return false ;
}
2024-03-07 13:44:59 -05:00
# endif // UE_ZENDASHBOARD_SYSTRAY && PLATFORM_WINDOWS
2022-12-06 15:38:54 -05:00
void ExitDashboard ( )
{
FSlateApplication : : Get ( ) . RequestDestroyWindow ( Window . ToSharedRef ( ) ) ;
}
2023-11-17 12:46:23 -05:00
bool CanExecuteExclusiveAction ( )
{
return ! bLatentExclusiveOperationActive ;
}
2022-12-06 15:38:54 -05:00
void StartZenServer ( )
{
UE : : Zen : : FZenLocalServiceRunContext RunContext ;
if ( UE : : Zen : : TryGetLocalServiceRunContext ( RunContext ) )
{
UE : : Zen : : StartLocalService ( RunContext ) ;
}
}
void StopZenServer ( )
{
UE : : Zen : : FZenLocalServiceRunContext RunContext ;
if ( UE : : Zen : : TryGetLocalServiceRunContext ( RunContext ) )
{
UE : : Zen : : StopLocalService ( * RunContext . GetDataPath ( ) ) ;
}
}
void RestartZenServer ( )
{
StopZenServer ( ) ;
StartZenServer ( ) ;
}
void DeleteDataAndRestartZenServer ( )
{
UE : : Zen : : FZenLocalServiceRunContext RunContext ;
if ( UE : : Zen : : TryGetLocalServiceRunContext ( RunContext ) )
{
if ( UE : : Zen : : IsLocalServiceRunning ( * RunContext . GetDataPath ( ) ) )
{
FText Title = LOCTEXT ( " ConfirmToDeleteZenServerData_Title " , " Zen Server Data Delete " ) ;
FText ConfirmMessage = FText : : Format ( LOCTEXT ( " ConfirmToDeleteZenServerData " , " You are about to delete all local Zen Server data at: \n \n {0} \n \n This will require you to build or download all data stored there which can take a long time. Are you sure you want to proceed? " ) ,
FText : : FromString ( RunContext . GetDataPath ( ) ) ) ;
2023-06-29 14:57:59 -04:00
EAppReturnType : : Type OkToDelete = OpenModalMessageDialog_Internal ( EAppMsgCategory : : Warning , EAppMsgType : : YesNo , ConfirmMessage , Title , Window ) ;
2022-12-06 15:38:54 -05:00
if ( OkToDelete = = EAppReturnType : : No )
{
return ;
}
StopZenServer ( ) ;
2023-11-17 12:46:23 -05:00
bLatentExclusiveOperationActive = true ;
2022-12-06 15:38:54 -05:00
2023-11-17 12:46:23 -05:00
UE : : Tasks : : Launch ( TEXT ( " DeleteZenDataAndRestart " ) ,
[ this , DataPath = RunContext . GetDataPath ( ) ] ( )
{
FPlatformProcess : : Sleep ( 10.0f ) ;
2023-12-08 19:00:53 -05:00
FPlatformFileManager : : Get ( ) . GetPlatformFile ( ) . DeleteDirectoryRecursively ( * DataPath ) ;
2023-11-17 12:46:23 -05:00
StartZenServer ( ) ;
bLatentExclusiveOperationActive = false ;
} ,
UE : : Tasks : : ETaskPriority : : BackgroundNormal
) ;
2022-12-06 15:38:54 -05:00
}
}
}
void GatherDiagnostics ( )
{
}
void LaunchUtilityCommandPrompt ( )
{
# if PLATFORM_WINDOWS
TStringBuilder < 128 > Args ;
FString UtilityPath = UE : : Zen : : GetLocalInstallUtilityPath ( ) ;
Args < < TEXT ( " /k \" " ) < < UtilityPath < < TEXT ( " \" --help " ) ;
FProcHandle UtilProcHandle = FPlatformProcess : : CreateProc ( TEXT ( " cmd.exe " ) , Args . ToString ( ) , false , false , false , nullptr , 0 , * FPaths : : GetPath ( UtilityPath ) , nullptr ) ;
# else
// TODO: Need to get the equivalent for linux/mac
# endif
}
void RunGC ( )
{
if ( TSharedPtr < UE : : Zen : : FZenServiceInstance > ZenServiceInstance = ServiceInstanceManager - > GetZenServiceInstance ( ) )
{
ZenServiceInstance - > RequestGC ( ) ;
}
}
2023-04-28 16:01:26 -04:00
void RunGCOneWeek ( )
{
if ( TSharedPtr < UE : : Zen : : FZenServiceInstance > ZenServiceInstance = ServiceInstanceManager - > GetZenServiceInstance ( ) )
{
uint32 CacheDuration = static_cast < uint32 > ( FTimespan : : FromDays ( 7 ) . GetTotalSeconds ( ) ) ;
ZenServiceInstance - > RequestGC ( nullptr , & CacheDuration ) ;
}
}
void RunGCOneDay ( )
{
if ( TSharedPtr < UE : : Zen : : FZenServiceInstance > ZenServiceInstance = ServiceInstanceManager - > GetZenServiceInstance ( ) )
{
uint32 CacheDuration = static_cast < uint32 > ( FTimespan : : FromDays ( 1 ) . GetTotalSeconds ( ) ) ;
ZenServiceInstance - > RequestGC ( nullptr , & CacheDuration ) ;
}
}
2022-12-06 15:38:54 -05:00
TSharedRef < SWidget > MakeMainMenu ( )
{
FMenuBarBuilder MenuBuilder ( nullptr ) ;
{
// Control
MenuBuilder . AddPullDownMenu (
LOCTEXT ( " FileMenu " , " File " ) ,
LOCTEXT ( " FileMenu_ToolTip " , " Opens the file menu " ) ,
2024-03-07 13:44:59 -05:00
FOnGetContent : : CreateRaw ( this , & FZenDashboardApp : : FillFileMenu ) ) ;
2022-12-06 15:38:54 -05:00
// Control
MenuBuilder . AddPullDownMenu (
LOCTEXT ( " ToolsMenu " , " Tools " ) ,
LOCTEXT ( " ToolsMenu_ToolTip " , " Opens the tools menu " ) ,
2024-03-07 13:44:59 -05:00
FOnGetContent : : CreateRaw ( this , & FZenDashboardApp : : FillToolsMenu ) ) ;
2022-12-06 15:38:54 -05:00
}
// Create the menu bar
TSharedRef < SWidget > MenuBarWidget = MenuBuilder . MakeWidget ( ) ;
MenuBarWidget - > SetVisibility ( EVisibility : : Visible ) ; // Work around for menu bar not showing on Mac
return MenuBarWidget ;
}
2024-03-07 13:44:59 -05:00
TSharedRef < SWidget > FillFileMenu ( )
2022-12-06 15:38:54 -05:00
{
2024-03-07 13:44:59 -05:00
const bool bCloseSelfOnly = false ;
const bool bSearchable = false ;
const bool bRecursivelySearchable = false ;
FMenuBuilder MenuBuilder ( true ,
nullptr ,
TSharedPtr < FExtender > ( ) ,
bCloseSelfOnly ,
& FCoreStyle : : Get ( ) ,
bSearchable ,
NAME_None ,
bRecursivelySearchable ) ;
2022-12-06 15:38:54 -05:00
MenuBuilder . AddMenuEntry (
LOCTEXT ( " Exit " , " Exit " ) ,
LOCTEXT ( " Exit_ToolTip " , " Exits the Zen Dashboard " ) ,
FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateRaw ( this , & FZenDashboardApp : : ExitDashboard ) ,
2023-11-17 12:46:23 -05:00
FCanExecuteAction : : CreateRaw ( this , & FZenDashboardApp : : CanExecuteExclusiveAction )
2022-12-06 15:38:54 -05:00
) ,
NAME_None ,
EUserInterfaceActionType : : Button
) ;
2024-03-07 13:44:59 -05:00
return MenuBuilder . MakeWidget ( ) ;
2022-12-06 15:38:54 -05:00
}
2024-03-07 13:44:59 -05:00
TSharedRef < SWidget > FillToolsMenu ( )
2022-12-06 15:38:54 -05:00
{
2024-03-07 13:44:59 -05:00
const bool bCloseSelfOnly = false ;
const bool bSearchable = false ;
const bool bRecursivelySearchable = false ;
FMenuBuilder MenuBuilder ( true ,
nullptr ,
TSharedPtr < FExtender > ( ) ,
bCloseSelfOnly ,
& FCoreStyle : : Get ( ) ,
bSearchable ,
NAME_None ,
bRecursivelySearchable ) ;
2022-12-06 15:38:54 -05:00
MenuBuilder . BeginSection ( NAME_None , LOCTEXT ( " ServiceControls " , " Service controls " ) ) ;
{
MenuBuilder . AddMenuEntry (
LOCTEXT ( " Start_ZenServer " , " Start Zen Server " ) ,
LOCTEXT ( " Start_ZenServer_ToolTip " , " Ensures ZenServer is started " ) ,
FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateRaw ( this , & FZenDashboardApp : : StartZenServer ) ,
2023-11-17 12:46:23 -05:00
FCanExecuteAction : : CreateRaw ( this , & FZenDashboardApp : : CanExecuteExclusiveAction )
2022-12-06 15:38:54 -05:00
) ,
NAME_None ,
EUserInterfaceActionType : : Button
) ;
MenuBuilder . AddMenuEntry (
LOCTEXT ( " Stop_ZenServer " , " Stop Zen Server " ) ,
LOCTEXT ( " Stop_ZenServer_ToolTip " , " Ensures ZenServer is stopped " ) ,
FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateRaw ( this , & FZenDashboardApp : : StopZenServer ) ,
2023-11-17 12:46:23 -05:00
FCanExecuteAction : : CreateRaw ( this , & FZenDashboardApp : : CanExecuteExclusiveAction )
2022-12-06 15:38:54 -05:00
) ,
NAME_None ,
EUserInterfaceActionType : : Button
) ;
MenuBuilder . AddMenuEntry (
LOCTEXT ( " Restart_ZenServer " , " Restart Zen Server " ) ,
LOCTEXT ( " Restart_ZenServer_ToolTip " , " Stops ZenServer if it is running then ensures it is running " ) ,
FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateRaw ( this , & FZenDashboardApp : : RestartZenServer ) ,
2023-11-17 12:46:23 -05:00
FCanExecuteAction : : CreateRaw ( this , & FZenDashboardApp : : CanExecuteExclusiveAction )
2022-12-06 15:38:54 -05:00
) ,
NAME_None ,
EUserInterfaceActionType : : Button
) ;
2024-03-07 13:44:59 -05:00
MenuBuilder . AddWrapperSubMenu ( LOCTEXT ( " Advanced " , " Advanced " ) , LOCTEXT ( " Advanced_ToolTip " , " Advanced service control commands " ) ,
FOnGetContent : : CreateLambda ( [ this ] ( ) - > TSharedRef < SWidget >
2022-12-06 15:38:54 -05:00
{
2024-03-07 13:44:59 -05:00
const bool bCloseSelfOnly = false ;
const bool bSearchable = false ;
const bool bRecursivelySearchable = false ;
FMenuBuilder SubMenuBuilder ( true ,
nullptr ,
TSharedPtr < FExtender > ( ) ,
bCloseSelfOnly ,
& FCoreStyle : : Get ( ) ,
bSearchable ,
NAME_None ,
bRecursivelySearchable ) ;
2022-12-06 15:38:54 -05:00
SubMenuBuilder . AddMenuEntry (
LOCTEXT ( " DeleteDataAndRestart_ZenServer " , " Delete data and restart Zen Server " ) ,
LOCTEXT ( " DeleteDataAndRestart_ZenServer_ToolTip " , " Stops ZenServer if it is running, deletes ALL of its data, then starts it from a blank state " ) ,
FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateRaw ( this , & FZenDashboardApp : : DeleteDataAndRestartZenServer ) ,
2023-11-17 12:46:23 -05:00
FCanExecuteAction : : CreateRaw ( this , & FZenDashboardApp : : CanExecuteExclusiveAction )
2022-12-06 15:38:54 -05:00
) ,
NAME_None ,
EUserInterfaceActionType : : Button
) ;
2024-03-07 13:44:59 -05:00
return SubMenuBuilder . MakeWidget ( ) ;
2022-12-06 15:38:54 -05:00
} )
2024-03-07 13:44:59 -05:00
, FSlateIcon ( )
2022-12-06 15:38:54 -05:00
) ;
}
MenuBuilder . EndSection ( ) ;
MenuBuilder . BeginSection ( NAME_None , LOCTEXT ( " Debug " , " Debug " ) ) ;
{
// TODO: The "Gather diagnostic info" feature is off for now and needs to be filled in as part of a subsequent change
// MenuBuilder.AddMenuEntry(
// LOCTEXT("GatherDiagnosticInfo", "Gather diagnostic info"),
// LOCTEXT("GatherDiagnosticInfo_ToolTip", "Gathers information for diagnosing issues"),
// FSlateIcon(),
// FUIAction(
// FExecuteAction::CreateRaw(this, &FZenDashboardApp::GatherDiagnostics),
// FCanExecuteAction()
// ),
// NAME_None,
// EUserInterfaceActionType::Button
// );
MenuBuilder . AddMenuEntry (
LOCTEXT ( " LaunchUtilityCommandPrompt " , " Launch utility command prompt " ) ,
LOCTEXT ( " LaunchUtilityCommandPrompt_ToolTip " , " Launches command prompt for issuing zen server specific commands " ) ,
FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateRaw ( this , & FZenDashboardApp : : LaunchUtilityCommandPrompt ) ,
FCanExecuteAction ( )
) ,
NAME_None ,
EUserInterfaceActionType : : Button
) ;
}
MenuBuilder . EndSection ( ) ;
MenuBuilder . BeginSection ( NAME_None , LOCTEXT ( " Disk " , " Disk " ) ) ;
{
MenuBuilder . AddMenuEntry (
LOCTEXT ( " FreeUnusedDiskSpace " , " Free unused disk space " ) ,
LOCTEXT ( " FreeUnusedDiskSpace_ToolTip " , " Frees unused disk space by running a garbage collection process " ) ,
FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateRaw ( this , & FZenDashboardApp : : RunGC ) ,
2023-11-17 12:46:23 -05:00
FCanExecuteAction : : CreateRaw ( this , & FZenDashboardApp : : CanExecuteExclusiveAction )
2022-12-06 15:38:54 -05:00
) ,
NAME_None ,
EUserInterfaceActionType : : Button
) ;
2023-04-28 16:01:26 -04:00
MenuBuilder . AddMenuEntry (
LOCTEXT ( " FreeUnusedDiskSpaceOneWeek " , " Free unused disk space (1 week age limit) " ) ,
LOCTEXT ( " FreeUnusedDiskSpaceOneWeek_ToolTip " , " Frees unused disk space by running a garbage collection process, only keeps data that was used in the past week " ) ,
FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateRaw ( this , & FZenDashboardApp : : RunGCOneWeek ) ,
2023-11-17 12:46:23 -05:00
FCanExecuteAction : : CreateRaw ( this , & FZenDashboardApp : : CanExecuteExclusiveAction )
2023-04-28 16:01:26 -04:00
) ,
NAME_None ,
EUserInterfaceActionType : : Button
) ;
MenuBuilder . AddMenuEntry (
LOCTEXT ( " FreeUnusedDiskSpaceOneDay " , " Free unused disk space (1 day age limit) " ) ,
LOCTEXT ( " FreeUnusedDiskSpaceOneDay_ToolTip " , " Frees unused disk space by running a garbage collection process, only keeps data that was used in the past day " ) ,
FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateRaw ( this , & FZenDashboardApp : : RunGCOneDay ) ,
2023-11-17 12:46:23 -05:00
FCanExecuteAction : : CreateRaw ( this , & FZenDashboardApp : : CanExecuteExclusiveAction )
2023-04-28 16:01:26 -04:00
) ,
NAME_None ,
EUserInterfaceActionType : : Button
) ;
2022-12-06 15:38:54 -05:00
}
MenuBuilder . EndSection ( ) ;
2024-03-07 13:44:59 -05:00
return MenuBuilder . MakeWidget ( ) ;
2022-12-06 15:38:54 -05:00
}
2021-10-25 20:05:28 -04:00
public :
FZenDashboardApp ( FSlateApplication & InSlate )
: Slate ( InSlate )
{
2022-12-06 15:38:54 -05:00
ServiceInstanceManager = MakeShared < UE : : Zen : : FServiceInstanceManager > ( ) ;
InstallMessageDialogOverride ( ) ;
2021-10-25 20:05:28 -04:00
}
virtual ~ FZenDashboardApp ( )
{
2022-12-06 15:38:54 -05:00
RemoveMessageDialogOverride ( ) ;
2021-10-25 20:05:28 -04:00
}
void Run ( )
{
2024-03-07 13:44:59 -05:00
const bool bSystemTrayMode = ! ! UE_ZENDASHBOARD_SYSTRAY & & ! ! PLATFORM_WINDOWS ;
const bool bShowWindow = ! ( FParse : : Param ( FCommandLine : : Get ( ) , TEXT ( " Minimized " ) ) & & bSystemTrayMode ) ;
2022-12-06 15:38:54 -05:00
2021-10-25 20:05:28 -04:00
Window =
SNew ( SWindow )
. Title ( GetWindowTitle ( ) )
. ClientSize ( FVector2D ( 384.0f , 128.0f ) )
. ActivationPolicy ( EWindowActivationPolicy : : Always )
. SizingRule ( ESizingRule : : Autosized )
2022-12-06 15:38:54 -05:00
. IsTopmostWindow ( false )
2021-10-25 20:05:28 -04:00
. FocusWhenFirstShown ( false )
. SupportsMaximize ( false )
. SupportsMinimize ( true )
. HasCloseButton ( true )
[
SNew ( SBorder )
. BorderImage ( FCoreStyle : : Get ( ) . GetBrush ( " ToolPanel.GroupBorder " ) )
[
SNew ( SVerticalBox )
2022-12-06 15:38:54 -05:00
// Menu
2021-10-25 20:05:28 -04:00
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
2022-12-06 15:38:54 -05:00
[
MakeMainMenu ( )
]
// Status panel
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
. Padding ( 0.0f , 10.0f , 0.0f , 0.0f )
2021-10-25 20:05:28 -04:00
. VAlign ( VAlign_Top )
[
2022-12-06 15:38:54 -05:00
SNew ( SZenServiceStatus )
. ZenServiceInstance ( ServiceInstanceManager . ToSharedRef ( ) , & UE : : Zen : : FServiceInstanceManager : : GetZenServiceInstance )
]
// Stats panel
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
. Padding ( 0.0f , 10.0f , 0.0f , 0.0f )
. VAlign ( VAlign_Top )
[
2023-08-31 22:30:53 -04:00
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
. HAlign ( HAlign_Left )
. VAlign ( VAlign_Top )
[
SNew ( SZenCacheStatistics )
. ZenServiceInstance ( ServiceInstanceManager . ToSharedRef ( ) , & UE : : Zen : : FServiceInstanceManager : : GetZenServiceInstance )
]
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
. HAlign ( HAlign_Left )
. VAlign ( VAlign_Top )
[
SNew ( SZenProjectStatistics )
. ZenServiceInstance ( ServiceInstanceManager . ToSharedRef ( ) , & UE : : Zen : : FServiceInstanceManager : : GetZenServiceInstance )
]
2023-09-14 15:56:45 -04:00
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
. HAlign ( HAlign_Left )
. VAlign ( VAlign_Top )
[
SNew ( SZenCidStoreStatistics )
. ZenServiceInstance ( ServiceInstanceManager . ToSharedRef ( ) , & UE : : Zen : : FServiceInstanceManager : : GetZenServiceInstance )
]
2021-10-25 20:05:28 -04:00
]
]
] ;
2022-12-06 15:38:54 -05:00
if ( bSystemTrayMode )
{
Window - > SetRequestDestroyWindowOverride ( FRequestDestroyWindowOverride : : CreateStatic ( & HideOnCloseOverride ) ) ;
}
2021-10-25 20:05:28 -04:00
2022-12-06 19:06:55 -05:00
Slate . AddWindow ( Window . ToSharedRef ( ) , bShowWindow ) ;
2021-10-25 20:05:28 -04:00
// Setting focus seems to have to happen after the Window has been added
Slate . ClearKeyboardFocus ( EFocusCause : : Cleared ) ;
//
2024-03-07 13:44:59 -05:00
# if UE_ZENDASHBOARD_SYSTRAY && PLATFORM_WINDOWS
if ( bSystemTrayMode )
{
( ( FWindowsApplication * ) Slate . Get ( ) . GetPlatformApplication ( ) . Get ( ) ) - > AddMessageHandler ( * this ) ;
2021-10-25 20:05:28 -04:00
2024-03-07 13:44:59 -05:00
NOTIFYICONDATAW NotifyIconData ;
memset ( & NotifyIconData , 0 , sizeof ( NotifyIconData ) ) ;
NotifyIconData . cbSize = sizeof ( NotifyIconData ) ;
NotifyIconData . hWnd = ( HWND ) Window - > GetNativeWindow ( ) - > GetOSWindowHandle ( ) ;
NotifyIconData . uID = 0 ;
NotifyIconData . uCallbackMessage = WM_USER + 1000 ;
NotifyIconData . uFlags = NIF_ICON | NIF_MESSAGE ;
NotifyIconData . hIcon = : : LoadIconW ( GetModuleHandleW ( nullptr ) , MAKEINTRESOURCE ( IDICON_UEGame ) ) ;
Shell_NotifyIcon ( NIM_ADD , & NotifyIconData ) ;
}
2021-10-25 20:05:28 -04:00
# endif
// loop until the app is ready to quit
while ( ! IsEngineExitRequested ( ) )
{
BeginExitIfRequested ( ) ;
Slate . PumpMessages ( ) ;
Slate . Tick ( ) ;
FPlatformProcess : : Sleep ( 1.0f / 30.0f ) ;
// Execute all the main thread tasks
FScopeLock Lock ( & CriticalSection ) ;
for ( FSimpleDelegate & MainThreadTask : MainThreadTasks )
{
MainThreadTask . Execute ( ) ;
}
MainThreadTasks . Empty ( ) ;
}
2024-03-07 13:44:59 -05:00
# if UE_ZENDASHBOARD_SYSTRAY && PLATFORM_WINDOWS
if ( bSystemTrayMode )
{
memset ( & NotifyIconData , 0 , sizeof ( NotifyIconData ) ) ;
NotifyIconData . cbSize = sizeof ( NotifyIconData ) ;
NotifyIconData . uID = 0 ;
NotifyIconData . hWnd = ( HWND ) Window - > GetNativeWindow ( ) - > GetOSWindowHandle ( ) ;
Shell_NotifyIcon ( NIM_DELETE , & NotifyIconData ) ;
}
2021-10-25 20:05:28 -04:00
# endif
// Make sure the window is hidden, because it might take a while for the background thread to finish.
Window - > HideWindow ( ) ;
}
private :
FText GetWindowTitle ( )
{
2023-12-08 19:00:53 -05:00
return LOCTEXT ( " WindowTitle " , " Unreal Zen Dashboard " ) ;
2021-10-25 20:05:28 -04:00
}
2023-06-29 14:57:59 -04:00
EAppReturnType : : Type OnModalMessageDialog ( EAppMsgCategory InMessageCategory , EAppMsgType : : Type InMessage , const FText & InText , const FText & InTitle )
2021-10-25 20:05:28 -04:00
{
2022-12-06 15:38:54 -05:00
if ( IsInGameThread ( ) & & FSlateApplication : : IsInitialized ( ) & & FSlateApplication : : Get ( ) . CanAddModalWindow ( ) )
2021-10-25 20:05:28 -04:00
{
2023-06-29 14:57:59 -04:00
return OpenModalMessageDialog_Internal ( InMessageCategory , InMessage , InText , InTitle , Window ) ;
2021-10-25 20:05:28 -04:00
}
else
{
2022-12-06 15:38:54 -05:00
return FPlatformMisc : : MessageBoxExt ( InMessage , * InText . ToString ( ) , * InTitle . ToString ( ) ) ;
2021-10-25 20:05:28 -04:00
}
}
2022-12-06 15:38:54 -05:00
void InstallMessageDialogOverride ( )
2021-10-25 20:05:28 -04:00
{
2023-06-29 14:57:59 -04:00
FCoreDelegates : : ModalMessageDialog . BindRaw ( this , & FZenDashboardApp : : OnModalMessageDialog ) ;
2022-12-06 15:38:54 -05:00
}
void RemoveMessageDialogOverride ( )
{
2023-06-29 14:57:59 -04:00
FCoreDelegates : : ModalMessageDialog . Unbind ( ) ;
2021-10-25 20:05:28 -04:00
}
} ;
2022-12-06 15:38:54 -05:00
int ZenDashboardMain ( const TCHAR * CmdLine )
2021-10-25 20:05:28 -04:00
{
2022-12-06 15:38:54 -05:00
ON_SCOPE_EXIT
{
RequestEngineExit ( TEXT ( " Exiting " ) ) ;
FEngineLoop : : AppPreExit ( ) ;
FModuleManager : : Get ( ) . UnloadModulesAtShutdown ( ) ;
FEngineLoop : : AppExit ( ) ;
} ;
2021-10-25 20:05:28 -04:00
// start up the main loop
GEngineLoop . PreInit ( CmdLine ) ;
2022-12-06 15:38:54 -05:00
FSystemWideCriticalSection SystemWideZenDashboardCritSec ( TEXT ( " ZenDashboard " ) ) ;
if ( ! SystemWideZenDashboardCritSec . IsValid ( ) )
{
return true ;
}
2021-10-25 20:05:28 -04:00
check ( GConfig & & GConfig - > IsReadyForUse ( ) ) ;
// Initialize high DPI mode
FSlateApplication : : InitHighDPI ( true ) ;
{
// Create the platform slate application (what FSlateApplication::Get() returns)
TSharedRef < FSlateApplication > Slate = FSlateApplication : : Create ( MakeShareable ( FPlatformApplicationMisc : : CreateApplication ( ) ) ) ;
{
// Initialize renderer
TSharedRef < FSlateRenderer > SlateRenderer = GetStandardStandaloneRenderer ( ) ;
// Try to initialize the renderer. It's possible that we launched when the driver crashed so try a few times before giving up.
bool bRendererInitialized = Slate - > InitializeRenderer ( SlateRenderer , true ) ;
if ( ! bRendererInitialized )
{
// Close down the Slate application
FSlateApplication : : Shutdown ( ) ;
return false ;
}
// Set the normal UE IsEngineExitRequested() when outer frame is closed
Slate - > SetExitRequestedHandler ( FSimpleDelegate : : CreateStatic ( & OnRequestExit ) ) ;
// Prepare the custom Slate styles
FZenDashboardStyle : : Initialize ( ) ;
// Set the icon
FAppStyle : : SetAppStyleSet ( FZenDashboardStyle : : Get ( ) ) ;
// Run the inner application loop
FZenDashboardApp App ( Slate . Get ( ) ) ;
App . Run ( ) ;
// Clean up the custom styles
FZenDashboardStyle : : Shutdown ( ) ;
}
// Close down the Slate application
FSlateApplication : : Shutdown ( ) ;
}
return true ;
}
2022-12-06 15:38:54 -05:00
# if PLATFORM_WINDOWS
2023-11-17 12:46:23 -05:00
int WINAPI WinMain ( _In_ HINSTANCE hCurrInstance , _In_opt_ HINSTANCE hPrevInstance , _In_ LPSTR lpCmdLine , _In_ int nShowCmd )
2021-10-25 20:05:28 -04:00
{
hInstance = hCurrInstance ;
return ZenDashboardMain ( GetCommandLineW ( ) ) ? 0 : 1 ;
}
2022-12-06 15:38:54 -05:00
# elif PLATFORM_LINUX
int main ( int argc , char * argv [ ] )
{
return CommonUnixMain ( argc , argv , & ZenDashboardMain ) ;
}
# elif PLATFORM_MAC
int main ( int argc , char * argv [ ] )
{
[ MacProgramDelegate mainWithArgc : argc argv : argv programMain : ZenDashboardMain programExit : FEngineLoop : : AppExit ] ;
}
# else
# error "Unsupported platform!"
# endif
2021-10-25 20:05:28 -04:00
# undef LOCTEXT_NAMESPACE