using UnityEngine; using UnityEngine.Rendering.Universal; using AibisDream.Kit; using AibisDream.Utility; namespace AibisDream.Framework { [RequireComponent(typeof(Camera))] public class CameraAspectAdapter : MonoBehaviour { private Camera _targetCamera; private Vector2Int _lastScreenSize; private Rect _targetRect; private IUnRegister _resolutionChangeUnRegister; private void Awake() { _targetCamera = GetComponent(); } private void Start() { _lastScreenSize = new Vector2Int(Screen.width, Screen.height); CalculateTargetRect(); ApplyToAllCameras(); } private void OnEnable() { _resolutionChangeUnRegister = EnumEventSystem.Global.Register( SettingChangeEvent.DisplayChanged, OnResolutionChanged); } private void OnDisable() { _resolutionChangeUnRegister?.UnRegister(); } private void LateUpdate() { bool screenChanged = Screen.width != _lastScreenSize.x || Screen.height != _lastScreenSize.y; if (screenChanged) { _lastScreenSize = new Vector2Int(Screen.width, Screen.height); CalculateTargetRect(); } ApplyToAllCameras(); } public void Refresh(bool reset = false) { if (_targetCamera == null) return; if (reset) { _targetRect = new Rect(0, 0, 1, 1); } else { CalculateTargetRect(); } ApplyToAllCameras(); } private void OnResolutionChanged() { _lastScreenSize = new Vector2Int(Screen.width, Screen.height); CalculateTargetRect(); ApplyToAllCameras(); } private void CalculateTargetRect() { const float Epsilon = 0.0001f; float windowAspect = (float)Screen.width / Screen.height; float targetAspect = ConstRef.TargetAspect; float diff = windowAspect - targetAspect; if (Mathf.Abs(diff) < Epsilon) { _targetRect = new Rect(0, 0, 1, 1); } else if (diff < 0) { float scaleHeight = windowAspect / targetAspect; _targetRect = new Rect(0, (1f - scaleHeight) / 2f, 1f, scaleHeight); } else { float scaleWidth = targetAspect / windowAspect; _targetRect = new Rect((1f - scaleWidth) / 2f, 0, scaleWidth, 1f); } } private void ApplyToAllCameras() { ApplyRect(_targetCamera); if (_targetCamera != null && _targetCamera.TryGetComponent(out UniversalAdditionalCameraData cameraData)) { foreach (var overlay in cameraData.cameraStack) { if (overlay != null) ApplyRect(overlay); } } } private void ApplyRect(Camera camera) { if (camera == null) return; const float Epsilon = 0.0001f; Rect current = camera.rect; if (Mathf.Abs(current.x - _targetRect.x) > Epsilon || Mathf.Abs(current.y - _targetRect.y) > Epsilon || Mathf.Abs(current.width - _targetRect.width) > Epsilon || Mathf.Abs(current.height - _targetRect.height) > Epsilon) { camera.rect = _targetRect; } } } }