Example/Complex/PlayerWalkControllerComplex.Camera.cs
using Sandbox;
namespace XMovement;

public partial class PlayerWalkControllerComplex : Component
{
	[Property, Group( "Camera" )]
	public bool UseSceneCamera { get; set; } = true;

	[Property, Group( "Camera" ), Change( "SetupCamera" )]
	public CameraModes CameraMode { get; set; } = CameraModes.ThirdPerson;
	public enum CameraModes
	{
		FirstPerson,
		ThirdPerson,
		Manual,
	}

	private bool _isfirstperson => CameraMode == CameraModes.FirstPerson && !UseSceneCamera;
	private bool _isthirdperson => CameraMode == CameraModes.ThirdPerson && !UseSceneCamera;
	private bool _ismanual => CameraMode == CameraModes.Manual && !UseSceneCamera;
	private bool _canToggleCamera => CameraMode != CameraModes.Manual && !UseSceneCamera;

	[Property, Group( "Camera" ), ShowIf( "_ismanual", true )]
	public CameraComponent Camera { get; set; }


	[Property, Group( "Camera" ), ShowIf( "_isfirstperson", true ), Change( "SetupCamera" )]
	public bool PlayerShadowsOnly { get; set; } = true;


	[Property, Group( "Camera" ), ShowIf( "_isfirstperson", true ), Change( "SetupCamera" )]
	public Vector3 FirstPersonOffset { get; set; } = new Vector3( 0, 0, 0 );


	[Property, Group( "Camera" ), ShowIf( "_isthirdperson", true ), Change( "SetupCamera" )]
	public Vector3 ThirdPersonOffset { get; set; } = new Vector3( -180, 0, 0 );

	[Property, InputAction, Group( "Camera" ), ShowIf( "_canToggleCamera", true )]
	public string CameraToggleAction { get; set; } = "View";

	/// <summary>
	/// If true, the camera will apply user preferences such as FOV and other settings.
	/// </summary>
	[Property, Group( "Camera" )]
	public bool ApplyUserPreferences { get; set; } = true;

	public virtual void OnCameraModeChanged() { }
	public void SetupCamera()
	{
		OnCameraModeChanged();
		if ( UseSceneCamera )
		{
			if ( !Game.IsPlaying ) return;
			if ( Scene.Camera.IsValid() ) Camera = Scene.Camera;
		}
		if ( CameraMode != CameraModes.Manual && !Camera.IsValid() )
		{
			var cameraobj = Scene.CreateObject();
			cameraobj.SetParent( Head );
			cameraobj.Name = "Camera";
			Camera = cameraobj.AddComponent<CameraComponent>();
			Camera.Enabled = false;
			Camera.TargetEye = StereoTargetEye.Both;
		}
		if ( CameraMode == CameraModes.FirstPerson )
		{
			Camera.LocalPosition = FirstPersonOffset;
		}
		if ( CameraMode == CameraModes.ThirdPerson )
		{
			Camera.LocalPosition = ThirdPersonOffset;
		}
		if ( Game.IsPlaying )
		{
			if ( !IsProxy ) Camera.Enabled = true;
			UpdateBodyVisibility();
			if ( ApplyUserPreferences )
			{
				Camera.FieldOfView = Preferences.FieldOfView;
			}
		}
	}

	public void UpdateCamera()
	{
		if ( UseSceneCamera && !Camera.IsValid() )
		{
			if ( Scene.Camera.IsValid() ) Camera = Scene.Camera;
		}
		if ( CameraMode == CameraModes.ThirdPerson )
		{
			var start = Head.WorldPosition;
			var end = start + (ThirdPersonOffset * Head.WorldRotation);
			var tr = Scene.Trace.Ray( start, end ).IgnoreDynamic().Radius( 6f ).Run();
			var camPos = tr.EndPosition;

			if ( UseSceneCamera )
			{
				// Scene camera has no parent — drive world pos/rot directly
				Camera.WorldPosition = camPos;
				Camera.WorldRotation = Rotation.LookAt( start - camPos, Vector3.Up );
			}
			else
			{
				// Owned camera is parented to Head — use local position
				Camera.LocalPosition = ThirdPersonOffset * tr.Fraction;
			}
		}
		if ( CameraMode == CameraModes.FirstPerson )
		{
			if ( UseSceneCamera )
			{
				Camera.WorldPosition = Head.WorldPosition + (FirstPersonOffset * Head.WorldRotation);
				Camera.WorldRotation = Head.WorldRotation;
			}
		}
		if ( Input.Pressed( CameraToggleAction ) )
		{
			if ( CameraMode == CameraModes.ThirdPerson ) CameraMode = CameraModes.FirstPerson;
			else if ( CameraMode == CameraModes.FirstPerson ) CameraMode = CameraModes.ThirdPerson;
		}
	}

	public void UpdateBodyVisibility()
	{
		if ( IsProxy )
		{
			foreach ( var mdlrenderer in Body.Components.GetAll<ModelRenderer>( FindMode.EverythingInSelfAndChildren ) )
			{
				mdlrenderer.RenderType = Sandbox.ModelRenderer.ShadowRenderType.On;
			}
			return;
		}
		if ( CameraMode == CameraModes.FirstPerson )
		{
			foreach ( var mdlrenderer in Body.Components.GetAll<ModelRenderer>( FindMode.EverythingInSelfAndChildren ) )
			{
				mdlrenderer.RenderType = PlayerShadowsOnly ? Sandbox.ModelRenderer.ShadowRenderType.ShadowsOnly : Sandbox.ModelRenderer.ShadowRenderType.On;
			}
		}
		if ( CameraMode == CameraModes.ThirdPerson )
		{
			if ( BodyModelRenderer.RenderType == Sandbox.ModelRenderer.ShadowRenderType.ShadowsOnly && PlayerShadowsOnly )
			{
				foreach ( var mdlrenderer in Body.Components.GetAll<ModelRenderer>( FindMode.EverythingInSelfAndChildren ) )
				{
					mdlrenderer.RenderType = Sandbox.ModelRenderer.ShadowRenderType.On;
				}
			}
		}
	}
}