Files
BlockSpace-v1.5.0b/Assets/Scripts/Assembly-CSharp/BlockSpace/Worlds/WorldLoadingScreenController.cs
T
2026-06-01 17:19:55 +02:00

356 lines
9.1 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace BlockSpace.Worlds
{
[DisallowMultipleComponent]
public sealed class WorldLoadingScreenController : MonoBehaviour
{
private struct CameraState
{
public CameraClearFlags clearFlags;
public Color backgroundColor;
}
private struct RigidbodyState
{
public Vector3 linearVelocity;
public Vector3 angularVelocity;
}
[SerializeField]
private GameObject loadingScreenObject;
[SerializeField]
private Slider progressSlider;
[SerializeField]
private bool hideSceneWhileLoading = true;
[SerializeField]
private int requiredTeleportsToComplete = 2;
private readonly Dictionary<Renderer, bool> rendererStates = new Dictionary<Renderer, bool>();
private readonly Dictionary<Canvas, bool> canvasStates = new Dictionary<Canvas, bool>();
private readonly Dictionary<Graphic, bool> graphicStates = new Dictionary<Graphic, bool>();
private readonly Dictionary<Camera, CameraState> cameraStates = new Dictionary<Camera, CameraState>();
private readonly Dictionary<Behaviour, bool> movementBehaviourStates = new Dictionary<Behaviour, bool>();
private readonly Dictionary<Rigidbody, RigidbodyState> rigidbodyStates = new Dictionary<Rigidbody, RigidbodyState>();
private bool loading;
private int completedTeleports;
public static WorldLoadingScreenController Instance { get; private set; }
public bool IsLoading => loading;
public static event Action LoadingFinished;
public void Configure(GameObject screenObject, Slider slider)
{
if (screenObject != null)
{
loadingScreenObject = screenObject;
}
if (slider != null)
{
progressSlider = slider;
}
if (!loading)
{
SetScreenVisible(visible: false);
}
}
private void Awake()
{
if (Instance != null && Instance != this)
{
Debug.LogWarning("Multiple WorldLoadingScreenController instances found. Using the latest active instance.", this);
}
Instance = this;
SetScreenVisible(visible: false);
SetProgress(0f);
}
private void OnDisable()
{
SetLoading(isLoading: false);
}
private void OnDestroy()
{
if (Instance == this)
{
Instance = null;
}
}
public void BeginLoading(float initialProgress = 0f)
{
completedTeleports = 0;
SetLoading(isLoading: true);
SetProgress(initialProgress);
}
public void SetLoading(bool isLoading)
{
if (loading == isLoading)
{
SetScreenVisible(isLoading);
return;
}
loading = isLoading;
SetScreenVisible(isLoading);
if (hideSceneWhileLoading)
{
if (isLoading)
{
HideScene();
}
else
{
RestoreScene();
}
}
if (isLoading)
{
DisableMovement();
}
else
{
RestoreMovement();
}
if (!isLoading)
{
completedTeleports = 0;
SetProgress(0f);
WorldLoadingScreenController.LoadingFinished?.Invoke();
}
}
public void SetCheckpoint(float progress)
{
if (loading && (!(progressSlider != null) || !(progress < progressSlider.value)))
{
SetProgress(progress);
}
}
public void NotifyLocalPlayerTeleported(bool forceComplete = false)
{
if (loading)
{
completedTeleports++;
if (!forceComplete && completedTeleports < Mathf.Max(1, requiredTeleportsToComplete))
{
SetCheckpoint(0.97f);
}
else
{
CompleteLoading();
}
}
}
public void CompleteLoading()
{
if (loading)
{
SetProgress(1f);
SetLoading(isLoading: false);
}
}
public void SetProgress(float progress)
{
if (loading && hideSceneWhileLoading)
{
HideScene();
}
if (!(progressSlider == null))
{
progressSlider.minValue = 0f;
progressSlider.maxValue = 1f;
progressSlider.value = Mathf.Clamp01(progress);
}
}
private void SetScreenVisible(bool visible)
{
if (loadingScreenObject != null)
{
loadingScreenObject.SetActive(visible);
}
}
private void HideScene()
{
Transform loadingRoot = ((loadingScreenObject != null) ? loadingScreenObject.transform : base.transform);
Renderer[] array = UnityEngine.Object.FindObjectsByType<Renderer>(FindObjectsInactive.Include, FindObjectsSortMode.None);
foreach (Renderer renderer in array)
{
if (!(renderer == null) && !rendererStates.ContainsKey(renderer) && !IsInsideLoadingScreen(renderer.transform, loadingRoot))
{
rendererStates[renderer] = renderer.enabled;
renderer.enabled = false;
}
}
Canvas[] array2 = UnityEngine.Object.FindObjectsByType<Canvas>(FindObjectsInactive.Include, FindObjectsSortMode.None);
foreach (Canvas canvas in array2)
{
if (!(canvas == null) && !canvasStates.ContainsKey(canvas) && !IsInsideLoadingScreen(canvas.transform, loadingRoot))
{
canvasStates[canvas] = canvas.enabled;
canvas.enabled = false;
}
}
Graphic[] array3 = UnityEngine.Object.FindObjectsByType<Graphic>(FindObjectsInactive.Include, FindObjectsSortMode.None);
foreach (Graphic graphic in array3)
{
if (!(graphic == null) && !graphicStates.ContainsKey(graphic) && !IsInsideLoadingScreen(graphic.transform, loadingRoot))
{
graphicStates[graphic] = graphic.enabled;
graphic.enabled = false;
}
}
Camera[] array4 = UnityEngine.Object.FindObjectsByType<Camera>(FindObjectsInactive.Include, FindObjectsSortMode.None);
foreach (Camera camera in array4)
{
if (!(camera == null) && !cameraStates.ContainsKey(camera))
{
cameraStates[camera] = new CameraState
{
clearFlags = camera.clearFlags,
backgroundColor = camera.backgroundColor
};
camera.clearFlags = CameraClearFlags.Color;
camera.backgroundColor = Color.black;
}
}
}
private void RestoreScene()
{
foreach (KeyValuePair<Renderer, bool> rendererState in rendererStates)
{
if (rendererState.Key != null)
{
rendererState.Key.enabled = rendererState.Value;
}
}
foreach (KeyValuePair<Canvas, bool> canvasState in canvasStates)
{
if (canvasState.Key != null)
{
canvasState.Key.enabled = canvasState.Value;
}
}
foreach (KeyValuePair<Graphic, bool> graphicState in graphicStates)
{
if (graphicState.Key != null)
{
graphicState.Key.enabled = graphicState.Value;
}
}
foreach (KeyValuePair<Camera, CameraState> cameraState in cameraStates)
{
if (cameraState.Key != null)
{
cameraState.Key.clearFlags = cameraState.Value.clearFlags;
cameraState.Key.backgroundColor = cameraState.Value.backgroundColor;
}
}
rendererStates.Clear();
canvasStates.Clear();
graphicStates.Clear();
cameraStates.Clear();
}
private void DisableMovement()
{
Behaviour[] array = UnityEngine.Object.FindObjectsByType<Behaviour>(FindObjectsInactive.Include, FindObjectsSortMode.None);
foreach (Behaviour behaviour in array)
{
if (!(behaviour == null) && !movementBehaviourStates.ContainsKey(behaviour) && IsMovementBehaviour(behaviour))
{
movementBehaviourStates[behaviour] = behaviour.enabled;
behaviour.enabled = false;
}
}
Rigidbody[] array2 = UnityEngine.Object.FindObjectsByType<Rigidbody>(FindObjectsInactive.Include, FindObjectsSortMode.None);
foreach (Rigidbody rigidbody in array2)
{
if (!(rigidbody == null) && !rigidbodyStates.ContainsKey(rigidbody))
{
rigidbodyStates[rigidbody] = new RigidbodyState
{
linearVelocity = rigidbody.linearVelocity,
angularVelocity = rigidbody.angularVelocity
};
rigidbody.linearVelocity = Vector3.zero;
rigidbody.angularVelocity = Vector3.zero;
}
}
}
private void RestoreMovement()
{
foreach (KeyValuePair<Behaviour, bool> movementBehaviourState in movementBehaviourStates)
{
if (movementBehaviourState.Key != null)
{
movementBehaviourState.Key.enabled = movementBehaviourState.Value;
}
}
foreach (KeyValuePair<Rigidbody, RigidbodyState> rigidbodyState in rigidbodyStates)
{
if (rigidbodyState.Key != null)
{
rigidbodyState.Key.linearVelocity = rigidbodyState.Value.linearVelocity;
rigidbodyState.Key.angularVelocity = rigidbodyState.Value.angularVelocity;
}
}
movementBehaviourStates.Clear();
rigidbodyStates.Clear();
}
private bool IsMovementBehaviour(Behaviour behaviour)
{
if (behaviour == this)
{
return false;
}
string text = behaviour.GetType().Name;
if (!((behaviour.GetType().FullName ?? string.Empty) == "GorillaLocomotion.Player") && !(text == "DesktopRigController") && !(text == "CreatorFlightController") && !text.Contains("LocomotionProvider") && !text.Contains("MoveProvider") && !text.Contains("TurnProvider") && !text.Contains("JumpProvider") && !text.Contains("TeleportationProvider") && !text.Contains("ClimbProvider") && !text.Contains("ContinuousMove") && !text.Contains("DynamicMove") && !text.Contains("SnapTurn"))
{
return text.Contains("SmoothTurn");
}
return true;
}
private bool IsInsideLoadingScreen(Transform target, Transform loadingRoot)
{
if (target != null && loadingRoot != null)
{
if (!(target == loadingRoot) && !target.IsChildOf(loadingRoot))
{
return loadingRoot.IsChildOf(target);
}
return true;
}
return false;
}
}
}