Update the rotation enforcement to automatically lock device into
desired orientation.
This commit is contained in:
@@ -1,46 +1,37 @@
|
|||||||
using UnityEngine;
|
using System;
|
||||||
using UnityEngine.SceneManagement;
|
using System.Collections;
|
||||||
using System;
|
using Bootstrap;
|
||||||
using Input;
|
using Input;
|
||||||
using Settings;
|
using Settings;
|
||||||
using System.Collections;
|
using UnityEngine;
|
||||||
using Minigames.DivingForPictures;
|
using UnityEngine.SceneManagement;
|
||||||
using Bootstrap;
|
|
||||||
using Core;
|
|
||||||
|
|
||||||
namespace Utility
|
namespace Core
|
||||||
{
|
{
|
||||||
public class SceneOrientationEnforcer : MonoBehaviour
|
public class SceneOrientationEnforcer : MonoBehaviour
|
||||||
{
|
{
|
||||||
|
// Singleton instance
|
||||||
private static SceneOrientationEnforcer _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;
|
public static SceneOrientationEnforcer Instance => _instance;
|
||||||
|
|
||||||
[Header("Config")]
|
[Header("Config")]
|
||||||
public SceneOrientationConfig orientationConfig;
|
public SceneOrientationConfig orientationConfig;
|
||||||
public GameObject orientationPromptPrefab;
|
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()
|
void Awake()
|
||||||
{
|
{
|
||||||
_instance = this;
|
_instance = this;
|
||||||
OnOrientationCorrect += HandleOrientationCorrect;
|
|
||||||
|
|
||||||
// Register for post-boot initialization
|
// Register for post-boot initialization
|
||||||
BootCompletionService.RegisterInitAction(InitializePostBoot);
|
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()
|
private void InitializePostBoot()
|
||||||
@@ -50,180 +41,118 @@ namespace Utility
|
|||||||
|
|
||||||
// Subscribe to sceneLoaded event
|
// Subscribe to sceneLoaded event
|
||||||
SceneManager.sceneLoaded += OnSceneLoaded;
|
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)
|
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
|
||||||
{
|
{
|
||||||
// Clean up any previous prompt/coroutine
|
// Determine desired orientation for this scene
|
||||||
CleanupPromptAndCoroutine();
|
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;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_isDivingMinigame = IsDivingMinigameScene(scene);
|
if (orientationConfig != null)
|
||||||
|
|
||||||
_requiredOrientation = orientationConfig != null ? orientationConfig.GetRequirementForScene(scene.name) : ScreenOrientationRequirement.NotApplicable;
|
|
||||||
_orientationCorrect = IsOrientationCorrect();
|
|
||||||
|
|
||||||
if (!_orientationCorrect)
|
|
||||||
{
|
{
|
||||||
InputManager.Instance.SetInputMode(InputMode.UI);
|
requirement = orientationConfig.GetRequirementForScene(sceneName);
|
||||||
ShowPrompt();
|
|
||||||
// If this is the diving minigame, start continuous orientation checking
|
|
||||||
if (_isDivingMinigame)
|
|
||||||
{
|
|
||||||
_continuousOrientationCheckCoroutine = StartCoroutine(ContinuousOrientationCheckRoutine());
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_orientationCheckCoroutine = StartCoroutine(OrientationCheckRoutine());
|
Logging.Debug($"[SceneOrientationEnforcer] No orientationConfig assigned. Defaulting to Landscape for scene '{sceneName}'");
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_orientationCorrect = true;
|
|
||||||
OnOrientationCorrect?.Invoke();
|
|
||||||
|
|
||||||
// If this is the diving minigame, start continuous orientation checking
|
|
||||||
if (_isDivingMinigame)
|
|
||||||
{
|
|
||||||
_continuousOrientationCheckCoroutine = StartCoroutine(ContinuousOrientationCheckRoutine());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private System.Collections.IEnumerator OrientationCheckRoutine()
|
switch (requirement)
|
||||||
{
|
{
|
||||||
while (!IsOrientationCorrect())
|
case ScreenOrientationRequirement.Portrait:
|
||||||
{
|
Logging.Debug($"[SceneOrientationEnforcer] Forcing Portrait for scene '{sceneName}'");
|
||||||
yield return new WaitForSeconds(0.5f);
|
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()
|
void OnDestroy()
|
||||||
{
|
{
|
||||||
SceneManager.sceneLoaded -= OnSceneLoaded;
|
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;
|
||||||
using UnityEngine.Events;
|
using UnityEngine.Events;
|
||||||
using UnityEngine.Playables;
|
using UnityEngine.Playables;
|
||||||
using Utility;
|
|
||||||
|
|
||||||
namespace Minigames.DivingForPictures
|
namespace Minigames.DivingForPictures
|
||||||
{
|
{
|
||||||
@@ -169,26 +168,7 @@ namespace Minigames.DivingForPictures
|
|||||||
GameManager.Instance.RegisterPausableComponent(this);
|
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();
|
InitializeGame();
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Logging.Warning("[DivingGameManager] SceneOrientationEnforcer not found. Initializing game immediately.");
|
|
||||||
InitializeGame();
|
|
||||||
}
|
|
||||||
|
|
||||||
CinematicsManager.Instance.OnCinematicStopped += EndGame;
|
CinematicsManager.Instance.OnCinematicStopped += EndGame;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,12 +177,6 @@ namespace Minigames.DivingForPictures
|
|||||||
// Unsubscribe from events when the manager is destroyed
|
// Unsubscribe from events when the manager is destroyed
|
||||||
PlayerCollisionBehavior.OnDamageTaken -= OnPlayerDamageTaken;
|
PlayerCollisionBehavior.OnDamageTaken -= OnPlayerDamageTaken;
|
||||||
|
|
||||||
if (SceneOrientationEnforcer.Instance != null)
|
|
||||||
{
|
|
||||||
SceneOrientationEnforcer.Instance.OnOrientationCorrect -= InitializeGame;
|
|
||||||
SceneOrientationEnforcer.Instance.OnOrientationIncorrect -= Pause;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unregister from GameManager
|
// Unregister from GameManager
|
||||||
if (GameManager.Instance != null)
|
if (GameManager.Instance != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ PlayerSettings:
|
|||||||
AndroidProfiler: 0
|
AndroidProfiler: 0
|
||||||
AndroidFilterTouchesWhenObscured: 0
|
AndroidFilterTouchesWhenObscured: 0
|
||||||
AndroidEnableSustainedPerformanceMode: 0
|
AndroidEnableSustainedPerformanceMode: 0
|
||||||
defaultScreenOrientation: 4
|
defaultScreenOrientation: 2
|
||||||
targetDevice: 2
|
targetDevice: 2
|
||||||
useOnDemandResources: 0
|
useOnDemandResources: 0
|
||||||
accelerometerFrequency: 60
|
accelerometerFrequency: 60
|
||||||
|
|||||||
Reference in New Issue
Block a user