using System.Collections.Generic; using System.IO; using UnityEditor; using Ubisoft.Hotel.Package; using Ubisoft.Hotel.Package.Editor; namespace Ubisoft.Hotel.PackageManager.Editor { internal class BuildStep_PreparePlayer : BuildStep { internal const string StepName = "BuildStep_PreparePlayer"; private EPlatform Platform { get; set; } internal BuildStep_PreparePlayer(EPlatform platform) : base(StepName) { Platform = platform; } protected override void ExtendedPerform() { // If manifest.json has changed then we need to retrieve packages again, which might take long if (PackageManager.BuildBatch_ManifestHasChanged) { PackageManagerHelper.ProcessPackages(OnProcessPackages); } else { DoProcessPackages(null, false); } } private void OnProcessPackages(HashSet packageNames) { DoProcessPackages(packageNames, true); } private void DoProcessPackages(HashSet packageNames, bool manifestHasChanged) { if (manifestHasChanged) { GeneratePlayerResources(packageNames); PrunePlayerPlugins(packageNames); } else { // In optimised mode Package space's stuff stays the same so only App space's player properties need to be updated DeletePlayerPackageSuite(); GeneratePlayerPackageSuiteInResources(); } // // Package space properties // // Update BuildSuite from PackageSpace PackageSpaceBuildSuite.Clear(); PackageSpaceBuildSuiteProvider.ApplyToBuildSuite(Platform, PackageSpaceBuildSuite); // Add current platform to symbols HashSet symbols = PlatformUtils.GetPlatformSymbols(Platform); if (symbols != null && symbols.Count > 0) { UnityBuildProperty property = UnityBuildProperty.CreateInstanceWithParams("BuildTarget"); property.AddDefineSymbols(symbols); PackageSpaceBuildSuite.OrderProperty(property); } PackageSpaceBuildSuite.CompileBuildProperties(); // // Combined space properties // // Combine both CombinedSpaceBuildSuite.Clear(); if (AppSpaceBuildSuiteProvider.CanPerform()) { CombinedSpaceBuildSuite.OrderBuildSuite(AppSpaceBuildSuite); } CombinedSpaceBuildSuite.OrderBuildSuite(PackageSpaceBuildSuite); CombinedSpaceBuildSuite.CompileBuildProperties(); // We need to refresh the object after compiling build properties to make sure that they will be stored PackageManager.RefreshObject(); CombinedSpaceBuildSuite.PreBuild(Platform); // Make sure that latest crc is stored so the same properties won't be applied again next time PackageManager is loaded _ = PackageManager.CalculateCrc(); OnDone(); } #region player private static readonly string ASSETS_HOTEL_RESOURCES_ROOT_PATH = PackageManager.ASSETS_HOTEL_RESOURCES_ROOT_PATH; private static readonly string ASSETS_PLUGINS_ANDROID_PATH = "Assets/Plugins/Android/"; private void DeletePlayerResources() { // Delete the directory and its files HtAssetDatabase.DeleteFolder(ASSETS_HOTEL_RESOURCES_ROOT_PATH); } private PlayerPackageSuite CreatePlayerPackageSuite() { string name = PlayerPackageSuite.FILENAME; // Create the ScriptableObject that will contain all player properties PlayerPackageSuite returnValue = HtUnityEditorFactory.CreateScriptableObject(typeof(PlayerPackageSuite), ASSETS_HOTEL_RESOURCES_ROOT_PATH, name) as PlayerPackageSuite; returnValue.name = name; return returnValue; } private void DeletePlayerPackageSuite() { string unityPath = HtAssetDatabase.UnityPathCombine(ASSETS_HOTEL_RESOURCES_ROOT_PATH, $"{PlayerPackageSuite.FILENAME}.asset"); if (HtAssetDatabase.ExistsFile(unityPath)) { HtAssetDatabase.DeleteFile(unityPath, true); } } private void GeneratePlayerResources(HashSet packageNames) { DeletePlayerResources(); string path = ASSETS_HOTEL_RESOURCES_ROOT_PATH; HtAssetDatabase.CreateFolder(path); // Generate the player package suite that contains all player properties GeneratePlayerPackageSuiteInResources(); // Current suite's properties have the chance to copy stuff over Resources AppSpaceBuildSuiteProvider.GenerateResources(Platform); // Create symbolic links to stuff in Hotel/Assets/Resources so consumers can edit these properties if (packageNames != null) { string platformSrcPath; string platformDstPath; string platformDstRootPath = HtAssetDatabase.UnityPathToPlatformPath(ASSETS_HOTEL_RESOURCES_ROOT_PATH, true); platformDstRootPath += Path.DirectorySeparatorChar; string platformHotelResourcesPath = HtAssetDatabase.UnityPathToPlatformPath(AssetManager.HOTEL_ASSETS_RESOURCES_PATH, true); platformHotelResourcesPath += Path.DirectorySeparatorChar; int count = 0; foreach (var packageName in packageNames) { platformSrcPath = platformHotelResourcesPath + packageName; if (Directory.Exists(platformSrcPath)) { count++; platformDstPath = platformDstRootPath + packageName; HtSymlinkUtility.Symlink(platformSrcPath, platformDstPath, false); } } if (count > 0) { AssetDatabase.Refresh(); } } } private void GeneratePlayerPackageSuiteInResources() { List properties = AppSpaceBuildSuiteProvider.BuildPlayerPackageProperties(Platform); if (properties != null && properties.Count > 0) { PlayerPackageSuite packageSuite = CreatePlayerPackageSuite(); string path = AssetDatabase.GetAssetPath(packageSuite.GetInstanceID()); // Add player package properties to the suite foreach (PlayerPackageProperty p in properties) { if (p != null) { // Add packageSettings ScriptableObject to packageSuite ScriptableObject AssetDatabase.AddObjectToAsset(p, path); // Add the reference to packageSuite so it can be retrieved by packageSuite users packageSuite.AddProperty(p); } } // Make sure packageSuite is saved, otherwise its properties can get lost after exiting play mode AssetDatabase.SaveAssets(); HtAssetDatabase.RefreshObject(packageSuite); } } private void PrunePlayerPlugins(HashSet packageNames) { // Orion installs a package's plugins stuff upon package installation but it doesn't delete this stuff when // the package is uninstall, hence Hotel PackageManager deletes those orion directories in Plugins/Android // which corresponding package is not in manifest. if (packageNames != null) { // Get all directories in Plugins string[] directories = HtAssetDatabase.DirectoryGetDirectories(ASSETS_PLUGINS_ANDROID_PATH); bool refreshDb = false; string packageName; int count = directories.Length; for (int i = 0; i < count; ++i) { if (directories[i].Contains("orion")) { packageName = directories[i].Replace(".androidlib", ""); packageName = packageName.Replace(ASSETS_PLUGINS_ANDROID_PATH, ""); if (!packageNames.Contains(packageName)) { refreshDb = true; HtAssetDatabase.DeleteFolder(directories[i]); UnityEngine.Debug.Log("Delete " + directories[i]); } } } if (refreshDb) { AssetDatabase.Refresh(); } } } #endregion } }