using System; using UnityEngine; using UnityEngine.SceneManagement; namespace StansAssets.SceneManagement { public class SceneLoadService : ISceneLoadService { public void Load(IScenePreloader preloader, string sceneName, Action onComplete) where T : ISceneManager { preloader.FadeIn(() => { Load(sceneName, (scene, sceneManager) => { preloader.FadeOut(() => { onComplete?.Invoke(scene, sceneManager); }); }); }); } public void Load(string sceneName, Action onComplete) where T : ISceneManager { AdditiveScenesLoader.LoadAdditively(sceneName, loadOperationArgs => { if (loadOperationArgs.Status == OperationStatus.Success) { var sceneManager = FindMonoTypeOnSceneRoot(loadOperationArgs.Scene); var sceneDelegate = FindMonoTypeOnSceneRoot(loadOperationArgs.Scene); if (sceneDelegate != null) { sceneDelegate.ActivateScene(() => { onComplete?.Invoke(loadOperationArgs.Scene, sceneManager); }); } else { onComplete?.Invoke(loadOperationArgs.Scene, sceneManager); } } else { onComplete?.Invoke(default, default); } }); } public void Deactivate(string sceneName, Action onComplete) where T : ISceneManager { if (AdditiveScenesLoader.TryGetLoadedScene(sceneName, out var scene)) { var sceneManager = FindMonoTypeOnSceneRoot(scene); var sceneDelegate = FindMonoTypeOnSceneRoot(scene); sceneDelegate?.DeactivateScene(() => { onComplete?.Invoke(sceneManager); }); } else { throw new InvalidOperationException($"{nameof(SceneLoadService)} can not deactivate {sceneName} scene, because it wasn't loaded. "); } } public void Unload(string sceneName, Action onComplete) { if (AdditiveScenesLoader.TryGetLoadedScene(sceneName, out var scene)) { AdditiveScenesLoader.Unload(scene, onComplete); } else { // TODO error and optional param with scene action stack onComplete?.Invoke(); } } T FindMonoTypeOnSceneRoot(Scene scene) { foreach (var gameObject in scene.GetRootGameObjects()) { foreach (var mono in gameObject.GetComponents()) { if (mono is T sceneDelegate) return sceneDelegate; } } return default; } } }