using System; using UnityEngine; using UI; using Core; using UnityEngine.SceneManagement; namespace Bootstrap { /// /// Controller for the boot scene that coordinates bootstrap initialization with loading screen /// public class BootSceneController : MonoBehaviour { [SerializeField] private string mainMenuSceneName = "MainMenu"; [SerializeField] private float minDelayAfterBoot = 0.5f; // Small delay after boot to ensure smooth transition [SerializeField] private bool debugMode = false; // Progress distribution between bootstrap and scene loading [SerializeField, Range(0.1f, 0.9f)] private float bootProgressWeight = 0.5f; // Default 50/50 split private enum LoadingPhase { Bootstrap, SceneLoading } private LoadingPhase _currentPhase = LoadingPhase.Bootstrap; private bool _bootComplete = false; private bool _hasStartedLoading = false; private float _sceneLoadingProgress = 0f; private void Start() { Debug.Log("[BootSceneController] Boot scene started"); // Ensure the loading screen controller exists if (LoadingScreenController.Instance == null) { Debug.LogError("[BootSceneController] No LoadingScreenController found in the scene!"); return; } // Show the loading screen immediately with our combined progress provider LoadingScreenController.Instance.ShowLoadingScreen( progressProvider: GetCombinedProgress, onComplete: () => { Debug.Log("[BootSceneController] Loading screen fully hidden, boot sequence completed"); } ); // Start the boot process if not already initialized if (!CustomBoot.Initialised) { // Subscribe to the boot completion event CustomBoot.OnBootCompleted += OnBootCompleted; CustomBoot.OnBootProgressChanged += OnBootProgressChanged; // Start initialization CustomBoot.PerformInitialisation(); } else { // If already initialized (can happen in editor testing), proceed immediately Debug.Log("[BootSceneController] Bootstrap already initialized, proceeding to main menu"); OnBootCompleted(); } // In debug mode, log additional information if (debugMode) { InvokeRepeating(nameof(LogDebugInfo), 0.1f, 0.5f); } } private void OnDestroy() { // Clean up event subscriptions CustomBoot.OnBootCompleted -= OnBootCompleted; CustomBoot.OnBootProgressChanged -= OnBootProgressChanged; if (debugMode) { CancelInvoke(nameof(LogDebugInfo)); } } /// /// Progress provider that combines bootstrap and scene loading progress /// private float GetCombinedProgress() { switch (_currentPhase) { case LoadingPhase.Bootstrap: // Scale bootstrap progress from 0 to bootProgressWeight return CustomBoot.CurrentProgress * bootProgressWeight; case LoadingPhase.SceneLoading: // Scale scene loading progress from bootProgressWeight to 1.0 return bootProgressWeight + (_sceneLoadingProgress * (1f - bootProgressWeight)); default: return 0f; } } private void OnBootProgressChanged(float progress) { if (debugMode) { Debug.Log($"[BootSceneController] Bootstrap progress: {progress:P0}, Combined: {GetCombinedProgress():P0}"); } } private void LogDebugInfo() { Debug.Log($"[BootSceneController] Debug - Phase: {_currentPhase}, Bootstrap: {CustomBoot.CurrentProgress:P0}, " + $"Scene: {_sceneLoadingProgress:P0}, Combined: {GetCombinedProgress():P0}, Boot Complete: {_bootComplete}"); } private void OnBootCompleted() { // Unsubscribe to prevent duplicate calls CustomBoot.OnBootCompleted -= OnBootCompleted; Debug.Log("[BootSceneController] Boot process completed"); _bootComplete = true; // After a small delay, start loading the main menu // This prevents jerky transitions if boot happens very quickly Invoke(nameof(StartLoadingMainMenu), minDelayAfterBoot); } private void StartLoadingMainMenu() { if (_hasStartedLoading) return; _hasStartedLoading = true; _currentPhase = LoadingPhase.SceneLoading; LoadMainMenu(); } private async void LoadMainMenu() { Debug.Log($"[BootSceneController] Loading main menu scene: {mainMenuSceneName}"); try { // Initialize scene loading progress to 0 to ensure proper remapping _sceneLoadingProgress = 0f; // Create a progress object that remaps scene loading progress (0-1) to our second phase range var progress = new Progress(p => { // Store the raw scene loading progress (0-1) _sceneLoadingProgress = p; if (debugMode) { Debug.Log($"[BootSceneController] Scene loading raw: {p:P0}, Combined: {GetCombinedProgress():P0}"); } }); // Load the scene but don't auto-hide loading screen (we're managing that ourselves) await SceneManagerService.Instance.SwitchSceneAsync(mainMenuSceneName, progress, autoHideLoadingScreen: false); // Ensure progress is complete _sceneLoadingProgress = 1f; // Scene is fully loaded, we can now hide the loading screen LoadingScreenController.Instance.HideLoadingScreen(); } catch (Exception e) { Debug.LogError($"[BootSceneController] Error loading main menu: {e.Message}"); // Still try to hide the loading screen even if there was an error LoadingScreenController.Instance.HideLoadingScreen(); } } } }