Files
UnrealEngineUWP/Engine/Source/Programs/UnrealFrontend/Private/UnrealFrontendMain.cpp
Max Preussner 3aece47882 Docs: Removed file comments and added missing code documentation
Please note that file comments had no purpose in nearly all cases and just added visual clutter. The two files that had meaningful file comments had their comments moved into the corresponding classes. There are still hundreds of file comments left in other files that will be removed over time.

Also cleaned up some random stuff along the way:
- relative paths to public headers within the same module are no longer necessary (automatically discovered by UBT now)
- header guards are deprecated, use #pragma once instead (all compilers support it now)
- space between multiple template brackets is no longer required (all compilers support >> now)
- NULL to nullptr, OVERRIDE to override
- spelling errors, whitespace, line breaks

[CL 2104067 by Max Preussner in Main branch]
2014-06-12 23:22:18 -04:00

512 lines
14 KiB
C++

// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
#include "UnrealFrontendMain.h"
#include "RequiredProgramMainCPPInclude.h"
#include "AutomationController.h"
#include "DeviceManager.h"
#include "ProfilerClient.h"
#include "SessionFrontend.h"
#include "StatsData.h"
#include "StatsFile.h"
#include "EditorStyle.h"
#include "SlateReflector.h"
IMPLEMENT_APPLICATION(UnrealFrontend, "UnrealFrontend");
#define IDEAL_FRAMERATE 60;
namespace WorkspaceMenu
{
TSharedRef<FWorkspaceItem> DeveloperTools = FWorkspaceItem::NewGroup( NSLOCTEXT("UnrealFrontend", "DeveloperToolsMenu", "Developer Tools") );
}
void RunPackageCommand()
{
FString SourceDir;
FParse::Value(FCommandLine::Get(), TEXT("-SOURCEDIR="), SourceDir);
ITargetPlatformManagerModule* TPM = GetTargetPlatformManager();
if (TPM)
{
const TArray<ITargetPlatform*>& Platforms = TPM->GetActiveTargetPlatforms();
for (int32 Index = 0; Index < Platforms.Num(); ++Index)
{
if (Platforms[Index]->PackageBuild(SourceDir))
{
}
}
}
}
bool RunDeployCommand()
{
bool bDeployed = false;
// get the target device
FString Device;
FParse::Value(FCommandLine::Get(), TEXT("-DEVICE="), Device);
// get the file manifest
FString Manifest;
FParse::Value(FCommandLine::Get(), TEXT("-MANIFEST="), Manifest);
FString SourceDir;
FParse::Value(FCommandLine::Get(), TEXT("-SOURCEDIR="), SourceDir);
ITargetPlatformManagerModule* TPM = GetTargetPlatformManager();
if (!TPM)
{
return false;
}
// Initialize the messaging subsystem so we can do device discovery.
FModuleManager::LoadModuleChecked<IMessagingModule>("Messaging");
// load plug-in modules
// @todo: allow for better plug-in support in standalone Slate apps
IPluginManager::Get().LoadModulesForEnabledPlugins(ELoadingPhase::PreDefault);
double DeltaTime = 0.0;
double LastTime = FPlatformTime::Seconds();
// We track the message sent time because we have to keep updating the loop until the message is *actually sent*. (ie all packets queued, sent, buffer flushed, etc.)
double MessageSentTime = 0.0;
bool bMessageSent = false;
while ( !GIsRequestingExit && (MessageSentTime > LastTime + 1.0 || MessageSentTime <= 0.1) )
{
FTaskGraphInterface::Get().ProcessThreadUntilIdle(ENamedThreads::GameThread);
FTicker::GetCoreTicker().Tick(DeltaTime);
FPlatformProcess::Sleep(0);
DeltaTime = FPlatformTime::Seconds() - LastTime;
LastTime = FPlatformTime::Seconds();
if ( !bMessageSent )
{
const TArray<ITargetPlatform*>& Platforms = TPM->GetActiveTargetPlatforms();
FString Platform;
FString DeviceName;
Device.Split(TEXT("@"), &Platform, &DeviceName);
FTargetDeviceId DeviceId(Platform, DeviceName);
ITargetDevicePtr TargetDevice;
for (int32 Index = 0; Index < Platforms.Num(); ++Index)
{
TargetDevice = Platforms[Index]->GetDevice(DeviceId);
if (TargetDevice.IsValid())
{
FString OutId;
if (Platforms[Index]->PackageBuild(SourceDir))
{
if (TargetDevice->Deploy(SourceDir, OutId))
{
bDeployed = true;
}
MessageSentTime = LastTime;
bMessageSent = true;
}
else
{
MessageSentTime = LastTime;
bMessageSent = true;
}
}
}
}
}
return bDeployed;
}
bool RunLaunchCommand(const FString& Params)
{
bool bLaunched = false;
// get the target device
FString Device;
FParse::Value(FCommandLine::Get(), TEXT("-DEVICE="), Device);
// get the executable to launch
FString Executable;
FParse::Value(FCommandLine::Get(), TEXT("-EXE="), Executable);
ITargetPlatformManagerModule* TPM = GetTargetPlatformManager();
if (!TPM)
{
return false;
}
// Initialize the messaging subsystem so we can do device discovery.
FModuleManager::LoadModuleChecked<IMessagingModule>("Messaging");
// load plug-in modules
// @todo: allow for better plug-in support in standalone Slate apps
IPluginManager::Get().LoadModulesForEnabledPlugins(ELoadingPhase::PreDefault);
double DeltaTime = 0.0;
double LastTime = FPlatformTime::Seconds();
static int32 MasterDisableChangeTagStartFrame = -1;
// We track the message sent time because we have to keep updating the loop until the message is *actually sent*. (ie all packets queued, sent, buffer flushed, etc.)
double MessageSentTime = 0.0;
bool bMessageSent = false;
while ( !GIsRequestingExit && (MessageSentTime > LastTime + 1.0 || MessageSentTime <= 0.1) )
{
FTaskGraphInterface::Get().ProcessThreadUntilIdle(ENamedThreads::GameThread);
FTicker::GetCoreTicker().Tick(DeltaTime);
FPlatformProcess::Sleep(0);
DeltaTime = FPlatformTime::Seconds() - LastTime;
LastTime = FPlatformTime::Seconds();
if ( !bMessageSent )
{
const TArray<ITargetPlatform*>& Platforms = TPM->GetActiveTargetPlatforms();
FString Platform;
FString DeviceName;
Device.Split(TEXT("@"), &Platform, &DeviceName);
FTargetDeviceId DeviceId(Platform, DeviceName);
ITargetDevicePtr TargetDevice;
for (int32 Index = 0; Index < Platforms.Num(); ++Index)
{
TargetDevice = Platforms[Index]->GetDevice(DeviceId);
if (TargetDevice.IsValid())
{
uint32 OutId;
if (TargetDevice->Run(Executable, Params, &OutId))
{
MessageSentTime = LastTime;
bMessageSent = true;
bLaunched = true;
}
else
{
MessageSentTime = LastTime;
bMessageSent = true;
}
}
}
}
}
return bLaunched;
}
void WriteString(FArchive* File, const ANSICHAR* Format, ...)
{
if( File != NULL )
{
check(File);
ANSICHAR Array[1024];
va_list ArgPtr;
va_start(ArgPtr,Format);
// Build the string
int32 Result = FCStringAnsi::GetVarArgs(Array,ARRAY_COUNT(Array),ARRAY_COUNT(Array)-1,Format,ArgPtr);
// Now write that to the file
File->Serialize((void*)Array,Result);
}
}
void RunStatsConvertCommand()
{
#if STATS
// get the target file
FString TargetFile;
FParse::Value(FCommandLine::Get(), TEXT("-INFILE="), TargetFile);
FString OutFile;
FParse::Value(FCommandLine::Get(), TEXT("-OUTFILE="), OutFile);
FString StatListString;
FParse::Value(FCommandLine::Get(), TEXT("-STATLIST="), StatListString);
// get the list of stats
TArray<FString> StatList;
if (StatListString.ParseIntoArray(&StatList, TEXT("+"), true) == 0)
{
StatList.Add(TEXT("STAT_FrameTime"));
}
// open a csv file for write
TAutoPtr<FArchive> FileWriter( IFileManager::Get().CreateFileWriter( *OutFile ) );
if (!FileWriter)
{
UE_LOG( LogStats, Error, TEXT( "Could not open output file: %s" ), *OutFile );
return;
}
// @TODO yrx 2014-03-24 move to function
// attempt to read the data and convert to csv
const int64 Size = IFileManager::Get().FileSize( *TargetFile );
if( Size < 4 )
{
UE_LOG( LogStats, Error, TEXT( "Could not open input file: %s" ), *TargetFile );
return;
}
TAutoPtr<FArchive> FileReader( IFileManager::Get().CreateFileReader( *TargetFile ) );
if( !FileReader )
{
UE_LOG( LogStats, Error, TEXT( "Could not open input file: %s" ), *TargetFile );
return;
}
FStatsReadStream Stream;
if( !Stream.ReadHeader( *FileReader ) )
{
UE_LOG( LogStats, Error, TEXT( "Could not open input file, bad magic: %s" ), *TargetFile );
return;
}
// This is not supported yet.
if (Stream.Header.bRawStatsFile)
{
UE_LOG( LogStats, Error, TEXT( "Could not open input file, not supported type (raw): %s" ), *TargetFile );
return;
}
// output the csv header
WriteString( FileWriter, "Frame,Name,Value\r\n" );
// read in the data
TArray<FStatMessage> Messages;
FStatsThreadState ThreadState;
while(FileReader->Tell() < FileReader->TotalSize())
{
// read the message
FStatMessage Message(Stream.ReadMessage(*FileReader));
if (Message.NameAndInfo.GetShortName() != TEXT("Unknown FName"))
{
if (Message.NameAndInfo.GetField<EStatOperation>() == EStatOperation::AdvanceFrameEventGameThread)
{
new (Messages) FStatMessage(Message);
ThreadState.AddMessages(Messages);
Messages.Reset(Messages.Num());
// get the frame time and the render time
if (ThreadState.CurrentGameFrame > 1)
{
// get the thread stats
TArray<FStatMessage> Stats;
ThreadState.GetInclusiveAggregateStackStats(ThreadState.CurrentGameFrame, Stats);
for (int32 Index = 0; Index < Stats.Num(); ++Index)
{
FStatMessage const& Meta = Stats[Index];
// UE_LOG(LogTemp, Display, TEXT("Stat: %s"), *Meta.NameAndInfo.GetShortName().ToString());
for (int32 Jndex = 0; Jndex < StatList.Num(); ++Jndex)
{
if (Meta.NameAndInfo.GetShortName().ToString() == StatList[Jndex])
{
float CycleTime = 0.0f;
if (Meta.NameAndInfo.GetFlag(EStatMetaFlags::IsPackedCCAndDuration))
{
CycleTime = FPlatformTime::ToMilliseconds( FromPackedCallCountDuration_Duration(Meta.GetValue_int64()) );
}
else if (Meta.NameAndInfo.GetFlag(EStatMetaFlags::IsCycle))
{
CycleTime = FPlatformTime::ToMilliseconds( Meta.GetValue_int64() );
}
else
{
CycleTime = Meta.GetValue_int64();
}
// write out to the csv file
WriteString(FileWriter, "%d,%S,%f\r\n", ThreadState.CurrentGameFrame, *StatList[Jndex], CycleTime);
}
}
}
}
}
new (Messages) FStatMessage(Message);
}
else
{
break;
}
}
#endif // STATS
}
void RunUI()
{
FString UnrealFrontendLayoutIni = FPaths::GetPath(GEngineIni) + "/Layout.ini";
FSlateApplication::InitializeAsStandaloneApplication(GetStandardStandaloneRenderer());
// The frontend currently relies on EditorStyle being loaded
FModuleManager::LoadModuleChecked<IEditorStyleModule>("EditorStyle");
// initialize messaging subsystem
FModuleManager::LoadModuleChecked<IMessagingModule>("Messaging");
// load plug-in modules
// @todo: allow for better plug-in support in standalone Slate apps
IPluginManager::Get().LoadModulesForEnabledPlugins(ELoadingPhase::PreDefault);
// initialize automation tests
IAutomationControllerModule& AutomationControllerModule = FModuleManager::LoadModuleChecked<IAutomationControllerModule>("AutomationController");
AutomationControllerModule.Init();
// initialize profiler
FModuleManager::Get().LoadModule("ProfilerClient");
// initialize user interface
FModuleManager::Get().LoadModule("DeviceManager");
FModuleManager::Get().LoadModule("SessionFrontend");
FModuleManager::Get().LoadModule("SessionLauncher");
FModuleManager::Get().LoadModule("SettingsEditor");
// Create developer tools menu with widget reflector.
FModuleManager::LoadModuleChecked<ISlateReflectorModule>("SlateReflector").RegisterTabSpawner(WorkspaceMenu::DeveloperTools);
// check to see if want the widget reflector
const bool bAllowDebugTools = FParse::Param(FCommandLine::Get(), TEXT("DebugTools"));
// set the application name
FGlobalTabmanager::Get()->SetApplicationTitle(NSLOCTEXT("UnrealFrontend", "AppTitle", "Unreal Frontend"));
// restore application layout
TSharedRef<FTabManager::FLayout> NewLayout = FTabManager::NewLayout("SessionFrontendLayout_v1.1")
->AddArea
(
FTabManager::NewArea(1280.f, 720.0f)
->Split
(
FTabManager::NewStack()
->AddTab(FName("DeviceManager"), ETabState::OpenedTab)
->AddTab(FName("MessagingDebugger"), ETabState::ClosedTab)
->AddTab(FName("SessionLauncher"), ETabState::OpenedTab)
->AddTab(FName("SessionFrontend"), ETabState::OpenedTab)
)
)
->AddArea
(
FTabManager::NewArea(600.0f, 600.0f)
->SetWindow(FVector2D(10.0f, 10.0f), false)
->Split
(
FTabManager::NewStack()->AddTab("WidgetReflector", bAllowDebugTools ? ETabState::OpenedTab : ETabState::ClosedTab)
)
);
TSharedRef<FTabManager::FLayout> UserConfiguredNewLayout = FLayoutSaveRestore::LoadFromConfig(UnrealFrontendLayoutIni, NewLayout);
FGlobalTabmanager::Get()->RestoreFrom(UserConfiguredNewLayout, TSharedPtr<SWindow>());
// enter main loop
double DeltaTime = 0.0;
double LastTime = FPlatformTime::Seconds();
const float IdealFrameTime = 1.0f / IDEAL_FRAMERATE;
while (!GIsRequestingExit)
{
//Save the state of the tabs here rather than after close of application (the tabs are undesirably saved out with ClosedTab state on application close)
//UserConfiguredNewLayout = FGlobalTabmanager::Get()->PersistLayout();
FTaskGraphInterface::Get().ProcessThreadUntilIdle(ENamedThreads::GameThread);
FSlateApplication::Get().PumpMessages();
FSlateApplication::Get().Tick();
FTicker::GetCoreTicker().Tick(DeltaTime);
AutomationControllerModule.Tick();
// throttle frame rate
FPlatformProcess::Sleep(FMath::Max<float>(0.0f, IdealFrameTime - (FPlatformTime::Seconds() - LastTime)));
double CurrentTime = FPlatformTime::Seconds();
DeltaTime = CurrentTime - LastTime;
LastTime = CurrentTime;
FStats::AdvanceFrame( false );
GLog->FlushThreadedLogs();
}
// save application layout
FLayoutSaveRestore::SaveToConfig(UnrealFrontendLayoutIni, UserConfiguredNewLayout);
GConfig->Flush(false, UnrealFrontendLayoutIni);
// shut down application
FSlateApplication::Shutdown();
}
int32 UnrealFrontendMain( const TCHAR* CommandLine )
{
// check to see if we should run in command line mode
FString Command;
FString Params;
FString NewCommandLine = CommandLine;
bool bRunCommand = FParse::Value(*NewCommandLine, TEXT("-RUN="), Command);
if (bRunCommand)
{
// extract off any -PARAM= parameters so that they aren't accidentally parsed by engine init
FParse::Value(*NewCommandLine, TEXT("-PARAMS="), Params);
if (Params.Len() > 0)
{
// remove from the command line
NewCommandLine = NewCommandLine.Replace(*Params, TEXT(""));
// trim the quotes
Params = Params.TrimQuotes();
}
}
if (!FParse::Param(*NewCommandLine, TEXT("-Messaging")))
{
NewCommandLine += TEXT(" -Messaging");
}
GEngineLoop.PreInit(*NewCommandLine);
// Tell the module manager is may now process newly-loaded UObjects when new C++ modules are loaded
FModuleManager::Get().StartProcessingNewlyLoadedObjects();
bool bReturnValue = true;
if (bRunCommand)
{
if (Command.Equals(TEXT("PACKAGE"), ESearchCase::IgnoreCase))
{
RunPackageCommand();
}
else if (Command.Equals(TEXT("DEPLOY"), ESearchCase::IgnoreCase))
{
bReturnValue = RunDeployCommand();
}
else if (Command.Equals(TEXT("LAUNCH"), ESearchCase::IgnoreCase))
{
bReturnValue = RunLaunchCommand(Params);
}
else if (Command.Equals(TEXT("CONVERT"), ESearchCase::IgnoreCase))
{
RunStatsConvertCommand();
}
}
else
{
RunUI();
}
FEngineLoop::AppPreExit();
FModuleManager::Get().UnloadModulesAtShutdown();
#if STATS
FThreadStats::StopThread();
#endif
FTaskGraphInterface::Shutdown();
return bReturnValue ? 0 : -1;
}