Update the rotation enforcement to automatically lock device into
desired orientation.
This commit is contained in:
@@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// Singleton instance of the SceneOrientationEnforcer. No longer creates an instance if one doesn't exist.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the current device orientation matches the required orientation for the scene
|
||||
/// </summary>
|
||||
/// <returns>True if the orientation is correct, false otherwise</returns>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the current scene is the diving minigame scene
|
||||
/// </summary>
|
||||
/// <returns>True if the scene is "DivingForPictures", false otherwise</returns>
|
||||
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))
|
||||
if (sceneName.ToLower().Contains("bootstrap"))
|
||||
{
|
||||
// Bootstrap being loaded additively, don't do anything
|
||||
Logging.Debug($"[SceneOrientationEnforcer] Detected bootstrapped scene: '{sceneName}'. Skipping orientation enforcement.");
|
||||
return;
|
||||
}
|
||||
|
||||
_isDivingMinigame = IsDivingMinigameScene(scene);
|
||||
|
||||
_requiredOrientation = orientationConfig != null ? orientationConfig.GetRequirementForScene(scene.name) : ScreenOrientationRequirement.NotApplicable;
|
||||
_orientationCorrect = IsOrientationCorrect();
|
||||
|
||||
if (!_orientationCorrect)
|
||||
if (orientationConfig != null)
|
||||
{
|
||||
InputManager.Instance.SetInputMode(InputMode.UI);
|
||||
ShowPrompt();
|
||||
// If this is the diving minigame, start continuous orientation checking
|
||||
if (_isDivingMinigame)
|
||||
{
|
||||
_continuousOrientationCheckCoroutine = StartCoroutine(ContinuousOrientationCheckRoutine());
|
||||
requirement = orientationConfig.GetRequirementForScene(sceneName);
|
||||
}
|
||||
else
|
||||
{
|
||||
_orientationCheckCoroutine = StartCoroutine(OrientationCheckRoutine());
|
||||
}
|
||||
}
|
||||
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}'");
|
||||
}
|
||||
|
||||
private System.Collections.IEnumerator OrientationCheckRoutine()
|
||||
switch (requirement)
|
||||
{
|
||||
while (!IsOrientationCorrect())
|
||||
{
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
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;
|
||||
}
|
||||
_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();
|
||||
}
|
||||
|
||||
void OnApplicationQuit()
|
||||
/// <summary>
|
||||
/// Forces the game into landscape mode, allowing both LandscapeLeft and LandscapeRight.
|
||||
/// </summary>
|
||||
public static IEnumerator ForceLandscape()
|
||||
{
|
||||
_isQuitting = true;
|
||||
// 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Forces the game into portrait mode, allowing both Portrait and PortraitUpsideDown.
|
||||
/// </summary>
|
||||
public static IEnumerator ForcePortrait()
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@ PlayerSettings:
|
||||
AndroidProfiler: 0
|
||||
AndroidFilterTouchesWhenObscured: 0
|
||||
AndroidEnableSustainedPerformanceMode: 0
|
||||
defaultScreenOrientation: 4
|
||||
defaultScreenOrientation: 2
|
||||
targetDevice: 2
|
||||
useOnDemandResources: 0
|
||||
accelerometerFrequency: 60
|
||||
|
||||
Reference in New Issue
Block a user