using System;
using System.Collections;
using AdaptUI;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
namespace AppUI
{
///
/// Entry / Login 竖屏,进 Home 横屏。真机用 Screen.orientation;编辑器用 Game 视图 1170×2532 ↔ 2532×1170。
///
public static class ScreenOrientationHelper
{
public const int PortraitWidth = 1170;
public const int PortraitHeight = 2532;
public const int LandscapeWidth = 2532;
public const int LandscapeHeight = 1170;
const float BlackFadeInDuration = 0.2f;
const float BlackFadeOutDuration = 0.45f;
const float BlackHoldBeforeFadeOut = 0.08f;
static Canvas _blackCanvas;
static CanvasGroup _blackCanvasGroup;
static Coroutine _transitionCoroutine;
public static void ApplyPortraitForBoot()
{
Screen.orientation = ScreenOrientation.Portrait;
Screen.autorotateToLandscapeRight = false;
Screen.autorotateToLandscapeLeft = false;
Screen.autorotateToPortrait = false;
Screen.autorotateToPortraitUpsideDown = false;
}
public static IEnumerator SwitchToPortraitEditorAndWait(float maxWaitSeconds = 2f)
{
#if UNITY_EDITOR
if (!ScreenOrientationEditorSettings.IsEnabled)
yield break;
yield return GameViewSizeHelper.EditorApplyPortraitCoroutine(maxWaitSeconds);
#else
yield break;
#endif
}
public static IEnumerator SwitchToLandscapeAndWait(float maxWaitSeconds = 2f)
{
yield return FadeBlackOverlay(1f, BlackFadeInDuration);
Screen.autorotateToLandscapeRight = true;
Screen.autorotateToLandscapeLeft = true;
Screen.autorotateToPortrait = false;
Screen.autorotateToPortraitUpsideDown = false;
Screen.orientation = ScreenOrientation.LandscapeLeft;
#if UNITY_EDITOR
if (ScreenOrientationEditorSettings.IsEnabled)
yield return GameViewSizeHelper.EditorSwapOrientationCoroutine(true, maxWaitSeconds);
#else
float elapsed = 0f;
while (elapsed < maxWaitSeconds)
{
if (Screen.width >= Screen.height)
break;
elapsed += Time.unscaledDeltaTime;
yield return null;
}
yield return null;
#endif
DeviceTypeHelper.InvalidateDeviceTypeCache();
}
public static IEnumerator FadeOutBlackOverlay(float duration = BlackFadeOutDuration)
{
EnsureBlackOverlay();
if (_blackCanvasGroup == null)
yield break;
_blackCanvas.gameObject.SetActive(true);
if (_blackCanvasGroup.alpha < 0.01f)
yield break;
yield return FadeBlackOverlay(0f, duration);
}
///
/// 竖屏切横屏 → 黑屏 → 加载场景 → 淡出。协程跑在 DontDestroyOnLoad 上,避免 LoadScene 销毁原场景后无法淡出。
///
public static void SwitchToLandscapeAndLoadScene(string sceneName)
{
var host = CoroutineRunnerHost.Instance;
if (_transitionCoroutine != null)
host.StopCoroutine(_transitionCoroutine);
_transitionCoroutine = host.StartCoroutine(SwitchToLandscapeAndLoadSceneCoroutine(sceneName));
}
///
/// 异步激活场景后淡出黑屏(Entry 等场景会在激活后被卸载,须提前在 DontDestroyOnLoad 上调度)。
///
public static void ScheduleFadeOutBlackOverlayAfterSceneLoad(string expectedSceneName)
{
var host = CoroutineRunnerHost.Instance;
if (_transitionCoroutine != null)
host.StopCoroutine(_transitionCoroutine);
_transitionCoroutine = host.StartCoroutine(FadeOutAfterSceneLoadCoroutine(expectedSceneName));
}
static IEnumerator SwitchToLandscapeAndLoadSceneCoroutine(string sceneName)
{
yield return SwitchToLandscapeAndWait();
SceneManager.LoadScene(sceneName, LoadSceneMode.Single);
yield return WaitSceneReadyForFadeOut(sceneName);
yield return FadeOutBlackOverlay();
_transitionCoroutine = null;
}
static IEnumerator FadeOutAfterSceneLoadCoroutine(string expectedSceneName)
{
yield return WaitSceneReadyForFadeOut(expectedSceneName);
yield return FadeOutBlackOverlay();
_transitionCoroutine = null;
}
static IEnumerator WaitSceneReadyForFadeOut(string expectedSceneName)
{
while (SceneManager.GetActiveScene().name != expectedSceneName)
yield return null;
float holdUntil = Time.unscaledTime + BlackHoldBeforeFadeOut;
while (Time.unscaledTime < holdUntil)
yield return null;
yield return new WaitForEndOfFrame();
yield return new WaitForEndOfFrame();
EnsureBlackOverlay();
_blackCanvas.gameObject.SetActive(true);
_blackCanvasGroup.alpha = 1f;
_blackCanvasGroup.blocksRaycasts = true;
}
static void EnsureBlackOverlay()
{
if (_blackCanvas != null)
return;
var go = new GameObject("[OrientationBlackOverlay]");
UnityEngine.Object.DontDestroyOnLoad(go);
_blackCanvas = go.AddComponent