using System.Collections.Generic; using UnityEditor; using UnityEditor.Build; using Ubisoft.Hotel.Package.Editor; namespace Ubisoft.Hotel.PackageManager.Editor { [InitializeOnLoad] public class PackageManagerMain : IActiveBuildTargetChanged { private static PackageManagerMain s_instance; public static PackageManagerMain Instance { get { if (s_instance == null) { s_instance = new PackageManagerMain(); } return s_instance; } } static PackageManagerMain() { EditorApplication.update += Instance.Update; } /// /// Bump version and tags it /// public static void ReleaseVersion() { Instance.Release_Perform(); } /// /// Apply a build suite settings. This is typically a step of the whole build full player process. /// public static void BuildApplyBuildSuite() { Instance.Build_PerformBatchMode(PackageManager.EBuildBatchMode.ApplyBuildSuite); } /// /// Build addressables. This is typically a step of the whole build full player process. /// public static void BuildAddressables() { Instance.Build_PerformBatchMode(PackageManager.EBuildBatchMode.BuildAddressables); } /// /// Build the player. This is typically a step of the whole build full player process. /// public static void BuildPlayer() { Instance.Build_PerformBatchMode(PackageManager.EBuildBatchMode.BuildPlayer); } /// /// Run all steps involved in building the player. /// public static void BuildFullPlayer() { Instance.Build_PerformBatchMode(PackageManager.EBuildBatchMode.Full); } private static readonly char RELEASE_ARG_SEPARATOR_CHAR = '='; private static readonly string RELEASE_ARG_SEPARATOR = RELEASE_ARG_SEPARATOR_CHAR.ToString(); private static readonly string RELEASE_ARG_SKIP_BUMP_VERSION = "skip_bump_version"; private static readonly string RELEASE_ARG_SKIP_TAG = "skip_tag"; private static readonly string RELEASE_ARG_TAG_NAME = "tag_name"; private PackageManager m_packageManager; public PackageManager PackageManager { get { if (m_packageManager == null) { LoadPackageManager(); } return m_packageManager; } } private bool NeedsToInit { get; set; } = true; public void Init(bool force = false) { if (NeedsToInit || force) { NeedsToInit = false; LoadPackageManager(); } } private void Update() { // We need to wait for Unity to be done with compiling to make sure that the code we're executing is up-to-date, // for example, when regenerating package suites based on consumer's code upon launching Unity Editor after // updating code // This stuff is required to be executed only in Editor time if (!EditorApplication.isCompiling && !EditorApplication.isPlayingOrWillChangePlaymode) { if (NeedsToInit) { Init(); } HtAssetDatabase.Update(); if (PackageManager != null) { // We need to wait for Unity to compile before generating package suites since we might have just copied into the app space the code that // creates the package suites by default from the packages space if (PackageManager.NeedsToReloadPackageManager) { PackageManager.NeedsToReloadPackageManager = false; LoadPackageManager(true); } else { PackageManager.Update(); } } } } private void LoadPackageManager(bool forceGenerate = false) { m_packageManager = PackageManager.LoadPackageManager(forceGenerate); } private void Release_Perform() { // Read arguments from command line string[] tokens; string[] arguments = System.Environment.GetCommandLineArgs(); Dictionary argumentsDict = new Dictionary(); if (arguments != null) { for (int i = arguments.Length - 1; i > -1; --i) { if (arguments[i].Contains(RELEASE_ARG_SEPARATOR)) { tokens = arguments[i].Split(RELEASE_ARG_SEPARATOR_CHAR); argumentsDict.Add(tokens[0], tokens[1]); } else { argumentsDict.Add(arguments[i], arguments[i]); } } } // By default we assume the user wants to bump version and create a tag bool bumpVersion = !argumentsDict.ContainsKey(RELEASE_ARG_SKIP_BUMP_VERSION); bool createTag = !argumentsDict.ContainsKey(RELEASE_ARG_SKIP_TAG); string tagName = createTag && argumentsDict.ContainsKey(RELEASE_ARG_TAG_NAME) ? argumentsDict[RELEASE_ARG_TAG_NAME] : null; PackageManager.Release_Perform(bumpVersion, createTag, tagName); } private void Build_PerformBatchMode(PackageManager.EBuildBatchMode mode) { // Make sure hotelSettings is generated before applying package suite so settings from a previous build job // are not applied to this job LoadPackageManager(mode == PackageManager.EBuildBatchMode.ApplyBuildSuite || mode == PackageManager.EBuildBatchMode.Full); // Use active platform, calculated out of current Unity BuildTarget if no argument overrides it EPlatform platform = PlatformUtils.GetActivePlatform(); string[] arguments = System.Environment.GetCommandLineArgs(); if (arguments != null) { BuildArguments buildArguments = new BuildArguments(BuildArguments.EVersion.None, platform); BuildArgumentsProcessor.ProcessArguments(arguments, null, buildArguments); platform = buildArguments.Platform; } PackageManager.Log($"Build_PerformBatchMode {mode} buildTarget: {platform} arguments: {string.Join(", ", arguments)}"); if (PackageManager == null) { PackageManager.LogError($"{Debug.FormatTextInCodeContext("PackageManager")} needs to be loaded before building"); } else { switch (mode) { case PackageManager.EBuildBatchMode.BuildAddressables: // Make sure BuildAddressables is enabled in Hotel build setttings PackageManager.AppSpaceBuildSuiteProvider.BuildSettings.BuildAddressables = true; break; } PackageManager.Build_PerformBatchMode(mode, platform, arguments, false, false); } } public int callbackOrder { get { return 0; } } public void OnActiveBuildTargetChanged(BuildTarget previousTarget, BuildTarget newTarget) { // We need to regenerate suites and apply the current one to take into consideration any changes due to the new build target PackageManager.NeedsToReloadPackageManager = true; } } }