2014-12-07 19:09:38 -05:00
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
2014-03-14 14:13:41 -04:00
using System ;
using System.Collections.Generic ;
2014-09-22 11:23:43 -04:00
using System.Text.RegularExpressions ;
2014-03-14 14:13:41 -04:00
using System.Linq ;
using System.Text ;
using System.IO ;
using AutomationTool ;
using UnrealBuildTool ;
2014-09-15 10:56:03 -04:00
using System.Diagnostics ;
using System.Threading ;
2014-03-14 14:13:41 -04:00
public class HTML5Platform : Platform
{
2015-04-08 14:53:36 -04:00
public HTML5Platform ( )
2014-08-18 13:29:39 -04:00
: base ( UnrealTargetPlatform . HTML5 )
2014-03-14 14:13:41 -04:00
{
}
public override void Package ( ProjectParams Params , DeploymentContext SC , int WorkingCL )
{
2015-04-09 14:18:38 -04:00
Log ( "Package {0}" , Params . RawProjectPath ) ;
2014-10-31 04:31:19 -04:00
2015-04-08 14:53:36 -04:00
string PackagePath = Path . Combine ( Path . GetDirectoryName ( Params . RawProjectPath ) , "Binaries" , "HTML5" ) ;
if ( ! Directory . Exists ( PackagePath ) )
{
Directory . CreateDirectory ( PackagePath ) ;
}
string FinalDataLocation = Path . Combine ( PackagePath , Params . ShortProjectName ) + ".data" ;
2014-07-07 19:15:12 -04:00
2015-04-09 14:18:38 -04:00
var ConfigCache = new UnrealBuildTool . ConfigCacheIni ( UnrealTargetPlatform . HTML5 , "Engine" , Path . GetDirectoryName ( Params . RawProjectPath ) , CommandUtils . CombinePaths ( CommandUtils . CmdEnv . LocalRoot , "Engine" ) ) ;
2015-04-08 14:53:36 -04:00
2015-04-09 14:18:38 -04:00
if ( HTMLPakAutomation . CanCreateMapPaks ( Params ) )
2015-04-08 14:53:36 -04:00
{
HTMLPakAutomation PakAutomation = new HTMLPakAutomation ( Params , SC ) ;
// Create Necessary Paks.
PakAutomation . CreateEnginePak ( ) ;
PakAutomation . CreateGamePak ( ) ;
PakAutomation . CreateContentDirectoryPak ( ) ;
// Create Emscripten Package from Necessary Paks. - This will be the VFS.
PakAutomation . CreateEmscriptenDataPackage ( PackagePath , FinalDataLocation ) ;
// Create All Map Paks which will be downloaded on the fly.
PakAutomation . CreateMapPak ( ) ;
// Create Delta Paks if setup.
List < string > Paks = new List < string > ( ) ;
ConfigCache . GetArray ( "/Script/HTML5PlatformEditor.HTML5TargetSettings" , "LevelTransitions" , out Paks ) ;
if ( Paks ! = null )
{
foreach ( var Pak in Paks )
{
var Matched = Regex . Matches ( Pak , "\"[^\"]+\"" , RegexOptions . IgnoreCase ) ;
string MapFrom = Path . GetFileNameWithoutExtension ( Matched [ 0 ] . ToString ( ) . Replace ( "\"" , "" ) ) ;
string MapTo = Path . GetFileNameWithoutExtension ( Matched [ 1 ] . ToString ( ) . Replace ( "\"" , "" ) ) ;
PakAutomation . CreateDeltaMapPaks ( MapFrom , MapTo ) ;
}
}
}
else
{
// we need to operate in the root
2014-10-31 04:31:19 -04:00
using ( new PushedDirectory ( Path . Combine ( Params . BaseStageDirectory , "HTML5" ) ) )
2014-09-22 11:23:43 -04:00
{
2014-10-31 04:31:19 -04:00
string PythonPath = HTML5SDKInfo . PythonPath ( ) ;
string PackagerPath = HTML5SDKInfo . EmscriptenPackager ( ) ;
2014-11-14 07:00:34 -05:00
string CmdLine = string . Format ( "\"{0}\" \"{1}\" --preload . --js-output=\"{1}.js\"" , PackagerPath , FinalDataLocation ) ;
2014-10-31 04:31:19 -04:00
RunAndLog ( CmdEnv , PythonPath , CmdLine ) ;
2014-09-22 11:23:43 -04:00
}
2015-04-08 14:53:36 -04:00
}
2014-09-24 13:56:28 -04:00
2015-04-08 14:53:36 -04:00
// copy the "Executable" to the package directory
string GameExe = Path . GetFileNameWithoutExtension ( Params . ProjectGameExeFilename ) ;
if ( Params . ClientConfigsToBuild [ 0 ] . ToString ( ) ! = "Development" )
{
GameExe + = "-HTML5-" + Params . ClientConfigsToBuild [ 0 ] . ToString ( ) ;
}
GameExe + = ".js" ;
2015-02-01 12:33:30 -05:00
2015-04-08 14:53:36 -04:00
// ensure the ue4game binary exists, if applicable
string FullGameExePath = Path . Combine ( Path . GetDirectoryName ( Params . ProjectGameExeFilename ) , GameExe ) ;
if ( ! SC . IsCodeBasedProject & & ! FileExists_NoExceptions ( FullGameExePath ) )
{
Log ( "Failed to find game application " + FullGameExePath ) ;
AutomationTool . ErrorReporter . Error ( "Stage Failed." , ( int ) AutomationTool . ErrorCodes . Error_MissingExecutable ) ;
throw new AutomationException ( "Could not find application {0}. You may need to build the UE4 project with your target configuration and platform." , FullGameExePath ) ;
}
2015-02-01 12:33:30 -05:00
2015-04-08 14:53:36 -04:00
if ( Path . Combine ( Path . GetDirectoryName ( Params . ProjectGameExeFilename ) , GameExe ) ! = Path . Combine ( PackagePath , GameExe ) )
{
File . Copy ( Path . Combine ( Path . GetDirectoryName ( Params . ProjectGameExeFilename ) , GameExe ) , Path . Combine ( PackagePath , GameExe ) , true ) ;
File . Copy ( Path . Combine ( Path . GetDirectoryName ( Params . ProjectGameExeFilename ) , GameExe ) + ".mem" , Path . Combine ( PackagePath , GameExe ) + ".mem" , true ) ;
}
File . SetAttributes ( Path . Combine ( PackagePath , GameExe ) , FileAttributes . Normal ) ;
File . SetAttributes ( Path . Combine ( PackagePath , GameExe ) + ".mem" , FileAttributes . Normal ) ;
// put the HTML file to the package directory
2015-04-22 14:26:39 -04:00
bool UseExperimentalTemplate = false ;
ConfigCache . GetBool ( "/Script/HTML5PlatformEditor.HTML5TargetSettings" , "UseExperimentalTemplate" , out UseExperimentalTemplate ) ;
string TemplateFileName = UseExperimentalTemplate ? "GameX.html.template" : "Game.html.template" ;
string TemplateFile = Path . Combine ( CombinePaths ( CmdEnv . LocalRoot , "Engine" ) , "Build" , "HTML5" , TemplateFileName ) ;
2015-04-08 14:53:36 -04:00
string OutputFile = Path . Combine ( PackagePath , ( Params . ClientConfigsToBuild [ 0 ] . ToString ( ) ! = "Development" ? ( Params . ShortProjectName + "-HTML5-" + Params . ClientConfigsToBuild [ 0 ] . ToString ( ) ) : Params . ShortProjectName ) ) + ".html" ;
// find Heap Size.
ulong HeapSize ;
int ConfigHeapSize = 0 ;
// Valuer set by Editor UI
var bGotHeapSize = ConfigCache . GetInt32 ( "/Script/HTML5PlatformEditor.HTML5TargetSettings" , "HeapSize" + Params . ClientConfigsToBuild [ 0 ] . ToString ( ) , out ConfigHeapSize ) ;
// Fallback if the previous method failed
if ( ! bGotHeapSize & & ! ConfigCache . GetInt32 ( "BuildSettings" , "HeapSize" + Params . ClientConfigsToBuild [ 0 ] . ToString ( ) , out ConfigHeapSize ) ) // in Megs.
{
// we couldn't find a per config heap size, look for a common one.
if ( ! ConfigCache . GetInt32 ( "BuildSettings" , "HeapSize" , out ConfigHeapSize ) )
2014-10-31 04:31:19 -04:00
{
2015-04-08 14:53:36 -04:00
ConfigHeapSize = Params . IsCodeBasedProject ? 1024 : 512 ;
Log ( "Could not find Heap Size setting in .ini for Client config {0}" , Params . ClientConfigsToBuild [ 0 ] . ToString ( ) ) ;
2014-10-31 04:31:19 -04:00
}
2015-04-08 14:53:36 -04:00
}
2014-10-31 04:31:19 -04:00
2015-04-08 14:53:36 -04:00
HeapSize = ( ulong ) ConfigHeapSize * 1024L * 1024L ; // convert to bytes.
Log ( "Setting Heap size to {0} Mb " , ConfigHeapSize ) ;
2014-07-07 19:15:12 -04:00
2015-04-08 14:53:36 -04:00
GenerateFileFromTemplate ( TemplateFile , OutputFile , Params . ShortProjectName , Params . ClientConfigsToBuild [ 0 ] . ToString ( ) , Params . StageCommandline , ! Params . IsCodeBasedProject , HeapSize ) ;
2014-07-07 19:15:12 -04:00
2015-04-08 14:53:36 -04:00
// copy the jstorage files to the binaries directory
string JSDir = Path . Combine ( CombinePaths ( CmdEnv . LocalRoot , "Engine" ) , "Build" , "HTML5" ) ;
string OutDir = PackagePath ;
File . Copy ( JSDir + "/json2.js" , OutDir + "/json2.js" , true ) ;
File . SetAttributes ( OutDir + "/json2.js" , FileAttributes . Normal ) ;
File . Copy ( JSDir + "/jStorage.js" , OutDir + "/jStorage.js" , true ) ;
File . SetAttributes ( OutDir + "/jStorage.js" , FileAttributes . Normal ) ;
File . Copy ( JSDir + "/moz_binarystring.js" , OutDir + "/moz_binarystring.js" , true ) ;
File . SetAttributes ( OutDir + "/moz_binarystring.js" , FileAttributes . Normal ) ;
PrintRunTime ( ) ;
2014-03-14 14:13:41 -04:00
}
2014-09-22 14:24:24 -04:00
public override bool RequiresPackageToDeploy
{
get { return true ; }
}
2014-05-29 17:32:36 -04:00
protected void GenerateFileFromTemplate ( string InTemplateFile , string InOutputFile , string InGameName , string InGameConfiguration , string InArguments , bool IsContentOnly , ulong HeapSize )
2014-03-14 14:13:41 -04:00
{
StringBuilder outputContents = new StringBuilder ( ) ;
using ( StreamReader reader = new StreamReader ( InTemplateFile ) )
{
string LineStr = null ;
while ( reader . Peek ( ) ! = - 1 )
{
LineStr = reader . ReadLine ( ) ;
if ( LineStr . Contains ( "%GAME%" ) )
{
LineStr = LineStr . Replace ( "%GAME%" , InGameName ) ;
}
2014-08-18 13:29:39 -04:00
if ( LineStr . Contains ( "%HEAPSIZE%" ) )
2014-05-29 17:32:36 -04:00
{
2014-08-18 13:29:39 -04:00
LineStr = LineStr . Replace ( "%HEAPSIZE%" , HeapSize . ToString ( ) ) ;
2014-05-29 17:32:36 -04:00
}
2014-03-14 14:13:41 -04:00
if ( LineStr . Contains ( "%CONFIG%" ) )
{
2014-06-18 11:36:29 -04:00
if ( IsContentOnly )
InGameName = "UE4Game" ;
2014-04-23 18:20:36 -04:00
LineStr = LineStr . Replace ( "%CONFIG%" , ( InGameConfiguration ! = "Development" ? ( InGameName + "-HTML5-" + InGameConfiguration ) : InGameName ) ) ;
2014-03-14 14:13:41 -04:00
}
if ( LineStr . Contains ( "%UE4CMDLINE%" ) )
{
2014-09-15 10:56:03 -04:00
InArguments = InArguments . Replace ( "\"" , "" ) ;
2014-03-14 14:13:41 -04:00
string [ ] Arguments = InArguments . Split ( ' ' ) ;
2015-02-06 04:29:05 -05:00
string ArgumentString = IsContentOnly ? "'../../../" + InGameName + "/" + InGameName + ".uproject '," : "" ;
2014-08-18 13:29:39 -04:00
for ( int i = 0 ; i < Arguments . Length - 1 ; + + i )
2014-03-14 14:13:41 -04:00
{
ArgumentString + = "'" ;
2014-09-15 10:56:03 -04:00
ArgumentString + = Arguments [ i ] ;
2014-03-14 14:13:41 -04:00
ArgumentString + = "'" ;
ArgumentString + = ",' '," ;
}
if ( Arguments . Length > 0 )
{
ArgumentString + = "'" ;
2014-08-18 13:29:39 -04:00
ArgumentString + = Arguments [ Arguments . Length - 1 ] ;
2014-03-14 14:13:41 -04:00
ArgumentString + = "'" ;
}
LineStr = LineStr . Replace ( "%UE4CMDLINE%" , ArgumentString ) ;
}
outputContents . AppendLine ( LineStr ) ;
}
}
if ( outputContents . Length > 0 )
{
// Save the file
try
{
Directory . CreateDirectory ( Path . GetDirectoryName ( InOutputFile ) ) ;
File . WriteAllText ( InOutputFile , outputContents . ToString ( ) , Encoding . UTF8 ) ;
}
catch ( Exception )
{
// Unable to write to the project file.
}
}
}
2014-10-29 08:01:57 -04:00
public override void GetFilesToDeployOrStage ( ProjectParams Params , DeploymentContext SC )
{
}
2014-07-07 19:15:12 -04:00
public override void GetFilesToArchive ( ProjectParams Params , DeploymentContext SC )
{
if ( SC . StageTargetConfigurations . Count ! = 1 )
{
throw new AutomationException ( "iOS is currently only able to package one target configuration at a time, but StageTargetConfigurations contained {0} configurations" , SC . StageTargetConfigurations . Count ) ;
}
string PackagePath = Path . Combine ( Path . GetDirectoryName ( Params . RawProjectPath ) , "Binaries" , "HTML5" ) ;
string FinalDataLocation = Path . Combine ( PackagePath , Params . ShortProjectName ) + ".data" ;
// copy the "Executable" to the archive directory
string GameExe = Path . GetFileNameWithoutExtension ( Params . ProjectGameExeFilename ) ;
if ( Params . ClientConfigsToBuild [ 0 ] . ToString ( ) ! = "Development" )
{
GameExe + = "-HTML5-" + Params . ClientConfigsToBuild [ 0 ] . ToString ( ) ;
}
GameExe + = ".js" ;
// put the HTML file to the package directory
string OutputFile = Path . Combine ( PackagePath , ( Params . ClientConfigsToBuild [ 0 ] . ToString ( ) ! = "Development" ? ( Params . ShortProjectName + "-HTML5-" + Params . ClientConfigsToBuild [ 0 ] . ToString ( ) ) : Params . ShortProjectName ) ) + ".html" ;
SC . ArchiveFiles ( PackagePath , Path . GetFileName ( FinalDataLocation ) ) ;
2014-08-18 13:29:39 -04:00
SC . ArchiveFiles ( PackagePath , Path . GetFileName ( FinalDataLocation + ".js" ) ) ;
2014-07-07 19:15:12 -04:00
SC . ArchiveFiles ( PackagePath , Path . GetFileName ( GameExe ) ) ;
2014-08-18 13:29:39 -04:00
SC . ArchiveFiles ( PackagePath , Path . GetFileName ( GameExe + ".mem" ) ) ;
2014-07-07 19:15:12 -04:00
SC . ArchiveFiles ( PackagePath , Path . GetFileName ( "json2.js" ) ) ;
2014-11-06 15:25:26 -05:00
SC . ArchiveFiles ( PackagePath , Path . GetFileName ( "jStorage.js" ) ) ;
2014-07-07 19:15:12 -04:00
SC . ArchiveFiles ( PackagePath , Path . GetFileName ( "moz_binarystring.js" ) ) ;
SC . ArchiveFiles ( PackagePath , Path . GetFileName ( OutputFile ) ) ;
2015-04-08 14:53:36 -04:00
2015-04-09 14:18:38 -04:00
if ( HTMLPakAutomation . CanCreateMapPaks ( Params ) )
2015-04-08 14:53:36 -04:00
{
// find all paks.
string [ ] Files = Directory . GetFiles ( Path . Combine ( PackagePath , Params . ShortProjectName ) , "*" , SearchOption . AllDirectories ) ;
foreach ( string PakFile in Files )
{
var DestPak = PakFile . Replace ( PackagePath , "" ) ;
SC . ArchivedFiles . Add ( PakFile , DestPak ) ;
}
}
2014-07-07 19:15:12 -04:00
}
2014-03-14 14:13:41 -04:00
public override ProcessResult RunClient ( ERunOptions ClientRunFlags , string ClientApp , string ClientCmdLine , ProjectParams Params )
{
2014-10-17 04:21:41 -04:00
// look for browser
var ConfigCache = new UnrealBuildTool . ConfigCacheIni ( UnrealTargetPlatform . HTML5 , "Engine" , Path . GetDirectoryName ( Params . RawProjectPath ) , CombinePaths ( CmdEnv . LocalRoot , "Engine" ) ) ;
2015-01-26 10:22:57 -05:00
bool ok = false ;
List < string > Devices ;
string browserPath = "" ;
2014-10-17 04:21:41 -04:00
string DeviceName = Params . Device . Split ( '@' ) [ 1 ] ;
DeviceName = DeviceName . Substring ( 0 , DeviceName . LastIndexOf ( " on " ) ) ;
2015-01-26 10:22:57 -05:00
if ( ConfigCache . GetArray ( "/Script/HTML5PlatformEditor.HTML5SDKSettings" , "DeviceMap" , out Devices ) )
{
foreach ( var Dev in Devices )
{
var Matched = Regex . Match ( Dev , "\\(DeviceName=\"(.*)\",DevicePath=\\(FilePath=\"(.*)\"\\)\\)" , RegexOptions . IgnoreCase ) ;
if ( Matched . Success & & Matched . Groups [ 1 ] . ToString ( ) = = DeviceName )
{
browserPath = Matched . Groups [ 2 ] . ToString ( ) ;
ok = true ;
break ;
}
}
}
if ( ! ok & & HTML5SDKInfo . bAllowFallbackSDKSettings )
{
string DeviceSection ;
if ( Utils . IsRunningOnMono )
{
DeviceSection = "HTML5DevicesMac" ;
}
else
{
DeviceSection = "HTML5DevicesWindows" ;
}
ok = ConfigCache . GetString ( DeviceSection , DeviceName , out browserPath ) ;
}
2014-09-15 10:56:03 -04:00
2014-09-02 14:36:52 -04:00
if ( ! ok )
2015-01-26 10:22:57 -05:00
{
throw new System . Exception ( "Incorrect browser configuration in HTML5Engine.ini " ) ;
}
2014-03-14 14:13:41 -04:00
2014-07-21 17:06:23 -04:00
// open the webpage
2015-02-20 04:41:01 -05:00
Int32 ServerPort = 8000 ;
ConfigCache . GetInt32 ( "/Script/HTML5PlatformEditor.HTML5TargetSettings" , "DeployServerPort" , out ServerPort ) ;
string WorkingDirectory = Path . GetDirectoryName ( ClientApp ) ;
2014-10-17 04:21:41 -04:00
string url = Path . GetFileName ( ClientApp ) + ".html" ;
2015-02-20 04:41:01 -05:00
string args = "-m " ;
2014-09-15 10:56:03 -04:00
// Are we running via cook on the fly server?
// find our http url - This is awkward because RunClient doesn't have real information that NFS is running or not.
2014-08-18 13:29:39 -04:00
bool IsCookOnTheFly = false ;
2014-09-24 14:50:15 -04:00
2014-10-17 04:21:41 -04:00
// 9/24/2014 @fixme - All this is convoluted, clean up.
// looks like cookonthefly commandline stopped adding protocol or the port :/ hard coding to DEFAULT_TCP_FILE_SERVING_PORT+1 (DEFAULT_HTTP_FILE_SERVING_PORT)
// This will fail if the NFS server is started with a different port - we need to modify driver .cs script to pass in IP/Port data correctly.
2014-09-24 14:50:15 -04:00
2014-10-17 04:21:41 -04:00
if ( ClientCmdLine . Contains ( "filehostip" ) )
{
IsCookOnTheFly = true ;
url = "http://127.0.0.1:41898/" + url ;
}
2014-07-21 17:06:23 -04:00
2014-10-17 04:21:41 -04:00
if ( IsCookOnTheFly )
{
url + = "?cookonthefly=true" ;
}
else
{
2015-02-20 04:41:01 -05:00
url = String . Format ( "http://127.0.0.1:{0}/{1}" , ServerPort , url ) ;
args + = String . Format ( "-h -s {0} " , ServerPort ) ;
2014-10-17 04:21:41 -04:00
}
2014-09-02 14:36:52 -04:00
2015-02-20 04:41:01 -05:00
// Check HTML5LaunchHelper source for command line args
var LowerBrowserPath = browserPath . ToLower ( ) ;
args + = String . Format ( "-b \"{0}\" -p \"{1}\" -w \"{2}\" " , browserPath , HTML5SDKInfo . PythonPath ( ) , WorkingDirectory ) ;
args + = url + " " ;
var ProfileDirectory = Path . Combine ( Utils . GetUserSettingDirectory ( ) , "UE4_HTML5" , "user" ) ;
if ( LowerBrowserPath . Contains ( "chrome" ) )
{
args + = String . Format ( "--user-data-dir=\"{0}\" --enable-logging --no-first-run" , Path . Combine ( ProfileDirectory , "chrome" ) ) ;
}
else if ( LowerBrowserPath . Contains ( "firefox" ) )
{
2015-03-10 10:17:11 -04:00
args + = String . Format ( "-no-remote -profile \"{0}\"" , Path . Combine ( ProfileDirectory , "firefox" ) ) ;
2015-02-20 04:41:01 -05:00
}
//else if (browserPath.Contains("Safari")) {}
var LaunchHelperPath = CombinePaths ( CmdEnv . LocalRoot , "Engine/Binaries/DotNET/HTML5LaunchHelper.exe" ) ;
ProcessResult BrowserProcess = Run ( LaunchHelperPath , args , null , ClientRunFlags | ERunOptions . NoWaitForExit ) ;
2014-09-15 10:56:03 -04:00
2014-10-17 04:21:41 -04:00
return BrowserProcess ;
2014-09-02 14:36:52 -04:00
2014-03-14 14:13:41 -04:00
}
public override string GetCookPlatform ( bool bDedicatedServer , bool bIsClientOnly , string CookFlavor )
{
return "HTML5" ;
}
2015-04-08 14:53:36 -04:00
public override string GetCookExtraCommandLine ( ProjectParams Params )
{
2015-04-09 14:18:38 -04:00
return HTMLPakAutomation . CanCreateMapPaks ( Params ) ? " -GenerateDependenciesForMaps " : "" ;
2015-04-08 14:53:36 -04:00
}
public override List < string > GetCookExtraMaps ( )
{
var Maps = new List < string > ( ) ;
2015-04-16 12:11:10 -04:00
Maps . Add ( "/Engine/Maps/Entry" ) ;
2015-04-08 14:53:36 -04:00
return Maps ;
}
2014-03-14 14:13:41 -04:00
public override bool DeployPakInternalLowerCaseFilenames ( )
{
return false ;
}
2014-09-23 20:31:24 -04:00
public override PakType RequiresPak ( ProjectParams Params )
{
2015-04-09 14:18:38 -04:00
return HTMLPakAutomation . CanCreateMapPaks ( Params ) ? PakType . Never : PakType . Always ;
2014-09-23 20:31:24 -04:00
}
2015-02-03 05:40:53 -05:00
public override string GetPlatformPakCommandLine ( )
{
return " -compress" ;
}
2014-03-14 14:13:41 -04:00
public override bool DeployLowerCaseFilenames ( bool bUFSFile )
{
return false ;
}
public override string LocalPathToTargetPath ( string LocalPath , string LocalRoot )
{
return LocalPath ; //.Replace("\\", "/").Replace(LocalRoot, "../../..");
}
public override bool IsSupported { get { return true ; } }
2014-08-18 13:29:39 -04:00
public override List < string > GetDebugFileExtentions ( )
{
return new List < string > { ".pdb" } ;
}
2014-03-14 14:13:41 -04:00
#region Hooks
public override void PreBuildAgenda ( UE4Build Build , UE4Build . BuildAgenda Agenda )
{
}
public override List < string > GetExecutableNames ( DeploymentContext SC , bool bIsRun = false )
{
var ExecutableNames = new List < String > ( ) ;
ExecutableNames . Add ( Path . Combine ( SC . ProjectRoot , "Binaries" , "HTML5" , SC . ShortProjectName ) ) ;
return ExecutableNames ;
}
#endregion
}