using Sandbox.Engine; using Sandbox.VR; namespace Sandbox; /// /// Allows querying of player button presses and other inputs. /// public static partial class Input { /// /// Virtual Reality specific input data. /// public static VRInput VR => VRInput.Current; /// /// Movement delta from the mouse. /// public static Vector2 MouseDelta { get => Suppressed ? default : CurrentContext.MouseDelta; set => CurrentContext.MouseDelta = value; } /// /// The state of the mouse wheel. /// public static Vector2 MouseWheel { get => Suppressed ? default : CurrentContext.MouseWheel; set => CurrentContext.MouseWheel = value; } /// /// True if the mouse cursor is visible (using UI etc) /// public static bool MouseCursorVisible { get => CurrentContext.MouseCursorVisible; } static Angles _analogLook; /// /// Analog look value from the default input device. This is scaled by Preferences.Sensitivity - so you don't need to scale it afterwards. /// [ActionGraphNode( "input.analog.look" ), Category( "Input" ), Icon( "gamepad" )] public static Angles AnalogLook { get => Suppressed ? default : _analogLook; set => _analogLook = value; } static Vector3 _analogMove; /// /// Analog move value from the default input device. /// [ActionGraphNode( "input.analog.move" ), Category( "Input" ), Icon( "gamepad" )] public static Vector3 AnalogMove { get => Suppressed ? default : _analogMove; set => _analogMove = value; } internal static void AddMouseMovement( Vector2 delta ) { foreach ( var e in Contexts ) { e.AccumMouseDelta += delta; } } internal static void AddMouseWheel( Vector2 delta ) { foreach ( var e in Contexts ) { e.AccumMouseWheel += delta; } } /// /// Called multiple times between ticks. /// internal static void Process() { // Reset suppression flag Suppressed = false; // Flip all controller input contexts once a frame foreach ( var controller in Controller.All ) { controller.InputContext?.Flip(); } // // Setup // CurrentContext.MouseCursorVisible = InputRouter.MouseCursorVisible; // this is all kind of how it did it in CInputService::HandleAnalogValueChange var mouseSensitivity = Preferences.Sensitivity * 10.0f; var halfDim = MathF.Max( Screen.Width, Screen.Height ) * 0.5f; if ( halfDim < 1.0f ) halfDim = 1.0f; AnalogLook = new( (MouseDelta.y / halfDim) * mouseSensitivity, (-MouseDelta.x / halfDim) * mouseSensitivity, 0 ); if ( MouseCursorVisible ) { AnalogLook = default; } Actions = CurrentContext.ActionsCurrent; LastActions = CurrentContext.ActionsPrevious; if ( Preferences.InvertMousePitch ) AnalogLook = AnalogLook.WithPitch( -AnalogLook.pitch ); if ( Preferences.InvertMouseYaw ) AnalogLook = AnalogLook.WithYaw( -AnalogLook.yaw ); // garry: do we need to smooth these or something? // They were smoothed in the old input code, but I think // we leave them as raw as possible now and let games decide AnalogMove = 0; if ( Down( "forward", false ) ) AnalogMove += Vector3.Forward; if ( Down( "backward", false ) ) AnalogMove += Vector3.Backward; if ( Down( "left", false ) ) AnalogMove += Vector3.Left; if ( Down( "right", false ) ) AnalogMove += Vector3.Right; ProcessControllerInput(); } /// /// Current state of the current input device's motion sensor(s) if supported. /// This is only supported on: Dualshock 4+, Switch Controllers, Steam Controller, Steam Deck. /// public static InputMotionData MotionData { get; internal set; } /// internal static string GetButtonOrigin( InputAction action, bool ignoreController = false ) { if ( UsingController ) { return action.GamepadCode.ToString(); } string loadedGame = Application.GameIdent; if ( string.IsNullOrEmpty( loadedGame ) ) loadedGame = "common"; var collection = InputBinds.FindCollection( loadedGame ); var bind = collection.Get( action.Name, 0 ); if ( string.IsNullOrEmpty( bind ) ) return action.KeyboardCode; return bind; } /// /// Returns the name of a key bound to this InputAction /// For example: /// Input.GetButtonOrigin( "Undo" ) /// could return SPACE if using keyboard or A Button when using a controller. /// /// public static string GetButtonOrigin( string name, bool ignoreController = false ) { var action = InputActions? .FirstOrDefault( x => string.Equals( x.Name, name, StringComparison.OrdinalIgnoreCase ) ); if ( action is null ) { Log.Warning( $"Couldn't find Input Action called \"{name}\"" ); return null; } return GetButtonOrigin( action, ignoreController ); } }