Files
sbox-public/engine/Sandbox.Engine/Systems/Input/Input.cs
s&box team 71f266059a Open source release
This commit imports the C# engine code and game files, excluding C++ source code.

[Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
2025-11-24 09:05:18 +00:00

181 lines
4.8 KiB
C#

using Sandbox.Engine;
using Sandbox.VR;
namespace Sandbox;
/// <summary>
/// Allows querying of player button presses and other inputs.
/// </summary>
public static partial class Input
{
/// <summary>
/// Virtual Reality specific input data.
/// </summary>
public static VRInput VR => VRInput.Current;
/// <summary>
/// Movement delta from the mouse.
/// </summary>
public static Vector2 MouseDelta
{
get => Suppressed ? default : CurrentContext.MouseDelta;
set => CurrentContext.MouseDelta = value;
}
/// <summary>
/// The state of the mouse wheel.
/// </summary>
public static Vector2 MouseWheel
{
get => Suppressed ? default : CurrentContext.MouseWheel;
set => CurrentContext.MouseWheel = value;
}
/// <summary>
/// True if the mouse cursor is visible (using UI etc)
/// </summary>
public static bool MouseCursorVisible
{
get => CurrentContext.MouseCursorVisible;
}
static Angles _analogLook;
/// <summary>
/// Analog look value from the default input device. This is scaled by Preferences.Sensitivity - so you don't need to scale it afterwards.
/// </summary>
[ActionGraphNode( "input.analog.look" ), Category( "Input" ), Icon( "gamepad" )]
public static Angles AnalogLook
{
get => Suppressed ? default : _analogLook;
set => _analogLook = value;
}
static Vector3 _analogMove;
/// <summary>
/// Analog move value from the default input device.
/// </summary>
[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;
}
}
/// <summary>
/// Called multiple times between ticks.
/// </summary>
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();
}
/// <summary>
/// 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.
/// </summary>
public static InputMotionData MotionData { get; internal set; }
/// <inheritdoc cref="GetButtonOrigin( string, bool )"/>
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;
}
/// <summary>
/// Returns the name of a key bound to this InputAction
/// <example>For example:
/// <code>Input.GetButtonOrigin( "Undo" )</code>
/// could return <c>SPACE</c> if using keyboard or <c>A Button</c> when using a controller.
/// </example>
/// </summary>
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 );
}
}