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