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; } } } } }