using System;
using System.Collections.Generic;
using UnityEditor;
using Ubisoft.Hotel.Package.Editor;
namespace Ubisoft.Hotel.PackageManager.Editor
{
internal class BuildStep_ApplyBuildSuite : BuildStep
{
internal const string StepName = "BuildStep_ApplyBuildSuite";
private enum EStep
{
None,
PreBuilding,
Done
};
private EPlatform Platform { get; set; }
private string[] Arguments { get; set; }
private bool IsManualBuild { get; set; }
private bool IsFullBuild { get; set; }
private bool IsOptimisedMode { get; set; }
///
/// Pararameter responsible for modifying game version
///
private BuildArguments.EVersion Version { get; set; }
private EStep m_step;
internal BuildStep_ApplyBuildSuite(EPlatform platform, string[] arguments, bool isManualBuild,
bool isFullBuild, bool isOptimisedMode) : base(StepName)
{
Platform = platform;
Arguments = arguments;
IsManualBuild = isManualBuild;
IsFullBuild = isFullBuild;
IsOptimisedMode = isOptimisedMode;
Step = EStep.None;
}
private void ResetParams()
{
Version = BuildArguments.EVersion.None;
}
private void PreBuild(EPlatform platform)
{
void onAppSpaceDone(Manifest manifest, HashSet symbols)
{
void onRegisteredPackages(UnityEditor.PackageManager.PackageRegistrationEventArgs args)
{
UnityEditor.PackageManager.Events.registeredPackages -= onRegisteredPackages;
Step = EStep.Done;
}
// We consider that the manifest has changed if it's the first time to make sure that packages properties
// are applied
bool manifestHasChanged = manifest.NeedsToSave || !PackageManager.HasCrcBeenCalculatedBefore();
// When optimised mode is not enabled we need to fully apply the suite if it's not a full build
if (!IsOptimisedMode && !manifestHasChanged)
{
manifestHasChanged = !IsFullBuild;
}
PackageManager.BuildBatch_ManifestHasChanged = manifestHasChanged;
AppSpaceBuildSuite.UnityBuildProperty.AddDefineSymbols(symbols);
// We need to refresh the object to make sure that these symbols will be stored
PackageManager.RefreshObject();
if (manifest.NeedsToSave)
{
PackageManager.BuildBatch_AddTimeDetail("Save manifest");
// Save manifest
UnityEditor.PackageManager.Events.registeredPackages += onRegisteredPackages;
manifest.Save();
// Packages in App space need to be pruned because manifest.json has changed which means
// that some of the packages's stuff in App space is not required anymore
PackageManagerHelper.PrunePackages();
// Make sure that latest crc is stored so the same properties won't be applied again next time PackageManager is loaded
_ = PackageManager.CalculateCrc();
// In Unity 2020 we need to force PackageManager to resolve, otherwise packages wouldn't get updated without leaving and returning to the Editor
UnityEditor.PackageManager.Client.Resolve();
}
else
{
if (!PackageManager.HasCrcBeenCalculatedBefore())
{
// Save it just to prevent PackageManager from being recreated the very first time after PackageManager is created
_ = PackageManager.CalculateCrc();
}
Step = EStep.Done;
}
}
//
// App space properties
//
if (AppSpaceBuildSuiteProvider.CanPerform())
{
Step = EStep.PreBuilding;
// Reset the editor so that the new build suites are shown properly
PackageManagerEditor.Clear();
// Update BuildSuite from AppSpace if it hasn't been updated yet
if (AppSpaceBuildSuiteProvider.IsPackageSuiteAppliedForBuildEmpty())
{
AppSpaceBuildSuiteProvider.ApplyPackageSuiteForBuild(platform, AppSpaceBuildSuite);
}
// Apply App space UpmBuildProperty to update manifest.json
Dictionary packagesHandledByConsumer = AppSpaceBuildSuiteProvider.GetPackagesHandledByConsumer();
AppSpaceBuildSuite.UpmBuildProperty.PreBuild(packagesHandledByConsumer, onAppSpaceDone);
}
else
{
Step = EStep.Done;
}
}
private string GetAndroidNdkEnvVariableName()
{
#if UNITY2019_4_OR_NEWER
return "ANDROID_NDK_R19";
#else
return "ANDROID_NDK_R16";
#endif
}
private string GetAndroidSdkEnvVariableName()
{
return $"ANDROID_SDK_ROOT";
}
private void SetEditorPrefsString(string key, string value)
{
if (!string.IsNullOrEmpty(value))
{
string currentValue = EditorPrefs.GetString(key);
if (currentValue != value)
{
PackageManager.Log($"Updating EditorPrefs {key} path to {value}");
EditorPrefs.SetString(key, value);
}
}
}
protected override void ExtendedPerform()
{
ResetParams();
string argumentsAsString = (Arguments == null) ? null : string.Join(", ", Arguments);
PackageManager.Log($"BuildPlayer arguments: {Debug.FormatTextInUserContext(argumentsAsString)}");
BuildSettings buildSettings = AppSpaceBuildSuiteProvider.BuildSettings;
BuildArguments buildArguments = new BuildArguments(Version, Platform);
BuildArgumentsProcessor.ProcessArguments(Arguments, buildSettings, buildArguments);
Dictionary argumentPairs = buildArguments.Pairs;
Version = buildArguments.Version;
Platform = buildArguments.Platform;
// Apply android properties by getting information from environment variables to set up Unity preferences for the CICD agent.
// They are ignored if they are not set, typically on developer's workstations.
if (Platform == EPlatform.Android)
{
// Android SDK
string envVariableValue = Environment.GetEnvironmentVariable(GetAndroidSdkEnvVariableName());
SetEditorPrefsString("AndroidSdkRoot", envVariableValue);
// Android NDK
envVariableValue = Environment.GetEnvironmentVariable(GetAndroidNdkEnvVariableName());
SetEditorPrefsString("AndroidNdkRoot", envVariableValue);
}
// Bump version
if (Version == BuildArguments.EVersion.BumpPatch)
{
AppSpaceBuildSuiteProvider.BumpVersion();
}
bool useCustomPath = IsFullBuild && AppSpaceBuildSuiteProvider.BuildSettings.AskForLocation;
AppSpaceBuildSuiteProvider.BuildPlayer(AppSpaceBuildSuite, Platform, argumentPairs, IsManualBuild, IsFullBuild, !useCustomPath, BuildSettings);
// Lightweight build mode
EditorUserBuildSettings.exportAsGoogleAndroidProject = buildSettings.ExportProject;
EditorUserBuildSettings.SetPlatformSettings("Standalone", "CreateSolution", buildSettings.ExportProject.ToString());
PreBuild(Platform);
}
private EStep Step
{
get { return m_step; }
set
{
m_step = value;
switch (value)
{
case EStep.Done:
OnDone();
break;
}
}
}
}
}