public static LoadableScene[] GetLoadableScenes(SubScene[] scenes)
        {
            var loadables = new List <LoadableScene>();

            foreach (var scene in scenes)
            {
                var sceneHeaderPath = EntityScenesPaths.GetLoadPath(scene.SceneGUID, EntityScenesPaths.PathType.EntitiesHeader, -1);
                var sceneHeader     = AssetDatabase.LoadAssetAtPath <SubSceneHeader>(sceneHeaderPath);

                if (sceneHeader != null && sceneHeader.Sections != null && scene._SceneEntities.Count == sceneHeader.Sections.Length)
                {
                    for (int i = 0; i != sceneHeader.Sections.Length; i++)
                    {
                        var name         = scene.SceneAsset.name;
                        var sectionIndex = sceneHeader.Sections[i].SubSectionIndex;
                        if (sectionIndex != 0)
                        {
                            name += $" Section: {sectionIndex}";
                        }

                        loadables.Add(new LoadableScene
                        {
                            Scene = scene._SceneEntities[i],
                            Name  = name
                        });
                    }
                }
            }

            return(loadables.ToArray());
        }
        public static string GetEntitySceneWarning(SubScene[] scenes, out bool requireCacheRebuild)
        {
            requireCacheRebuild = false;
            foreach (var scene in scenes)
            {
                if (scene.SceneAsset == null)
                {
                    return($"Please assign a valid Scene Asset");
                }

                var sceneHeaderPath = EntityScenesPaths.GetLoadPath(scene.SceneGUID, EntityScenesPaths.PathType.EntitiesHeader, -1);
                var sceneHeader     = AssetDatabase.LoadAssetAtPath <SubSceneHeader>(sceneHeaderPath);

                if (sceneHeader == null)
                {
                    requireCacheRebuild = true;
                    return($"The entity binary file header couldn't be found. Please Rebuild Entity Cache.");
                }

                //@TODO: validate header against wrong types?
                //@TODO: validate actual errors when loading
                //@TODO: validate against dependency chain being out of date
            }

            return(null);
        }
        public static void ConvertToBuild(GUID buildSettingSceneGuid, UnityEditor.Build.Pipeline.Tasks.CalculateCustomDependencyData task)
        {
            var buildSettingScenePath  = AssetDatabase.GUIDToAssetPath(buildSettingSceneGuid.ToString());
            var sceneWithBuildSettings = ReadSceneWithBuildSettings(buildSettingScenePath);

            var hash = UnityEditor.Experimental.AssetDatabaseExperimental.GetArtifactHash(buildSettingSceneGuid.ToString(), typeof(SubSceneImporter));

            string[] paths;
            if (!UnityEditor.Experimental.AssetDatabaseExperimental.GetArtifactPaths(hash, out paths))
            {
                return;
            }

            foreach (var path in paths)
            {
                var ext = System.IO.Path.GetExtension(path).Replace(".", "");
                if (ext == EntityScenesPaths.GetExtension(EntityScenesPaths.PathType.EntitiesHeader))
                {
                    var loadPath = EntityScenesPaths.GetLoadPath(sceneWithBuildSettings.SceneGUID, EntityScenesPaths.PathType.EntitiesHeader, -1);
                    System.IO.File.Copy(path, loadPath, true);
                    continue;
                }

                if (ext == EntityScenesPaths.GetExtension(EntityScenesPaths.PathType.EntitiesBinary))
                {
                    var sectionIndex = EntityScenesPaths.GetSectionIndexFromPath(path);
                    var loadPath     = EntityScenesPaths.GetLoadPath(sceneWithBuildSettings.SceneGUID, EntityScenesPaths.PathType.EntitiesBinary, sectionIndex);
                    System.IO.File.Copy(path, loadPath, true);
                    continue;
                }

                if (ext == EntityScenesPaths.GetExtension(EntityScenesPaths.PathType.EntitiesUnityObjectReferences))
                {
                    var sectionIndex = EntityScenesPaths.GetSectionIndexFromPath(path);
                    task.GetObjectIdentifiersAndTypesForSerializedFile(path, out UnityEditor.Build.Content.ObjectIdentifier[] objectIds, out System.Type[] types);
                    var bundlePath = EntityScenesPaths.GetLoadPath(sceneWithBuildSettings.SceneGUID, EntityScenesPaths.PathType.EntitiesUnityObjectReferences, sectionIndex);
                    var bundleName = System.IO.Path.GetFileName(bundlePath);
                    task.CreateAssetEntryForObjectIdentifiers(objectIds, path, bundleName, bundleName, typeof(ReferencedUnityObjects));
                }
            }
        }
        public override BuildStepResult RunBuildStep(BuildContext context)
        {
            m_TemporaryFileTracker = new TemporaryFileTracker();

            var profile = GetRequiredComponent <ClassicBuildProfile>(context);

            if (profile.Target == UnityEditor.BuildTarget.NoTarget)
            {
                return(Failure($"Invalid build target '{profile.Target.ToString()}'."));
            }
            if (profile.Target != EditorUserBuildSettings.activeBuildTarget)
            {
                return(Failure($"ActiveBuildTarget must be switched before the {nameof(BuildStepSubSceneBundles)} step."));
            }

            var buildConfigurationGuid = new Hash128(BuildContextInternals.GetBuildConfigurationGUID(context));
            var content   = new UnityEditor.Build.Pipeline.BundleBuildContent(new AssetBundleBuild[0]);
            var sceneList = GetRequiredComponent <SceneList>(context);
            var visited   = new HashSet <Hash128>();

            foreach (var scenePath in sceneList.GetScenePathsForBuild())
            {
                var sceneGuid     = AssetDatabase.AssetPathToGUID(scenePath);
                var subSceneGuids = SceneMetaDataImporter.GetSubSceneGuids(sceneGuid);
                foreach (var subSceneGuid in subSceneGuids)
                {
                    if (!visited.Add(subSceneGuid))
                    {
                        continue;
                    }

                    var hash128Guid = EntityScenesPaths.CreateBuildConfigurationSceneFile(subSceneGuid, buildConfigurationGuid);
                    content.CustomAssets.Add(new UnityEditor.Build.Pipeline.Interfaces.CustomContent
                    {
                        Asset     = hash128Guid,
                        Processor = SubSceneImporter.ConvertToBuild
                    });
                }
            }

            if (content.CustomAssets.Count == 0)
            {
                return(Success());
            }

            var buildPath = Path.GetDirectoryName(EntityScenesPaths.GetLoadPath(new Hash128(), EntityScenesPaths.PathType.EntitiesUnityObjectReferences, 0));

            // Delete SubScenes build folder defensively (Eg. if unity crashes during build)
            FileUtil.DeleteFileOrDirectory(buildPath);

            m_TemporaryFileTracker.CreateDirectory(buildPath);

            var group      = UnityEditor.BuildPipeline.GetBuildTargetGroup(profile.Target);
            var parameters = new UnityEditor.Build.Pipeline.BundleBuildParameters(profile.Target, group, buildPath);

            parameters.BundleCompression = UnityEngine.BuildCompression.Uncompressed;

            var status = UnityEditor.Build.Pipeline.ContentPipeline.BuildAssetBundles(parameters, content, out UnityEditor.Build.Pipeline.Interfaces.IBundleBuildResults result);

            context.SetValue(result);

            var succeeded = status >= UnityEditor.Build.Pipeline.ReturnCode.Success;

            return(succeeded ? Success() : Failure($"BuildAssetBundles failed with status '{status}'."));
        }