359 lines
10 KiB
C++
359 lines
10 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "BuildStorageTool.h"
|
|
#include "Experimental/ZenServerInterface.h"
|
|
#include "Features/IModularFeatures.h"
|
|
#include "Framework/Application/SlateApplication.h"
|
|
#include "Framework/MultiBox/MultiBoxBuilder.h"
|
|
#include "Framework/Notifications/NotificationManager.h"
|
|
#include "GenericPlatform/GenericPlatformFile.h"
|
|
#include "HAL/PlatformProcess.h"
|
|
#include "Misc/CompilationResult.h"
|
|
#include "Misc/MessageDialog.h"
|
|
#include "Misc/Optional.h"
|
|
#include "Misc/Timespan.h"
|
|
#include "Modules/ModuleInterface.h"
|
|
#include "Modules/ModuleManager.h"
|
|
#include "RequiredProgramMainCPPInclude.h"
|
|
#include "SBuildActivity.h"
|
|
#include "SBuildSelection.h"
|
|
#include "SBuildLogin.h"
|
|
#include "SMessageDialog.h"
|
|
#include "StandaloneRenderer.h"
|
|
#include "BuildStorageToolStyle.h"
|
|
#include "Tasks/Task.h"
|
|
#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 "ZenServiceInstanceManager.h"
|
|
#include "BuildServiceInstanceManager.h"
|
|
|
|
#if PLATFORM_WINDOWS
|
|
#include "Runtime/Launch/Resources/Windows/Resource.h"
|
|
#include "Windows/WindowsApplication.h"
|
|
#include "Windows/AllowWindowsPlatformTypes.h"
|
|
#include <shellapi.h>
|
|
#include "Windows/HideWindowsPlatformTypes.h"
|
|
#elif PLATFORM_LINUX
|
|
#include "UnixCommonStartup.h"
|
|
#elif PLATFORM_MAC
|
|
#include "Mac/MacProgramDelegate.h"
|
|
#include "LaunchEngineLoop.h"
|
|
#else
|
|
#error "Unsupported platform!"
|
|
#endif
|
|
|
|
#define LOCTEXT_NAMESPACE "BuildStorageTool"
|
|
|
|
// These macros are not properly defined by UBT in the case of an engine program with bTreatAsEngineModule=true
|
|
// So define them here as a workaround
|
|
#define IMPLEMENT_ENCRYPTION_KEY_REGISTRATION()
|
|
#define IMPLEMENT_SIGNING_KEY_REGISTRATION()
|
|
IMPLEMENT_APPLICATION(BuildStorageTool, "BuildStorageTool");
|
|
|
|
static void OnRequestExit()
|
|
{
|
|
RequestEngineExit(TEXT("BuildStorageTool Closed"));
|
|
}
|
|
|
|
static void HideOnCloseOverride(const TSharedRef<SWindow>& WindowBeingClosed)
|
|
{
|
|
WindowBeingClosed->HideWindow();
|
|
}
|
|
|
|
class FBuildStorageToolApp
|
|
{
|
|
FCriticalSection CriticalSection;
|
|
FSlateApplication& Slate;
|
|
TSharedPtr<SWindow> Window;
|
|
TSharedPtr<SNotificationItem> CompileNotification;
|
|
TSharedPtr<UE::Zen::FServiceInstanceManager> ZenServiceInstanceManager;
|
|
TSharedPtr<UE::Zen::Build::FServiceInstanceManager> BuildServiceInstanceManager;
|
|
|
|
std::atomic<bool> bLatentExclusiveOperationActive = false;
|
|
|
|
void ExitTool()
|
|
{
|
|
FSlateApplication::Get().RequestDestroyWindow(Window.ToSharedRef());
|
|
}
|
|
|
|
bool CanExecuteExclusiveAction()
|
|
{
|
|
return !bLatentExclusiveOperationActive;
|
|
}
|
|
|
|
TSharedRef< SWidget > MakeMainMenu()
|
|
{
|
|
FMenuBarBuilder MenuBuilder( nullptr );
|
|
{
|
|
// Control
|
|
MenuBuilder.AddPullDownMenu(
|
|
LOCTEXT( "FileMenu", "File" ),
|
|
LOCTEXT( "FileMenu_ToolTip", "Opens the file menu" ),
|
|
FOnGetContent::CreateRaw( this, &FBuildStorageToolApp::FillFileMenu ) );
|
|
}
|
|
|
|
// Create the menu bar
|
|
TSharedRef< SWidget > MenuBarWidget = MenuBuilder.MakeWidget();
|
|
MenuBarWidget->SetVisibility( EVisibility::Visible ); // Work around for menu bar not showing on Mac
|
|
|
|
return MenuBarWidget;
|
|
}
|
|
|
|
TSharedRef<SWidget> FillFileMenu()
|
|
{
|
|
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);
|
|
|
|
MenuBuilder.AddMenuEntry(
|
|
LOCTEXT("Exit", "Exit"),
|
|
LOCTEXT("Exit_ToolTip", "Exits the Storage Server UI"),
|
|
FSlateIcon(),
|
|
FUIAction(
|
|
FExecuteAction::CreateRaw( this, &FBuildStorageToolApp::ExitTool ),
|
|
FCanExecuteAction::CreateRaw(this, &FBuildStorageToolApp::CanExecuteExclusiveAction)
|
|
),
|
|
NAME_None,
|
|
EUserInterfaceActionType::Button
|
|
);
|
|
|
|
return MenuBuilder.MakeWidget();
|
|
}
|
|
|
|
public:
|
|
FBuildStorageToolApp(FSlateApplication& InSlate)
|
|
: Slate(InSlate)
|
|
{
|
|
ZenServiceInstanceManager = MakeShared<UE::Zen::FServiceInstanceManager>();
|
|
BuildServiceInstanceManager = MakeShared<UE::Zen::Build::FServiceInstanceManager>();
|
|
InstallMessageDialogOverride();
|
|
}
|
|
|
|
virtual ~FBuildStorageToolApp()
|
|
{
|
|
RemoveMessageDialogOverride();
|
|
}
|
|
|
|
void Run()
|
|
{
|
|
Window =
|
|
SNew(SWindow)
|
|
.Title(GetWindowTitle())
|
|
.ClientSize(FVector2D(900.0f, 600.0f))
|
|
.ActivationPolicy(EWindowActivationPolicy::Always)
|
|
.SizingRule(ESizingRule::UserSized)
|
|
.IsTopmostWindow(false)
|
|
.FocusWhenFirstShown(false)
|
|
.SupportsMaximize(true)
|
|
.SupportsMinimize(true)
|
|
.HasCloseButton(true)
|
|
[
|
|
SNew(SBorder)
|
|
.BorderImage(FCoreStyle::Get().GetBrush("ToolPanel.GroupBorder"))
|
|
[
|
|
SNew(SVerticalBox)
|
|
|
|
// Menu
|
|
+ SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
[
|
|
MakeMainMenu()
|
|
]
|
|
|
|
// Login panel
|
|
+ SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
.Padding(0.0f, 10.0f, 5.0f, 0.0f)
|
|
.HAlign(HAlign_Fill)
|
|
.VAlign(VAlign_Top)
|
|
[
|
|
SNew(SBuildLogin)
|
|
.ZenServiceInstance(ZenServiceInstanceManager.ToSharedRef(), &UE::Zen::FServiceInstanceManager::GetZenServiceInstance)
|
|
.BuildServiceInstance(BuildServiceInstanceManager.ToSharedRef(), &UE::Zen::Build::FServiceInstanceManager::GetBuildServiceInstance)
|
|
]
|
|
|
|
// Selection panel
|
|
+ SVerticalBox::Slot()
|
|
.Padding(0.0f, 10.0f, 5.0f, 0.0f)
|
|
.HAlign(HAlign_Fill)
|
|
.VAlign(VAlign_Top)
|
|
[
|
|
SNew(SBuildSelection)
|
|
.ZenServiceInstance(ZenServiceInstanceManager.ToSharedRef(), &UE::Zen::FServiceInstanceManager::GetZenServiceInstance)
|
|
.BuildServiceInstance(BuildServiceInstanceManager.ToSharedRef(), &UE::Zen::Build::FServiceInstanceManager::GetBuildServiceInstance)
|
|
.OnBuildTransferStarted_Lambda([this]
|
|
(UE::Zen::Build::FBuildServiceInstance::FBuildTransfer Transfer, FStringView Name, FStringView Platform)
|
|
{
|
|
BuildActivity->AddBuildTransfer(Transfer, Name, Platform);
|
|
})
|
|
]
|
|
|
|
// Activity panel
|
|
+ SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
.Padding(0.0f, 10.0f, 5.0f, 0.0f)
|
|
.HAlign(HAlign_Fill)
|
|
.VAlign(VAlign_Bottom)
|
|
[
|
|
SAssignNew(BuildActivity, SBuildActivity)
|
|
.ZenServiceInstance(ZenServiceInstanceManager.ToSharedRef(), &UE::Zen::FServiceInstanceManager::GetZenServiceInstance)
|
|
.BuildServiceInstance(BuildServiceInstanceManager.ToSharedRef(), &UE::Zen::Build::FServiceInstanceManager::GetBuildServiceInstance)
|
|
]
|
|
]
|
|
];
|
|
|
|
Slate.AddWindow(Window.ToSharedRef(), true);
|
|
|
|
// Setting focus seems to have to happen after the Window has been added
|
|
Slate.ClearKeyboardFocus(EFocusCause::Cleared);
|
|
|
|
// loop until the app is ready to quit
|
|
while (!IsEngineExitRequested())
|
|
{
|
|
BeginExitIfRequested();
|
|
|
|
FTaskGraphInterface::Get().ProcessThreadUntilIdle(ENamedThreads::GameThread);
|
|
FTSTicker::GetCoreTicker().Tick(FApp::GetDeltaTime());
|
|
Slate.PumpMessages();
|
|
Slate.Tick();
|
|
|
|
FPlatformProcess::Sleep(1.0f / 30.0f);
|
|
}
|
|
|
|
// Make sure the window is hidden, because it might take a while for the background thread to finish.
|
|
Window->HideWindow();
|
|
}
|
|
|
|
private:
|
|
FText GetWindowTitle()
|
|
{
|
|
return LOCTEXT("WindowTitle", "Unreal Build Storage Tool");
|
|
}
|
|
|
|
EAppReturnType::Type OnModalMessageDialog(EAppMsgCategory InMessageCategory, EAppMsgType::Type InMessage, const FText& InText, const FText& InTitle)
|
|
{
|
|
if (IsInGameThread() && FSlateApplication::IsInitialized() && FSlateApplication::Get().CanAddModalWindow())
|
|
{
|
|
return OpenModalMessageDialog_Internal(InMessageCategory, InMessage, InText, InTitle, Window);
|
|
}
|
|
else
|
|
{
|
|
return FPlatformMisc::MessageBoxExt(InMessage, *InText.ToString(), *InTitle.ToString());
|
|
}
|
|
}
|
|
|
|
void InstallMessageDialogOverride()
|
|
{
|
|
FCoreDelegates::ModalMessageDialog.BindRaw(this, &FBuildStorageToolApp::OnModalMessageDialog);
|
|
}
|
|
|
|
void RemoveMessageDialogOverride()
|
|
{
|
|
FCoreDelegates::ModalMessageDialog.Unbind();
|
|
}
|
|
|
|
TSharedPtr<SBuildActivity> BuildActivity;
|
|
};
|
|
|
|
int BuildStorageToolMain(const TCHAR* CmdLine)
|
|
{
|
|
ON_SCOPE_EXIT
|
|
{
|
|
RequestEngineExit(TEXT("Exiting"));
|
|
FEngineLoop::AppPreExit();
|
|
FModuleManager::Get().UnloadModulesAtShutdown();
|
|
FEngineLoop::AppExit();
|
|
};
|
|
|
|
const FTaskTagScope Scope(ETaskTag::EGameThread);
|
|
|
|
// start up the main loop
|
|
GEngineLoop.PreInit(CmdLine);
|
|
|
|
FSystemWideCriticalSection SystemWideBuildStorageToolCritSec(TEXT("BuildStorageTool"));
|
|
if (!SystemWideBuildStorageToolCritSec.IsValid())
|
|
{
|
|
return true;
|
|
}
|
|
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
|
|
FBuildStorageToolStyle::Initialize();
|
|
|
|
// Set the icon
|
|
FAppStyle::SetAppStyleSet(FBuildStorageToolStyle::Get());
|
|
|
|
// Run the inner application loop
|
|
FBuildStorageToolApp App(Slate.Get());
|
|
App.Run();
|
|
|
|
// Clean up the custom styles
|
|
FBuildStorageToolStyle::Shutdown();
|
|
}
|
|
|
|
// Close down the Slate application
|
|
FSlateApplication::Shutdown();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
#if PLATFORM_WINDOWS
|
|
int WINAPI WinMain(_In_ HINSTANCE hCurrInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd)
|
|
{
|
|
hInstance = hCurrInstance;
|
|
return BuildStorageToolMain(GetCommandLineW())? 0 : 1;
|
|
}
|
|
|
|
#elif PLATFORM_LINUX
|
|
int main(int argc, char* argv[])
|
|
{
|
|
return CommonUnixMain(argc, argv, &BuildStorageToolMain);
|
|
}
|
|
#elif PLATFORM_MAC
|
|
int main(int argc, char* argv[])
|
|
{
|
|
[MacProgramDelegate mainWithArgc : argc argv : argv programMain : BuildStorageToolMain programExit : FEngineLoop::AppExit] ;
|
|
}
|
|
#else
|
|
#error "Unsupported platform!"
|
|
#endif
|
|
|
|
#undef LOCTEXT_NAMESPACE
|