using System.Collections.Generic;
using UnityEngine.SceneManagement;
namespace UnityEngine.Sequences
{
///
/// Manager used by SceneActivationTrack and SceneActivationMixer.
/// It enables/disables Scenes based on the number of requests it receives.
///
static class SceneActivationManager
{
///
/// List of active tracked Scenes.
///
static readonly List s_SceneTrackers = new List();
///
/// Activation strategy to apply when enabling or disabling a Scene.
///
static readonly ISceneActivationBehaviour s_ActivationStrategy = new BasicSceneActivation();
///
/// Tracker object used to follow the number of requesters (= SceneActivationTrack) for a given Scene.
///
///
/// Mostly useful when multiple SceneActivationTrack request the same Scene.
/// A weight is computed based on the received request to ensure if a given Scene must be enabled.
///
[System.Serializable]
class SceneTracker
{
SceneReference m_Scene;
///
/// Scene path relative to the Assets/ folder.
///
public string path
{
get => m_Scene.path;
set => m_Scene = new SceneReference() {path = value};
}
///
/// List of request received for a given frame.
///
List m_RequestReceivedCount = new List();
///
/// Number of registered requester.
///
int m_ReferenceCount = 0;
///
/// Number of requester about to be deleted>
///
int m_ReferenceTrashCount;
public bool hasReceivedOneActiveRequest => m_RequestReceivedCount.Contains(true);
public void RequestState(bool state)
{
m_RequestReceivedCount.Add(state);
}
public void IncrementRegisteredRequesterCount()
{
++m_ReferenceCount;
}
void DecrementRegisterRequesterCount()
{
--m_ReferenceCount;
}
public void RemoveRequester()
{
++m_ReferenceTrashCount;
DecrementRegisterRequesterCount();
}
public bool HasRegisteredRequester()
{
return m_ReferenceCount > 0;
}
///
/// Indicates if the tracker has received a request from every registered requester.
///
/// False when not all requester have made their request yet.
public bool Completed()
{
return m_ReferenceCount + m_ReferenceTrashCount == m_RequestReceivedCount.Count;
}
///
/// Reset the current list of received state requests and references to be deleted.
/// Call this method at the beginning of a new frame.
///
public void Reset()
{
m_RequestReceivedCount.Clear();
m_ReferenceTrashCount = 0;
}
}
internal static Scene GetScene(string path)
{
return SceneManager.GetSceneByPath(path);
}
///
/// Requests a Scene to be activated.
///
/// Path to the Scene, relative to the project folder.
internal static void RequestActivateScene(string path)
{
Scene loadedScene = SceneManager.GetSceneByPath(path);
if (!loadedScene.isLoaded)
return;
SceneTracker tracker = GetSceneTracker(path);
tracker.RequestState(true);
if (tracker.Completed())
ProcessState(tracker);
}
///
/// Requests a Scene to be deactivated.
///
/// Path to the Scene, relative to the project folder.
internal static void RequestDeactivateScene(string path)
{
Scene loadedScene = SceneManager.GetSceneByPath(path);
if (!loadedScene.isLoaded)
return;
SceneTracker tracker = GetSceneTracker(path);
tracker.RequestState(false);
if (tracker.Completed())
ProcessState(tracker);
}
///
/// Registers a requester. This must be done before making a request.
///
/// Path to the Scene, relative to the project folder.
internal static void Register(string path)
{
if (string.IsNullOrEmpty(path))
throw new System.ArgumentException("Invalid scene path provided.");
var tracker = GetSceneTracker(path);
if (tracker != null)
{
tracker.IncrementRegisteredRequesterCount();
return;
}
tracker = new SceneTracker() { path = path };
tracker.IncrementRegisteredRequesterCount();
s_SceneTrackers.Add(tracker);
}
///
/// Unregisters a requester.
///
/// Path to the Scene, relative to the project folder.
internal static void Unregister(string path)
{
if (string.IsNullOrEmpty(path))
throw new System.ArgumentException("Invalid scene path provided.");
var tracker = GetSceneTracker(path);
if (tracker == null)
return;
RequestDeactivateScene(path);
tracker.RemoveRequester();
if (!tracker.HasRegisteredRequester())
s_SceneTrackers.Remove(tracker);
}
///
/// Processes the received requests for a frame then executes the active activation strategy.
///
///
static void ProcessState(SceneTracker tracker)
{
Scene loadedScene = GetScene(tracker.path);
if (!loadedScene.isLoaded)
return;
s_ActivationStrategy.Execute(loadedScene, tracker.hasReceivedOneActiveRequest);
tracker.Reset();
}
///
/// Gets the SceneTracker for the given Scene path.
///
/// The Scene path to use to find the corresponding SceneTracker.
/// The SceneTracker found, or null if no SceneTracker exists for the given Scene path.
static SceneTracker GetSceneTracker(string path)
{
SceneTracker tracker = s_SceneTrackers.Find(sceneTracker => sceneTracker.path == path);
return tracker;
}
}
}