diff --git a/Assets/Scripts/Core/SceneOrientationEnforcer.cs b/Assets/Scripts/Core/SceneOrientationEnforcer.cs index 7ab784ff..3964613a 100644 --- a/Assets/Scripts/Core/SceneOrientationEnforcer.cs +++ b/Assets/Scripts/Core/SceneOrientationEnforcer.cs @@ -1,46 +1,37 @@ -using UnityEngine; -using UnityEngine.SceneManagement; -using System; +using System; +using System.Collections; +using Bootstrap; using Input; using Settings; -using System.Collections; -using Minigames.DivingForPictures; -using Bootstrap; -using Core; +using UnityEngine; +using UnityEngine.SceneManagement; -namespace Utility +namespace Core { public class SceneOrientationEnforcer : MonoBehaviour { + // Singleton instance private static SceneOrientationEnforcer _instance; - private static bool _isQuitting; - - /// - /// Singleton instance of the SceneOrientationEnforcer. No longer creates an instance if one doesn't exist. - /// public static SceneOrientationEnforcer Instance => _instance; [Header("Config")] public SceneOrientationConfig orientationConfig; public GameObject orientationPromptPrefab; - public event Action OnOrientationCorrect; - public event Action OnOrientationIncorrect; - - private GameObject _promptInstance; - private ScreenOrientationRequirement _requiredOrientation; - private bool _orientationCorrect; - private Coroutine _orientationCheckCoroutine; - private bool _isDivingMinigame = false; - private Coroutine _continuousOrientationCheckCoroutine; - void Awake() { _instance = this; - OnOrientationCorrect += HandleOrientationCorrect; // Register for post-boot initialization BootCompletionService.RegisterInitAction(InitializePostBoot); + + #if UNITY_EDITOR + // When playing in the editor, manually invoke OnSceneLoaded for the currently active scene + if (Application.isPlaying) + { + OnSceneLoaded(SceneManager.GetActiveScene(), LoadSceneMode.Single); + } + #endif } private void InitializePostBoot() @@ -50,180 +41,118 @@ namespace Utility // Subscribe to sceneLoaded event SceneManager.sceneLoaded += OnSceneLoaded; - // Manually invoke for the first scene (unless it's Main Menu) - var activeScene = SceneManager.GetActiveScene(); - if (!IsMainMenuScene(activeScene)) - { - OnSceneLoaded(activeScene, LoadSceneMode.Single); - } } - - /// - /// Checks if the current device orientation matches the required orientation for the scene - /// - /// True if the orientation is correct, false otherwise - public bool IsOrientationCorrect() - { - switch (_requiredOrientation) - { - case ScreenOrientationRequirement.Portrait: - return Screen.orientation == ScreenOrientation.Portrait || Screen.orientation == ScreenOrientation.PortraitUpsideDown; - case ScreenOrientationRequirement.Landscape: - return Screen.orientation == ScreenOrientation.LandscapeLeft || Screen.orientation == ScreenOrientation.LandscapeRight; - case ScreenOrientationRequirement.NotApplicable: - return true; - default: - return true; - } - } - - /// - /// Checks if the current scene is the diving minigame scene - /// - /// True if the scene is "DivingForPictures", false otherwise - public bool IsDivingMinigameScene(Scene scene) - { - return scene.name == "DivingForPictures"; - } - + private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { - // Clean up any previous prompt/coroutine - CleanupPromptAndCoroutine(); + // Determine desired orientation for this scene + string sceneName = scene.name; + ScreenOrientationRequirement requirement = ScreenOrientationRequirement.NotApplicable; - if (IsMainMenuScene(scene)) - return; - - _isDivingMinigame = IsDivingMinigameScene(scene); - - _requiredOrientation = orientationConfig != null ? orientationConfig.GetRequirementForScene(scene.name) : ScreenOrientationRequirement.NotApplicable; - _orientationCorrect = IsOrientationCorrect(); - - if (!_orientationCorrect) + if (sceneName.ToLower().Contains("bootstrap")) { - InputManager.Instance.SetInputMode(InputMode.UI); - ShowPrompt(); - // If this is the diving minigame, start continuous orientation checking - if (_isDivingMinigame) - { - _continuousOrientationCheckCoroutine = StartCoroutine(ContinuousOrientationCheckRoutine()); - } - else - { - _orientationCheckCoroutine = StartCoroutine(OrientationCheckRoutine()); - } + // Bootstrap being loaded additively, don't do anything + Logging.Debug($"[SceneOrientationEnforcer] Detected bootstrapped scene: '{sceneName}'. Skipping orientation enforcement."); + return; + } + + if (orientationConfig != null) + { + requirement = orientationConfig.GetRequirementForScene(sceneName); } else { - _orientationCorrect = true; - OnOrientationCorrect?.Invoke(); - - // If this is the diving minigame, start continuous orientation checking - if (_isDivingMinigame) - { - _continuousOrientationCheckCoroutine = StartCoroutine(ContinuousOrientationCheckRoutine()); - } + Logging.Debug($"[SceneOrientationEnforcer] No orientationConfig assigned. Defaulting to Landscape for scene '{sceneName}'"); + } + + switch (requirement) + { + case ScreenOrientationRequirement.Portrait: + Logging.Debug($"[SceneOrientationEnforcer] Forcing Portrait for scene '{sceneName}'"); + StartCoroutine(ForcePortrait()); + break; + case ScreenOrientationRequirement.Landscape: + Logging.Debug($"[SceneOrientationEnforcer] Forcing Landscape for scene '{sceneName}'"); + StartCoroutine(ForceLandscape()); + break; + case ScreenOrientationRequirement.NotApplicable: + default: + // Default to landscape when no specific requirement is found + Logging.Debug($"[SceneOrientationEnforcer] No specific orientation for scene '{sceneName}'. Defaulting to Landscape"); + StartCoroutine(ForceLandscape()); + break; } } - - private System.Collections.IEnumerator OrientationCheckRoutine() - { - while (!IsOrientationCorrect()) - { - yield return new WaitForSeconds(0.5f); - } - _orientationCorrect = true; - OnOrientationCorrect?.Invoke(); - } - - private System.Collections.IEnumerator ContinuousOrientationCheckRoutine() - { - while (!IsOrientationCorrect()) - { - yield return new WaitForSeconds(0.5f); - } - _orientationCorrect = true; - OnOrientationCorrect?.Invoke(); - - while (true) - { - // Wait for a short interval before checking again - yield return new WaitForSeconds(0.2f); - - // Check if orientation is now incorrect - if (!IsOrientationCorrect()) - { - OnOrientationIncorrect?.Invoke();; - InputManager.Instance.SetInputMode(InputMode.UI); - ShowPrompt(); - _continuousOrientationCheckCoroutine = StartCoroutine(ContinuousOrientationCheckRoutine()); - yield break; // Exit this coroutine - } - } - } - - private void ShowPrompt() - { - if (orientationPromptPrefab != null && _promptInstance == null) - { - _promptInstance = Instantiate(orientationPromptPrefab); - DontDestroyOnLoad(_promptInstance); - } - } - - private void HandleOrientationCorrect() - { - if (_promptInstance != null) - { - Destroy(_promptInstance); - _promptInstance = null; - } - if (_orientationCheckCoroutine != null) - { - StopCoroutine(_orientationCheckCoroutine); - _orientationCheckCoroutine = null; - } - - InputManager.Instance.SetInputMode(InputMode.GameAndUI); - } - - private void CleanupPromptAndCoroutine() - { - if (_promptInstance != null) - { - Destroy(_promptInstance); - _promptInstance = null; - } - - if (_orientationCheckCoroutine != null) - { - StopCoroutine(_orientationCheckCoroutine); - _orientationCheckCoroutine = null; - } - - if (_continuousOrientationCheckCoroutine != null) - { - StopCoroutine(_continuousOrientationCheckCoroutine); - _continuousOrientationCheckCoroutine = null; - } - } - - private bool IsMainMenuScene(Scene scene) - { - // Adjust this logic if you have a different main menu scene name - return scene.name == "Main Menu" || scene.name == "MainMenu"; - } - + void OnDestroy() { SceneManager.sceneLoaded -= OnSceneLoaded; - OnOrientationCorrect -= HandleOrientationCorrect; - CleanupPromptAndCoroutine(); + } + + /// + /// Forces the game into landscape mode, allowing both LandscapeLeft and LandscapeRight. + /// + public static IEnumerator ForceLandscape() + { + // If we're already in a landscape orientation, nothing to do. + bool currentlyLandscape = Screen.orientation == ScreenOrientation.LandscapeLeft + || Screen.orientation == ScreenOrientation.LandscapeRight; + if (!currentlyLandscape) + { + // Lock it to portrait and allow the device to orient itself + Logging.Debug($"[SceneOrientationEnforcer] Actually forcing Portrait from previous: {Screen.orientation}"); + Screen.orientation = ScreenOrientation.LandscapeRight; + } + else + { + Logging.Debug($"[SceneOrientationEnforcer] Skipping Landscape enforcement, device already in: {Screen.orientation}"); + } + + yield return null; + + // Enable only landscape autorotations + Screen.autorotateToPortrait = false; + Screen.autorotateToPortraitUpsideDown = false; + Screen.autorotateToLandscapeLeft = true; + Screen.autorotateToLandscapeRight = true; + + yield return null; + + // Allow device to auto-rotate to correct landscape orientation + Screen.orientation = ScreenOrientation.AutoRotation; } - void OnApplicationQuit() + /// + /// Forces the game into portrait mode, allowing both Portrait and PortraitUpsideDown. + /// + public static IEnumerator ForcePortrait() { - _isQuitting = true; + // If we're already in a portrait orientation, nothing to do. + bool currentlyPortrait = Screen.orientation == ScreenOrientation.Portrait + || Screen.orientation == ScreenOrientation.PortraitUpsideDown; + if (!currentlyPortrait) + { + // Lock it to portrait and allow the device to orient itself + Logging.Debug($"[SceneOrientationEnforcer] Actually forcing Portrait from previous: {Screen.orientation}"); + Screen.orientation = ScreenOrientation.PortraitUpsideDown; + } + else + { + Logging.Debug($"[SceneOrientationEnforcer] Skipping Portrait enforcement, device already in: {Screen.orientation}"); + } + + yield return null; + + // Enable only portrait autorotations + Screen.autorotateToPortrait = true; + Screen.autorotateToPortraitUpsideDown = true; + Screen.autorotateToLandscapeLeft = false; + Screen.autorotateToLandscapeRight = false; + + yield return null; + + // Allow device to auto-rotate to correct portrait orientation + Screen.orientation = ScreenOrientation.AutoRotation; } } } diff --git a/Assets/Scripts/Minigames/DivingForPictures/DivingGameManager.cs b/Assets/Scripts/Minigames/DivingForPictures/DivingGameManager.cs index 01c2fcfa..e013d69a 100644 --- a/Assets/Scripts/Minigames/DivingForPictures/DivingGameManager.cs +++ b/Assets/Scripts/Minigames/DivingForPictures/DivingGameManager.cs @@ -13,7 +13,6 @@ using UI.Core; using UnityEngine; using UnityEngine.Events; using UnityEngine.Playables; -using Utility; namespace Minigames.DivingForPictures { @@ -169,26 +168,7 @@ namespace Minigames.DivingForPictures GameManager.Instance.RegisterPausableComponent(this); } - // Subscribe to SceneOrientationEnforcer's event - if (SceneOrientationEnforcer.Instance != null) - { - // TODO: This is a bit of a hack to make sure the game is initialized after the orientation is correct - SceneOrientationEnforcer.Instance.OnOrientationCorrect += InitializeGame; - SceneOrientationEnforcer.Instance.OnOrientationIncorrect += Pause; - - // If orientation is already correct, initialize right away - // This prevents issues if the orientation was already correct before subscription - if (SceneOrientationEnforcer.Instance.IsOrientationCorrect()) - { - InitializeGame(); - } - } - else - { - Logging.Warning("[DivingGameManager] SceneOrientationEnforcer not found. Initializing game immediately."); - InitializeGame(); - } - + InitializeGame(); CinematicsManager.Instance.OnCinematicStopped += EndGame; } @@ -197,12 +177,6 @@ namespace Minigames.DivingForPictures // Unsubscribe from events when the manager is destroyed PlayerCollisionBehavior.OnDamageTaken -= OnPlayerDamageTaken; - if (SceneOrientationEnforcer.Instance != null) - { - SceneOrientationEnforcer.Instance.OnOrientationCorrect -= InitializeGame; - SceneOrientationEnforcer.Instance.OnOrientationIncorrect -= Pause; - } - // Unregister from GameManager if (GameManager.Instance != null) { diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset index d5bfaca8..d35a5c3d 100644 --- a/ProjectSettings/ProjectSettings.asset +++ b/ProjectSettings/ProjectSettings.asset @@ -8,7 +8,7 @@ PlayerSettings: AndroidProfiler: 0 AndroidFilterTouchesWhenObscured: 0 AndroidEnableSustainedPerformanceMode: 0 - defaultScreenOrientation: 4 + defaultScreenOrientation: 2 targetDevice: 2 useOnDemandResources: 0 accelerometerFrequency: 60