Editor/Drivers/SyntheticAimDriver.cs

Editor utility that simulates player aim for testing. It sets global input AnalogLook or MouseDelta for 'delta' mode, and for 'angles' mode clamps pitch, sets AnalogLook, updates the first PlayerController.EyeAngles or, if none, a CameraComponent.WorldRotation, then returns a ToolOutcome with details.

Native Interop
#nullable enable
using System;
using System.Linq;
using Sandbox;

namespace Editor.Mcp
{
	internal static class SyntheticAimDriver
	{
		public static ToolOutcome<object> SimulateAim( string mode = "angles", float pitch = 0f, float yaw = 0f, float roll = 0f, float deltaX = 0f, float deltaY = 0f )
		{
			if ( !Game.IsPlaying )
			{
				return ToolOutcome<object>.Failure( null, ToolStatus.Unavailable, "aim.playmode_inactive", "Play mode must be active to simulate aim." );
			}

			var normMode = mode.ToLowerInvariant();
			if ( normMode == "delta" )
			{
				Sandbox.Input.MouseDelta = new Vector2( deltaX, deltaY );
				Sandbox.Input.AnalogLook = new Angles( deltaY, -deltaX, 0 );
				return ToolOutcome<object>.Ready( new
				{
					Mode = "delta",
					DeltaX = deltaX,
					DeltaY = deltaY,
					AnalogLook = Sandbox.Input.AnalogLook,
					MouseDelta = Sandbox.Input.MouseDelta
				} );
			}

			var clampedPitch = Math.Clamp( pitch, -89f, 89f );
			var targetAngles = new Angles( clampedPitch, yaw, roll );

			// 1. Set global engine AnalogLook
			Sandbox.Input.AnalogLook = targetAngles;

			// 2. Update any active player controller in scene
			string? targetFound = null;
			var players = Game.ActiveScene?.GetAllComponents<PlayerController>();
			var target = players?.FirstOrDefault();
			if ( target != null )
			{
				target.EyeAngles = targetAngles;
				targetFound = target.GameObject.Name;
			}

			// 3. Also update CameraComponent if no PlayerController handled it
			var camera = Game.ActiveScene?.GetAllComponents<CameraComponent>()?.FirstOrDefault();
			if ( camera != null && target == null )
			{
				camera.WorldRotation = targetAngles.ToRotation();
				targetFound = camera.GameObject.Name;
			}

			return ToolOutcome<object>.Ready( new
			{
				Mode = "angles",
				TargetGameObject = targetFound,
				AppliedAngles = new { Pitch = clampedPitch, Yaw = yaw, Roll = roll },
				AimForward = targetAngles.Forward
			} );
		}
	}
}