Camera/GuestCamera.cs
namespace HC3;

public sealed class GuestCamera : Component
{
	public static GuestCamera Instance { get; private set; }

	[Property] public CameraComponent Camera { get; set; }

	public Guest Guest { get; private set; }

	protected override void OnAwake()
	{
		base.OnAwake();

		Instance = this;

		StopViewing();
	}

	public void ToggleViewing( Guest guest )
	{
		if ( Guest == guest )
		{
			StopViewing();
		}
		else
		{
			StartViewing( guest );
		}
	}

	public void StartViewing( Guest guest )
	{
		StopViewing();

		if ( !guest.IsValid() )
			return;

		var mainCamera = CameraPanning.Instance?.Camera;
		if ( mainCamera.IsValid() )
			mainCamera.GameObject.Enabled = false;

		Camera.GameObject.Enabled = true;

		Guest = guest;
		Guest.Body.RenderType = ModelRenderer.ShadowRenderType.ShadowsOnly;

		target = Angles.Zero;
	}

	public void StopViewing()
	{
		Camera.GameObject.Enabled = false;

		var mainCamera = CameraPanning.Instance?.Camera;
		if ( mainCamera.IsValid() )
			mainCamera.GameObject.Enabled = true;

		if ( !Guest.IsValid() )
			return;

		Guest.Body.RenderType = ModelRenderer.ShadowRenderType.On;
		Guest = null;
	}

	Angles target;

	protected override void OnUpdate()
	{
		base.OnUpdate();

		if ( !Guest.IsValid() )
		{
			StopViewing();
			return;
		}

		target.yaw += Input.AnalogLook.yaw;
		target.pitch += Input.AnalogLook.pitch;

		Camera.WorldPosition = Guest.WorldPosition + new Vector3( 0, 0, 30 ) * Guest.WorldScale;
		Camera.WorldRotation = Rotation.Lerp( Camera.WorldRotation, Guest.WorldRotation * target, Time.Delta * 5f );

		Camera.FovAxis = CameraComponent.Axis.Vertical;
		Camera.FieldOfView = Screen.CreateVerticalFieldOfView( Preferences.FieldOfView, 9.0f / 16.0f );
	}
}