Files
aibis-dream/Assets/Scripts/Framework/OtherKit/CameraAspectAdapter.cs
T

130 lines
3.7 KiB
C#

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<Camera>();
}
private void Start()
{
_lastScreenSize = new Vector2Int(Screen.width, Screen.height);
CalculateTargetRect();
ApplyToAllCameras();
}
private void OnEnable()
{
_resolutionChangeUnRegister = EnumEventSystem.Global.Register(
GameLoopEnum.ScreenResolutionChanged, 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;
}
}
}
}