Add Cook&Run and Run cooked game utilities to Game menu list for multilayer games testing

This commit is contained in:
Wojciech Figat
2022-09-07 11:52:11 +02:00
parent 94cacc8abc
commit 9a77517cb4
8 changed files with 154 additions and 7 deletions

View File

@@ -26,6 +26,16 @@ API_ENUM(Attributes="Flags") enum class BuildOptions
/// Shows the output directory folder on building end.
/// </summary>
ShowOutput = 1 << 0,
/// <summary>
/// Starts the cooked game build on building end.
/// </summary>
AutoRun = 1 << 1,
/// <summary>
/// Skips cooking logic and uses already cooked data (eg. to only use AutoRun or ShowOutput feature).
/// </summary>
NoCook = 1 << 2,
};
DECLARE_ENUM_OPERATORS(BuildOptions);

View File

@@ -430,6 +430,52 @@ void GameCooker::Cancel(bool waitForEnd)
}
}
void GameCooker::GetCurrentPlatform(PlatformType& platform, BuildPlatform& buildPlatform, BuildConfiguration& buildConfiguration)
{
platform = PLATFORM_TYPE;
#if BUILD_DEBUG
buildConfiguration = BuildConfiguration::Debug;
#elif BUILD_DEVELOPMENT
buildConfiguration = BuildConfiguration::Development;
#elif BUILD_RELEASE
buildConfiguration = BuildConfiguration::Release;
#endif
switch (PLATFORM_TYPE)
{
case PlatformType::Windows:
buildPlatform = PLATFORM_64BITS ? BuildPlatform::Windows64 : BuildPlatform::Windows32;
break;
case PlatformType::XboxOne:
buildPlatform = BuildPlatform::XboxOne;
break;
case PlatformType::UWP:
buildPlatform = BuildPlatform::UWPx64;
break;
case PlatformType::Linux:
buildPlatform = BuildPlatform::LinuxX64;
break;
case PlatformType::PS4:
buildPlatform = BuildPlatform::PS4;
break;
case PlatformType::XboxScarlett:
buildPlatform = BuildPlatform::XboxScarlett;
break;
case PlatformType::Android:
buildPlatform = BuildPlatform::AndroidARM64;
break;
case PlatformType::Switch:
buildPlatform = BuildPlatform::Switch;
break;
case PlatformType::PS5:
buildPlatform = BuildPlatform::PS5;
break;
case PlatformType::Mac:
buildPlatform = BuildPlatform::MacOSx64;
break;
default: ;
}
}
void GameCookerImpl::CallEvent(GameCooker::EventType type)
{
if (Internal_OnEvent == nullptr)
@@ -492,7 +538,6 @@ bool GameCookerImpl::Build()
// Late init feature
if (Steps.IsEmpty())
{
// Create steps
Steps.Add(New<ValidateStep>());
Steps.Add(New<CompileScriptsStep>());
Steps.Add(New<DeployDataStep>());
@@ -517,6 +562,8 @@ bool GameCookerImpl::Build()
{
if (GameCooker::IsCancelRequested())
break;
if (data.Options & BuildOptions::NoCook)
continue;
auto step = Steps[stepIndex];
data.NextStep();
@@ -544,6 +591,24 @@ bool GameCookerImpl::Build()
{
FileSystem::ShowFileExplorer(data.OriginalOutputPath);
}
if (data.Options & BuildOptions::AutoRun)
{
String executableFile, commandLineFormat, workingDir;
data.Tools->OnRun(data, executableFile, commandLineFormat, workingDir);
if (executableFile.HasChars())
{
const String gameArgs; // TODO: pass custom game run args from Editor? eg. starting map? or client info?
const String commandLine = commandLineFormat.HasChars() ? String::Format(*commandLineFormat, gameArgs) : gameArgs;
if (workingDir.IsEmpty())
workingDir = data.NativeCodeOutputPath;
Platform::StartProcess(executableFile, commandLine, workingDir);
}
else
{
LOG(Warning, "Missing executable to run or platform doesn't support build&run.");
}
}
}
IsRunning = false;
CancelFlag = 0;

View File

@@ -90,6 +90,11 @@ public:
/// <param name="waitForEnd">If set to <c>true</c> wait for the stopped building end.</param>
API_FUNCTION() static void Cancel(bool waitForEnd = false);
/// <summary>
/// Gets the current Editor build info (platform, configuration, etc).
/// </summary>
API_FUNCTION() static void GetCurrentPlatform(API_PARAM(Out) PlatformType& platform, API_PARAM(Out) BuildPlatform& buildPlatform, API_PARAM(Out) BuildConfiguration& buildConfiguration);
/// <summary>
/// Building event type.
/// </summary>

View File

@@ -36,11 +36,10 @@ ArchitectureType WindowsPlatformTools::GetArchitecture() const
bool WindowsPlatformTools::OnDeployBinaries(CookingData& data)
{
const auto platformSettings = WindowsPlatformSettings::Get();
const auto& outputPath = data.NativeCodeOutputPath;
// Apply executable icon
Array<String> files;
FileSystem::DirectoryGetFiles(files, outputPath, TEXT("*.exe"), DirectorySearchOption::TopDirectoryOnly);
FileSystem::DirectoryGetFiles(files, data.NativeCodeOutputPath, TEXT("*.exe"), DirectorySearchOption::TopDirectoryOnly);
if (files.HasItems())
{
TextureData iconData;
@@ -57,4 +56,15 @@ bool WindowsPlatformTools::OnDeployBinaries(CookingData& data)
return false;
}
void WindowsPlatformTools::OnRun(CookingData& data, String& executableFile, String& commandLineFormat, String& workingDir)
{
// Pick the first executable file
Array<String> files;
FileSystem::DirectoryGetFiles(files, data.NativeCodeOutputPath, TEXT("*.exe"), DirectorySearchOption::TopDirectoryOnly);
if (files.HasItems())
{
executableFile = files[0];
}
}
#endif

View File

@@ -30,6 +30,7 @@ public:
PlatformType GetPlatform() const override;
ArchitectureType GetArchitecture() const override;
bool OnDeployBinaries(CookingData& data) override;
void OnRun(CookingData& data, String& executableFile, String& commandLineFormat, String& workingDir) override;
};
#endif

View File

@@ -203,4 +203,15 @@ public:
{
return false;
}
/// <summary>
/// Called to run the cooked game build on device.
/// </summary>
/// <param name="data">The cooking data.</param>
/// <param name="executableFile">The game executable file path to run (or tool path to run if build should run on remote device). Empty if not supported.</param>
/// <param name="commandLineFormat">The command line for executable file. Use `{0}` to insert custom command line for passing to the cooked game.</param>
/// <param name="workingDir">Overriden custom working directory to use. Leave empty if use cooked data output folder.</param>
virtual void OnRun(CookingData& data, String& executableFile, String& commandLineFormat, String& workingDir)
{
}
};

View File

@@ -485,6 +485,9 @@ namespace FlaxEditor.Modules
cm.VisibleChanged += OnMenuGameShowHide;
_menuGamePlay = cm.AddButton("Play", "F5", Editor.Simulation.RequestStartPlay);
_menuGamePause = cm.AddButton("Pause", "F6", Editor.Simulation.RequestPausePlay);
cm.AddSeparator();
cm.AddButton("Cook&Run", Editor.Windows.GameCookerWin.BuildAndRun).LinkTooltip("Runs Game Cooker to build the game for this platform and runs the game after.");
cm.AddButton("Run cooked game", Editor.Windows.GameCookerWin.RunCooked).LinkTooltip("Runs the game build from the last cooking output. Use Cook&Play or Game Cooker first.");
// Tools
MenuTools = MainMenu.AddButton("Tools");

View File

@@ -35,7 +35,7 @@ namespace FlaxEditor.Windows
public readonly GameCookerWindow GameCookerWin;
public readonly PlatformSelector Selector;
private readonly Dictionary<PlatformType, Platform> PerPlatformOptions = new Dictionary<PlatformType, Platform>
internal readonly Dictionary<PlatformType, Platform> PerPlatformOptions = new Dictionary<PlatformType, Platform>
{
{ PlatformType.Windows, new Windows() },
{ PlatformType.XboxOne, new XboxOne() },
@@ -67,7 +67,7 @@ namespace FlaxEditor.Windows
}
[HideInEditor]
abstract class Platform
internal abstract class Platform
{
[HideInEditor]
public bool IsSupported;
@@ -490,10 +490,12 @@ namespace FlaxEditor.Windows
{
public string PresetName;
public BuildTarget Target;
public BuildOptions Options;
}
private PresetsColumn _presets;
private TargetsColumn _targets;
private BuildTabProxy _buildTabProxy;
private int _selectedPresetIndex = -1;
private int _selectedTargetIndex = -1;
private CustomEditorPresenter _targetSettings;
@@ -617,6 +619,44 @@ namespace FlaxEditor.Windows
});
}
/// <summary>
/// Builds the target for this platform and runs it on this device.
/// </summary>
public void BuildAndRun()
{
Editor.Log("Building and running");
GameCooker.GetCurrentPlatform(out var platform, out var buildPlatform, out var buildConfiguration);
_buildingQueue.Enqueue(new QueueItem
{
Target = new BuildTarget
{
Output = _buildTabProxy.PerPlatformOptions[platform].Output,
Platform = buildPlatform,
Mode = buildConfiguration,
},
Options = BuildOptions.AutoRun,
});
}
/// <summary>
/// Runs the cooked game for this platform on this device.
/// </summary>
public void RunCooked()
{
Editor.Log("Running cooked build");
GameCooker.GetCurrentPlatform(out var platform, out var buildPlatform, out var buildConfiguration);
_buildingQueue.Enqueue(new QueueItem
{
Target = new BuildTarget
{
Output = _buildTabProxy.PerPlatformOptions[platform].Output,
Platform = buildPlatform,
Mode = buildConfiguration,
},
Options = BuildOptions.AutoRun | BuildOptions.NoCook,
});
}
private void BuildTarget()
{
if (_data == null || _data.Length <= _selectedPresetIndex || _selectedPresetIndex == -1)
@@ -829,7 +869,8 @@ namespace FlaxEditor.Windows
var settings = new CustomEditorPresenter(null);
settings.Panel.Parent = panel;
settings.Select(new BuildTabProxy(this, platformSelector));
_buildTabProxy = new BuildTabProxy(this, platformSelector);
settings.Select(_buildTabProxy);
}
private void OnPlatformSelectorSizeChanged(Control platformSelector)
@@ -894,7 +935,7 @@ namespace FlaxEditor.Windows
_preBuildAction = target.PreBuildAction;
_postBuildAction = target.PostBuildAction;
GameCooker.Build(target.Platform, target.Mode, target.Output, BuildOptions.None, target.CustomDefines, item.PresetName, target.Name);
GameCooker.Build(target.Platform, target.Mode, target.Output, item.Options, target.CustomDefines, item.PresetName, target.Name);
}
else if (_exitOnBuildEnd)
{
@@ -908,6 +949,7 @@ namespace FlaxEditor.Windows
public override void OnDestroy()
{
GameCooker.Event -= OnGameCookerEvent;
_buildTabProxy = null;
base.OnDestroy();
}