You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#lockdown Nick.Penwarden ========================== MAJOR FEATURES + CHANGES ========================== Change 2716841 on 2015/10/05 by Mike.Beach (WIP) Cleaning up how we setup script assets for replacement on cook (aligning more with the Blueprint conversion tool). #codereview Maciej.Mroz Change 2719089 on 2015/10/07 by Maciej.Mroz ToValidCPPIdentifierChars handles propertly '?' char. #codereview Dan.Oconnor Change 2719361 on 2015/10/07 by Maciej.Mroz Generated native code for AnimBPGC - some preliminary changes. Refactor: UAnimBlueprintGeneratedClass is not accessed directly in runtime. It is accessed via UAnimClassInterface interface. Properties USkeletalMeshComponent::AnimBlueprintGeneratedClass and UInterpTrackFloatAnimBPParam::AnimBlueprintClass were changed into "TSubclassOf<UAnimInstance> AnimClass" The UDynamicClass also can deliver the IAnimClassInterface interface. See UAnimClassData, IAnimClassInterface::GetFromClass and UDynamicClass::AnimClassImplementation. #codereview Lina.Halper, Thomas.Sarkanen Change 2719383 on 2015/10/07 by Maciej.Mroz Debug-only code removed Change 2720528 on 2015/10/07 by Dan.Oconnor Fix for determinsitc cooking of async tasks and load asset nodes #codereview Mike.Beach, Maciej.Mroz Change 2721273 on 2015/10/08 by Maciej.Mroz Blueprint Compiler Cpp Backend - Anim Blueprints can be converted - Various fixes/improvements Change 2721310 on 2015/10/08 by Maciej.Mroz refactor (cl#2719361) - no "auto" keyword Change 2721727 on 2015/10/08 by Mike.Beach (WIP) Setup the cook commandlet so it handles converted assets, replacing them with generated classes. - Refactored the conversion manifest (using a map over an array) - Centralized destination paths into a helper struct (for the manifest) - Generating an Editor module that automatically hooks into the cook process when enabled - Loading and applying native replacments for the cook Change 2723276 on 2015/10/09 by Michael.Schoell Blueprints duplicated for PIE will no longer register as dependencies to other Blueprint. #jira UE-16695 - Editor freezes then crashes while attempting to save during PIE #jira UE-21614 - [CrashReport] Crash while saving during PIE - FKismetEditorUtilities::CompileBlueprint() kismet2.cpp:736 Change 2724345 on 2015/10/11 by Ben.Cosh Blueprint profiler at first pass, this includes the ability to instrument specific blueprints with realtime editor stat display. #UEBP-21 - Profiling data capture and storage #UEBP-13 - Performance capture landing page #Branch UE4 #Proj BlueprintProfiler, BlueprintGraph, EditorStyle, Kismet, UnrealEd, CoreUObject, Engine Change 2724613 on 2015/10/12 by Ben.Cosh Incremental update for blueprint profiler to fix the way some of the reported stats cascade through events and branches and additionally some missed bits of code are refactored/removed. #Branch UE4 #Proj BlueprintProfiler #info Whilst looking into this I spotted the reason why the stats seem so erratic, There appears to be an issue with FText's use of EXPERIMENTAL_TEXT_FAST_DECIMAL_FORMAT which I have reported, but ideally disable this locally until a fix is integrated. Change 2724723 on 2015/10/12 by Maciej.Mroz Constructor of a dynamic class creates CDO. #codereview Robert.Manuszewski Change 2725108 on 2015/10/12 by Mike.Beach [UE-21891] Minor fix to the array shuffle() function; now processes the last entry like all the others. Change 2726358 on 2015/10/13 by Maciej.Mroz UDataTable is properly saved even if its RowStruct is null. https://udn.unrealengine.com/questions/264064/crash-using-hotreload-in-custom-datatable-cdo-clas.html Change 2727395 on 2015/10/13 by Mike.Beach (WIP) Second pass on the Blueprint conversion pipeline; setting it up for more optimal (speedier) performance. * Using stubs for replacements (rather than loading dynamic replacement). * Giving the cook commandlet more control (so a conversion could be ran directly). * Now logging replacements by old object path (to account for UPackage replacement queries). * Fix for [UE-21947], unshelved from CL 2724944 (by Maciej.Mroz). #codereview Maciej.Mroz Change 2727484 on 2015/10/13 by Mike.Beach [UE-22008] Fixing up comment/tooltip typo for UActorComponent::bAutoActivate. Change 2727527 on 2015/10/13 by Mike.Beach Downgrading an inactionable EdGraph warning, while adding more info so we could possibly determine what's happening. Change 2727702 on 2015/10/13 by Dan.Oconnor Fix for crash in UDelegateProperty::GetCPPType when called on a function with no OwnerClass (events) Change 2727968 on 2015/10/14 by Maciej.Mroz Since ConstructorHelpers::FClassFinder is usually static, the loaded class should be in root set, to prevent the pointer stored in ConstructorHelpers::FClassFinder from being obsolete. FindOrLoadClass behaves now like FindOrLoadObject. #codereview Robert.Manuszewski, Nick.Whiting Change 2728139 on 2015/10/14 by Phillip.Kavan
342 lines
10 KiB
C#
342 lines
10 KiB
C#
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Threading;
|
|
using System.Reflection;
|
|
using AutomationTool;
|
|
using UnrealBuildTool;
|
|
|
|
[Help(@"Builds/Cooks/Runs a project.
|
|
|
|
For non-uprojects project targets are discovered by compiling target rule files found in the project folder.
|
|
If -map is not specified, the command looks for DefaultMap entry in the project's DefaultEngine.ini and if not found, in BaseEngine.ini.
|
|
If no DefaultMap can be found, the command falls back to /Engine/Maps/Entry.")]
|
|
[Help("project=Path", @"Project path (required), i.e: -project=QAGame, -project=Samples\BlackJack\BlackJack.uproject, -project=D:\Projects\MyProject.uproject")]
|
|
[Help("destsample", "Destination Sample name")]
|
|
[Help("foreigndest", "Foreign Destination")]
|
|
[Help(typeof(ProjectParams))]
|
|
[Help(typeof(UE4Build))]
|
|
[Help(typeof(CodeSign))]
|
|
public class BuildCookRun : BuildCommand
|
|
{
|
|
#region BaseCommand interface
|
|
|
|
public override void ExecuteBuild()
|
|
{
|
|
// allow BCR functions to call UBT functions (especially .ini parsing)
|
|
UnrealBuildTool.UnrealBuildTool.SetupUBTFromUAT();
|
|
|
|
// these need to be done first
|
|
var bForeign = ParseParam("foreign");
|
|
var bForeignCode = ParseParam("foreigncode");
|
|
if (bForeign)
|
|
{
|
|
MakeForeignSample();
|
|
}
|
|
else if (bForeignCode)
|
|
{
|
|
MakeForeignCodeSample();
|
|
}
|
|
var Params = SetupParams();
|
|
|
|
DoBuildCookRun(Params);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Setup
|
|
|
|
protected ProjectParams SetupParams()
|
|
{
|
|
Log("Setting up ProjectParams for {0}", ProjectPath);
|
|
|
|
var Params = new ProjectParams
|
|
(
|
|
Command: this,
|
|
// Shared
|
|
RawProjectPath: ProjectPath
|
|
);
|
|
|
|
var DirectoriesToCook = ParseParamValue("cookdir");
|
|
if (!String.IsNullOrEmpty(DirectoriesToCook))
|
|
{
|
|
Params.DirectoriesToCook = new ParamList<string>(DirectoriesToCook.Split('+'));
|
|
}
|
|
|
|
var InternationalizationPreset = ParseParamValue("i18npreset");
|
|
if (!String.IsNullOrEmpty(InternationalizationPreset))
|
|
{
|
|
Params.InternationalizationPreset = InternationalizationPreset;
|
|
}
|
|
|
|
var CulturesToCook = ParseParamValue("cookcultures");
|
|
if (!String.IsNullOrEmpty(CulturesToCook))
|
|
{
|
|
Params.CulturesToCook = new ParamList<string>(CulturesToCook.Split('+'));
|
|
}
|
|
|
|
if (Params.DedicatedServer)
|
|
{
|
|
foreach (var ServerPlatformInstance in Params.ServerTargetPlatformInstances)
|
|
{
|
|
ServerPlatformInstance.PlatformSetupParams(ref Params);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
foreach (var ClientPlatformInstance in Params.ClientTargetPlatformInstances)
|
|
{
|
|
ClientPlatformInstance.PlatformSetupParams(ref Params);
|
|
}
|
|
}
|
|
|
|
Params.ValidateAndLog();
|
|
return Params;
|
|
}
|
|
|
|
/// <summary>
|
|
/// In case the command line specified multiple map names with a '+', selects the first map from the list.
|
|
/// </summary>
|
|
/// <param name="Maps">Map(s) specified in the commandline.</param>
|
|
/// <returns>First map or an empty string.</returns>
|
|
private static string GetFirstMap(string Maps)
|
|
{
|
|
string Map = String.Empty;
|
|
if (!String.IsNullOrEmpty(Maps))
|
|
{
|
|
var AllMaps = Maps.Split(new char[] { '+' }, StringSplitOptions.RemoveEmptyEntries);
|
|
if (!IsNullOrEmpty(AllMaps))
|
|
{
|
|
Map = AllMaps[0];
|
|
}
|
|
}
|
|
return Map;
|
|
}
|
|
|
|
private string GetTargetName(Type TargetRulesType)
|
|
{
|
|
const string TargetPostfix = "Target";
|
|
var Name = TargetRulesType.Name;
|
|
if (Name.EndsWith(TargetPostfix, StringComparison.InvariantCultureIgnoreCase))
|
|
{
|
|
Name = Name.Substring(0, Name.Length - TargetPostfix.Length);
|
|
}
|
|
return Name;
|
|
}
|
|
|
|
private string GetDefaultMap(ProjectParams Params)
|
|
{
|
|
const string EngineEntryMap = "/Engine/Maps/Entry";
|
|
Log("Trying to find DefaultMap in ini files");
|
|
string DefaultMap = null;
|
|
var ProjectFolder = GetDirectoryName(Params.RawProjectPath.FullName);
|
|
var DefaultGameEngineConfig = CombinePaths(ProjectFolder, "Config", "DefaultEngine.ini");
|
|
if (FileExists(DefaultGameEngineConfig))
|
|
{
|
|
Log("Looking for DefaultMap in {0}", DefaultGameEngineConfig);
|
|
DefaultMap = GetDefaultMapFromIni(DefaultGameEngineConfig, Params.DedicatedServer);
|
|
if (DefaultMap == null && Params.DedicatedServer)
|
|
{
|
|
DefaultMap = GetDefaultMapFromIni(DefaultGameEngineConfig, false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var BaseEngineConfig = CombinePaths(CmdEnv.LocalRoot, "Config", "BaseEngine.ini");
|
|
if (FileExists(BaseEngineConfig))
|
|
{
|
|
Log("Looking for DefaultMap in {0}", BaseEngineConfig);
|
|
DefaultMap = GetDefaultMapFromIni(BaseEngineConfig, Params.DedicatedServer);
|
|
if (DefaultMap == null && Params.DedicatedServer)
|
|
{
|
|
DefaultMap = GetDefaultMapFromIni(BaseEngineConfig, false);
|
|
}
|
|
}
|
|
}
|
|
// We check for null here becase null == not found
|
|
if (DefaultMap == null)
|
|
{
|
|
Log("No DefaultMap found, assuming: {0}", EngineEntryMap);
|
|
DefaultMap = EngineEntryMap;
|
|
}
|
|
else
|
|
{
|
|
Log("Found DefaultMap={0}", DefaultMap);
|
|
}
|
|
return DefaultMap;
|
|
}
|
|
|
|
private string GetDefaultMapFromIni(string IniFilename, bool DedicatedServer)
|
|
{
|
|
var IniLines = ReadAllLines(IniFilename);
|
|
string DefaultMap = null;
|
|
|
|
string ConfigKeyStr = "GameDefaultMap";
|
|
if (DedicatedServer)
|
|
{
|
|
ConfigKeyStr = "ServerDefaultMap";
|
|
}
|
|
|
|
foreach (var Line in IniLines)
|
|
{
|
|
if (Line.StartsWith(ConfigKeyStr, StringComparison.InvariantCultureIgnoreCase))
|
|
{
|
|
var DefaultMapPair = Line.Split('=');
|
|
DefaultMap = DefaultMapPair[1].Trim();
|
|
}
|
|
if (DefaultMap != null)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
return DefaultMap;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region BuildCookRun
|
|
|
|
protected void DoBuildCookRun(ProjectParams Params)
|
|
{
|
|
const ProjectBuildTargets ClientTargets = ProjectBuildTargets.ClientCooked | ProjectBuildTargets.ServerCooked;
|
|
bool bGenerateNativeScripts = Params.RunAssetNativization;
|
|
int WorkingCL = -1;
|
|
if (P4Enabled && AllowSubmit)
|
|
{
|
|
WorkingCL = P4.CreateChange(P4Env.Client, String.Format("{0} build from changelist {1}", Params.ShortProjectName, P4Env.Changelist));
|
|
}
|
|
|
|
Project.Build(this, Params, WorkingCL, bGenerateNativeScripts ? (ProjectBuildTargets.All & ~ClientTargets) : ProjectBuildTargets.All);
|
|
Project.Cook(Params);
|
|
if (bGenerateNativeScripts)
|
|
{
|
|
Project.Build(this, Params, WorkingCL, ClientTargets);
|
|
}
|
|
Project.CopyBuildToStagingDirectory(Params);
|
|
Project.Package(Params, WorkingCL);
|
|
Project.Archive(Params);
|
|
Project.Deploy(Params);
|
|
PrintRunTime();
|
|
Project.Run(Params);
|
|
|
|
// Check everything in!
|
|
if (WorkingCL != -1)
|
|
{
|
|
int SubmittedCL;
|
|
P4.Submit(WorkingCL, out SubmittedCL, true, true);
|
|
}
|
|
}
|
|
|
|
private void MakeForeignSample()
|
|
{
|
|
string Sample = "BlankProject";
|
|
var DestSample = ParseParamValue("DestSample", "CopiedBlankProject");
|
|
var Src = CombinePaths(CmdEnv.LocalRoot, "Samples", "SampleGames", Sample);
|
|
if (!DirectoryExists(Src))
|
|
{
|
|
throw new AutomationException("Can't find source directory to make foreign sample {0}.", Src);
|
|
}
|
|
|
|
var Dest = ParseParamValue("ForeignDest", CombinePaths(@"C:\testue4\foreign\", DestSample + "_ _Dir"));
|
|
Log("Make a foreign sample {0} -> {1}", Src, Dest);
|
|
|
|
CloneDirectory(Src, Dest);
|
|
|
|
DeleteDirectory_NoExceptions(CombinePaths(Dest, "Intermediate"));
|
|
DeleteDirectory_NoExceptions(CombinePaths(Dest, "Saved"));
|
|
|
|
RenameFile(CombinePaths(Dest, Sample + ".uproject"), CombinePaths(Dest, DestSample + ".uproject"));
|
|
|
|
var IniFile = CombinePaths(Dest, "Config", "DefaultEngine.ini");
|
|
var Ini = new VersionFileUpdater(IniFile);
|
|
Ini.ReplaceLine("GameName=", DestSample);
|
|
Ini.Commit();
|
|
}
|
|
|
|
private void MakeForeignCodeSample()
|
|
{
|
|
string Sample = "PlatformerGame";
|
|
string DestSample = "PlatformerGame";
|
|
var Src = CombinePaths(CmdEnv.LocalRoot, Sample);
|
|
if (!DirectoryExists(Src))
|
|
{
|
|
throw new AutomationException("Can't find source directory to make foreign sample {0}.", Src);
|
|
}
|
|
|
|
var Dest = ParseParamValue("ForeignDest", CombinePaths(@"C:\testue4\foreign\", DestSample + "_ _Dir"));
|
|
Log("Make a foreign sample {0} -> {1}", Src, Dest);
|
|
|
|
CloneDirectory(Src, Dest);
|
|
DeleteDirectory_NoExceptions(CombinePaths(Dest, "Intermediate"));
|
|
DeleteDirectory_NoExceptions(CombinePaths(Dest, "Saved"));
|
|
DeleteDirectory_NoExceptions(CombinePaths(Dest, "Plugins", "FootIK", "Intermediate"));
|
|
|
|
//RenameFile(CombinePaths(Dest, Sample + ".uproject"), CombinePaths(Dest, DestSample + ".uproject"));
|
|
|
|
var IniFile = CombinePaths(Dest, "Config", "DefaultEngine.ini");
|
|
var Ini = new VersionFileUpdater(IniFile);
|
|
Ini.ReplaceLine("GameName=", DestSample);
|
|
Ini.Commit();
|
|
}
|
|
|
|
private FileReference ProjectFullPath;
|
|
public virtual FileReference ProjectPath
|
|
{
|
|
get
|
|
{
|
|
if (ProjectFullPath == null)
|
|
{
|
|
var bForeign = ParseParam("foreign");
|
|
var bForeignCode = ParseParam("foreigncode");
|
|
if (bForeign)
|
|
{
|
|
var DestSample = ParseParamValue("DestSample", "CopiedHoverShip");
|
|
var Dest = ParseParamValue("ForeignDest", CombinePaths(@"C:\testue4\foreign\", DestSample + "_ _Dir"));
|
|
ProjectFullPath = new FileReference(CombinePaths(Dest, DestSample + ".uproject"));
|
|
}
|
|
else if (bForeignCode)
|
|
{
|
|
var DestSample = ParseParamValue("DestSample", "PlatformerGame");
|
|
var Dest = ParseParamValue("ForeignDest", CombinePaths(@"C:\testue4\foreign\", DestSample + "_ _Dir"));
|
|
ProjectFullPath = new FileReference(CombinePaths(Dest, DestSample + ".uproject"));
|
|
}
|
|
else
|
|
{
|
|
var OriginalProjectName = ParseParamValue("project", "");
|
|
var ProjectName = OriginalProjectName;
|
|
ProjectName = ProjectName.Trim(new char[] { '\"' });
|
|
if (ProjectName.IndexOfAny(new char[] { '\\', '/' }) < 0)
|
|
{
|
|
ProjectName = CombinePaths(CmdEnv.LocalRoot, ProjectName, ProjectName + ".uproject");
|
|
}
|
|
else if (!FileExists_NoExceptions(ProjectName))
|
|
{
|
|
ProjectName = CombinePaths(CmdEnv.LocalRoot, ProjectName);
|
|
}
|
|
if(FileExists_NoExceptions(ProjectName))
|
|
{
|
|
ProjectFullPath = new FileReference(ProjectName);
|
|
}
|
|
else
|
|
{
|
|
var Branch = new BranchInfo(new List<UnrealTargetPlatform> { UnrealBuildTool.BuildHostPlatform.Current.Platform });
|
|
var GameProj = Branch.FindGame(OriginalProjectName);
|
|
if (GameProj != null)
|
|
{
|
|
ProjectFullPath = GameProj.FilePath;
|
|
}
|
|
if (!FileExists_NoExceptions(ProjectFullPath.FullName))
|
|
{
|
|
throw new AutomationException("Could not find a project file {0}.", ProjectName);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ProjectFullPath;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|