Code/k/TransitionCamera.cs
namespace Sandbox.k;

[Title( nameof(TransitionCamera))]
public class TransitionCamera : Component
{
	[RequireComponent] private CameraComponent _camera { get; set; }

	private string _initialCamera;
	private CameraComponent _targetCamera;
	private float _transitionTime;
	private TimeSince _transitionTimer;

	protected override void OnEnabled()
	{
		base.OnEnabled();
		_camera.Priority = 10;
	}

	public void CopyCamera( CameraComponent cameraComponent )
	{
		_initialCamera = cameraComponent.GameObject.Name;
		_camera.WorldPosition = cameraComponent.WorldPosition;
		_camera.WorldRotation = cameraComponent.WorldRotation;
		_camera.FieldOfView = cameraComponent.FieldOfView;
	}
	
	public void SetTargetCamera( CameraComponent cameraComponent, float transitionTime )
	{
		_targetCamera = cameraComponent;
		_transitionTime = transitionTime;
		_transitionTimer = 0;
	}
	
	protected override void OnUpdate()
	{
		base.OnUpdate();
		if ( _targetCamera == null )
		{
			LookForTarget();
			return;
		}
		if ( _transitionTimer >= _transitionTime )
		{
			DestroyGameObject();
			return;
		}
		
		var lerp = _transitionTimer / _transitionTime;
		WorldPosition = Vector3.Lerp( _camera.WorldPosition, _targetCamera.WorldPosition, lerp );
		WorldRotation = Rotation.Slerp( _camera.WorldRotation, _targetCamera.WorldRotation, lerp );
		_camera.FieldOfView = MathX.Lerp( _camera.FieldOfView, _targetCamera.FieldOfView, lerp );
	}

	private void LookForTarget()
	{
		var virtualCameras = Scene.GetAllComponents<VirtualCamera>();
		foreach ( var virtualCamera in virtualCameras )
		{
			if ( virtualCamera.GameObject.Name == _initialCamera )
			{
				continue;
			}
				
			SetTargetCamera( virtualCamera.Camera, 1f );
			return;
		}
	}
}