using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
namespace MoreMountains.Tools
{
///
/// This helper class, meant to be used by the MMAdditiveSceneLoadingManager, creates a temporary scene to store objects that might get instantiated, and empties it in the destination scene once loading is complete
///
public class MMSceneLoadingAntiSpill
{
protected Scene _antiSpillScene;
protected Scene _destinationScene;
protected UnityAction _onActiveSceneChangedCallback;
protected string _sceneToLoadName;
protected string _antiSpillSceneName;
protected List _spillSceneRoots = new List(50);
protected static List _scenesInBuild;
///
/// Creates the temporary scene
///
///
public virtual void PrepareAntiFill(string sceneToLoadName, string antiSpillSceneName = "")
{
_destinationScene = default;
_sceneToLoadName = sceneToLoadName;
if (antiSpillSceneName == "")
{
_antiSpillScene = SceneManager.CreateScene($"AntiSpill_{sceneToLoadName}");
PrepareAntiFillSetSceneActive();
}
else
{
_scenesInBuild = MMScene.GetScenesInBuild();
if (!_scenesInBuild.Contains(antiSpillSceneName))
{
Debug.LogError("MMSceneLoadingAntiSpill : impossible to load the '"+antiSpillSceneName+"' scene, " +
"there is no such scene in the project's build settings.");
return;
}
SceneManager.LoadScene(antiSpillSceneName, LoadSceneMode.Additive);
_antiSpillScene = SceneManager.GetSceneByName(antiSpillSceneName);
_antiSpillSceneName = _antiSpillScene.name;
SceneManager.sceneLoaded += PrepareAntiFillOnSceneLoaded;
}
}
///
/// When not creating an anti fill scene, acts once the scene has been actually created and is ready to be set active
/// This is bypassed when creating the scene
///
///
///
protected virtual void PrepareAntiFillOnSceneLoaded(Scene newScene, LoadSceneMode mode)
{
if (newScene.name != _antiSpillSceneName)
{
return;
}
SceneManager.sceneLoaded -= PrepareAntiFillOnSceneLoaded;
PrepareAntiFillSetSceneActive();
}
///
/// Sets the anti spill scene active
///
protected virtual void PrepareAntiFillSetSceneActive()
{
if (_onActiveSceneChangedCallback != null) { SceneManager.activeSceneChanged -= _onActiveSceneChangedCallback; }
_onActiveSceneChangedCallback = OnActiveSceneChanged;
SceneManager.activeSceneChanged += _onActiveSceneChangedCallback;
SceneManager.SetActiveScene(_antiSpillScene);
}
///
/// Once the destination scene has been loaded, we catch that event and prepare to empty
///
///
///
protected virtual void OnActiveSceneChanged(Scene from, Scene to)
{
if (from == _antiSpillScene)
{
SceneManager.activeSceneChanged -= _onActiveSceneChangedCallback;
_onActiveSceneChangedCallback = null;
EmptyAntiSpillScene();
}
}
///
/// Empties the contents of the anti spill scene into the destination scene
///
protected virtual void EmptyAntiSpillScene()
{
if (_antiSpillScene.IsValid() && _antiSpillScene.isLoaded)
{
_spillSceneRoots.Clear();
_antiSpillScene.GetRootGameObjects(_spillSceneRoots);
_destinationScene = SceneManager.GetSceneByName(_sceneToLoadName);
if (_spillSceneRoots.Count > 0)
{
if (_destinationScene.IsValid() && _destinationScene.isLoaded)
{
foreach (var root in _spillSceneRoots)
{
SceneManager.MoveGameObjectToScene(root, _destinationScene);
}
}
}
SceneManager.UnloadSceneAsync(_antiSpillScene);
}
}
}
}