Skip to content

Engine Library

hifihedgehog edited this page Mar 19, 2026 · 56 revisions

Engine Library

The PadForge.Engine assembly is a shared class library containing data types, interfaces, and enums used by both the Engine (input pipeline) and App (UI/ViewModel) assemblies. It has no UI dependencies and targets net10.0-windows.

Project file: PadForge.Engine/PadForge.Engine.csproj Namespace: PadForge.Engine (Common types), PadForge.Engine.Data (data models), PadForge.Engine.Common (InputHookManager), SDL3 (P/Invoke)


Table of Contents


Gamepad

File: PadForge.Engine/Common/GamepadTypes.cs Namespace: PadForge.Engine

Minimal struct matching the XInput XINPUT_GAMEPAD layout. Used as the output of the mapping pipeline (Step 3 -> Step 4 -> Step 5).

public struct Gamepad
{
    // Fields
    public ushort Buttons;       // Bitmask of button flags
    public ushort LeftTrigger;   // 0-65535
    public ushort RightTrigger;  // 0-65535
    public short ThumbLX;        // -32768 to 32767
    public short ThumbLY;        // -32768 to 32767
    public short ThumbRX;        // -32768 to 32767
    public short ThumbRY;        // -32768 to 32767

    // Methods
    public bool IsButtonPressed(ushort flag);
    public void SetButton(ushort flag, bool pressed);
    public void Clear();
}

Button Flag Constants

Constant Value Description
DPAD_UP 0x0001 D-pad up
DPAD_DOWN 0x0002 D-pad down
DPAD_LEFT 0x0004 D-pad left
DPAD_RIGHT 0x0008 D-pad right
START 0x0010 Start button
BACK 0x0020 Back button
LEFT_THUMB 0x0040 Left stick click
RIGHT_THUMB 0x0080 Right stick click
LEFT_SHOULDER 0x0100 Left bumper
RIGHT_SHOULDER 0x0200 Right bumper
GUIDE 0x0400 Guide/home button
A 0x1000 A button
B 0x2000 B button
X 0x4000 X button
Y 0x8000 Y button

Methods

Method Signature Description
IsButtonPressed bool IsButtonPressed(ushort flag) Returns true if the specified button flag bit is set in Buttons
SetButton void SetButton(ushort flag, bool pressed) Sets or clears a button flag bit using bitwise OR/AND
Clear void Clear() Resets all fields to zero

VJoyRawState

File: PadForge.Engine/Common/GamepadTypes.cs Namespace: PadForge.Engine

Raw vJoy output state for custom (non-gamepad) configurations. Bypasses the fixed Gamepad struct to support arbitrary axis/button/POV counts.

public struct VJoyRawState
{
    public short[] Axes;      // Up to 8 axes (signed short range -32768..32767)
    public uint[] Buttons;    // Button state as 4 x 32-bit words = 128 buttons max
    public int[] Povs;        // Up to 4 POV hat switches (-1=centered, 0-35900=direction)

    public static VJoyRawState Create(int nAxes, int nButtons, int nPovs);
    public void SetButton(int index, bool pressed);
    public bool IsButtonPressed(int index);
    public void Clear();
}

Methods

Method Signature Description
Create static VJoyRawState Create(int nAxes, int nButtons, int nPovs) Factory method. Axes clamped to max 8, buttons to max 128 (stored as (N+31)/32 uint words), POVs to max 4. All values zeroed.
SetButton void SetButton(int index, bool pressed) Sets a button by 0-based index. Calculates word = index/32, bit = index%32. No-op if index out of range.
IsButtonPressed bool IsButtonPressed(int index) Returns true if the button at the given index is set. Returns false if index out of range.
Clear void Clear() Resets axes to 0, buttons to 0, POVs to -1 (centered).

Button Storage

Buttons use a 128-bit bitmask stored as uint[4]. Each uint holds 32 buttons.

POV Values

POV values are in hundredths of degrees: 0=North, 4500=NE, 9000=East, 13500=SE, 18000=South, 22500=SW, 27000=West, 31500=NW, 0xFFFFFFFF (-1) = Centered.


KbmRawState

File: PadForge.Engine/Common/GamepadTypes.cs Namespace: PadForge.Engine

Raw keyboard + mouse output state for the KeyboardMouseVirtualController. Key states are packed into 4 x 64-bit words covering 256 Windows virtual key codes. Mouse axes are signed short range for delta movement per frame.

public struct KbmRawState
{
    // Key state (256 VK codes packed into 4 ulongs)
    public ulong Keys0;             // VK 0-63
    public ulong Keys1;             // VK 64-127
    public ulong Keys2;             // VK 128-191
    public ulong Keys3;             // VK 192-255

    // Mouse output
    public short MouseDeltaX;       // Mouse X delta (signed, pixels per frame)
    public short MouseDeltaY;       // Mouse Y delta (signed, pixels per frame)
    public short ScrollDelta;       // Mouse scroll delta (positive = up)
    public byte MouseButtons;       // Bit 0=LMB, 1=RMB, 2=MMB, 3=X1, 4=X2

    // Pre-deadzone values (for UI stick/trigger preview)
    public short PreDzMouseDeltaX;  // Mouse X before center offset + deadzone
    public short PreDzMouseDeltaY;  // Mouse Y before center offset + deadzone
    public short PreDzScrollDelta;  // Scroll before deadzone

    // Methods
    public bool GetKey(byte vk);
    public void SetKey(byte vk, bool pressed);
    public bool GetMouseButton(int index);
    public void SetMouseButton(int index, bool pressed);
    public void Clear();
    public static KbmRawState Combine(KbmRawState a, KbmRawState b);
}

Methods

Method Signature Description
GetKey bool GetKey(byte vk) Returns true if virtual key code is set. Calculates word = vk/64, bit = vk%64.
SetKey void SetKey(byte vk, bool pressed) Sets or clears a virtual key code bit.
GetMouseButton bool GetMouseButton(int index) Returns true if mouse button bit is set (0=LMB, 1=RMB, 2=MMB, 3=X1, 4=X2).
SetMouseButton void SetMouseButton(int index, bool pressed) Sets or clears a mouse button bit.
Clear void Clear() Resets all keys, mouse deltas, scroll, mouse buttons, and pre-deadzone fields to zero.
Combine static KbmRawState Combine(KbmRawState a, KbmRawState b) Merges two KBM states for multi-device assignment. Keys and mouse buttons are OR'd. Mouse deltas and scroll take the largest absolute magnitude. Pre-deadzone fields also use largest magnitude.

MidiRawState

File: PadForge.Engine/Common/GamepadTypes.cs Namespace: PadForge.Engine

Dynamic-sized MIDI output state for MidiVirtualController. CC values are 0-127 (MIDI range). Notes are boolean (on/off).

public struct MidiRawState
{
    public byte[] CcValues;   // CC values 0-127 per CC slot
    public bool[] Notes;      // Note on/off per note slot

    public static MidiRawState Create(int ccCount, int noteCount);
    public void Clear();
    public static MidiRawState Combine(MidiRawState a, MidiRawState b);
}

Methods

Method Signature Description
Create static MidiRawState Create(int ccCount, int noteCount) Allocates arrays of specified sizes. CC values initialized to 0.
Clear void Clear() Resets CC values to 64 (center for axes), notes to false.
Combine static MidiRawState Combine(MidiRawState a, MidiRawState b) Merges two MIDI states. CCs take the value furthest from center (64); notes are OR'd.

VirtualControllerType

File: PadForge.Engine/Common/VirtualControllerTypes.cs Namespace: PadForge.Engine

public enum VirtualControllerType
{
    Xbox360 = 0,
    DualShock4 = 1,
    VJoy = 2,
    Midi = 3,
    KeyboardMouse = 4
}

IVirtualController

File: PadForge.Engine/Common/VirtualControllerTypes.cs Namespace: PadForge.Engine

Abstraction over virtual controller operations. Concrete implementations live in the App assembly:

  • Xbox360VirtualController (ViGEm)
  • DS4VirtualController (ViGEm)
  • VJoyVirtualController (direct P/Invoke to vJoyInterface.dll)
  • MidiVirtualController (Windows MIDI Services SDK)
  • KeyboardMouseVirtualController (Win32 SendInput)
public interface IVirtualController : IDisposable
{
    VirtualControllerType Type { get; }
    bool IsConnected { get; }
    int FeedbackPadIndex { get; set; }

    void Connect();
    void Disconnect();
    void SubmitGamepadState(Gamepad gp);
    void RegisterFeedbackCallback(int padIndex, Vibration[] vibrationStates);
}

Members

Member Type Description
Type VirtualControllerType The type of virtual controller
IsConnected bool Whether the virtual controller is currently connected/plugged in
FeedbackPadIndex int Tracks which slot this VC occupies so feedback callbacks write to the correct VibrationStates element after a slot reorder via SwapSlotData
Connect() void Creates and plugs in the virtual controller
Disconnect() void Unplugs and destroys the virtual controller
SubmitGamepadState(Gamepad) void Sends the current gamepad state to the virtual controller
RegisterFeedbackCallback(int, Vibration[]) void Registers a callback that writes rumble feedback to the shared VibrationStates array at the given pad index

CustomInputState

File: PadForge.Engine/Common/CustomInputState.cs Namespace: PadForge.Engine

API-agnostic snapshot of a device's complete input state at a single point in time.

public class CustomInputState
{
    // Constants
    public const int MaxAxis = 24;
    public const int MaxSliders = 8;
    public const int MaxPovs = 4;
    public const int MaxButtons = 256;

    // Fields
    public int[] Axis;       // 0-65535, center = 32767
    public int[] Sliders;    // 0-65535
    public int[] Povs;       // centidegrees 0-35900, or -1 for centered
    public bool[] Buttons;   // true = pressed
    public float[] Gyro;     // [X, Y, Z] radians per second
    public float[] Accel;    // [X, Y, Z] meters per second squared

    // Constructors
    public CustomInputState();
    public CustomInputState(int[] axes, int[] sliders, int[] povs, bool[] buttons);

    // Methods
    public CustomInputState Clone();
    public static void GetAxisMask(DeviceObjectItem[] items, int numAxes,
        out int axisMask, out int actuatorMask, out int actuatorCount);
}

Constructors

Constructor Description
CustomInputState() Creates zeroed arrays with default sizes. POVs initialize to -1 (centered). Gyro and Accel are 3-element float arrays.
CustomInputState(int[], int[], int[], bool[]) Copies arrays up to max lengths (snapshot isolation). POVs initialized to -1 before copy.

Methods

Method Signature Description
Clone CustomInputState Clone() Deep copy of all arrays including Gyro and Accel.
GetAxisMask static void GetAxisMask(DeviceObjectItem[], int, out int, out int, out int) Scans device object items to build axis and force-feedback actuator bitmasks. Bit N set = axis/actuator N exists.

Value Conventions

Array Range Center Description
Axis 0-65535 32767 Indices 0-5 = X, Y, Z, Rx, Ry, Rz. 6-23 = additional
Sliders 0-65535 32767 Overflow or dedicated slider controls
Povs 0-35900 or -1 -1 Centidegrees. -1 = centered
Buttons bool false 256 max (covers full Windows VK code range)
Gyro float[3] 0.0 Radians/second. Only for gyro-capable devices
Accel float[3] 0.0 m/s^2. Only for accelerometer-capable devices

CustomInputUpdate

File: PadForge.Engine/Common/CustomInputUpdate.cs Namespace: PadForge.Engine

Represents a single buffered input change between two CustomInputState snapshots. Used by the input recorder and update pipeline.

public struct CustomInputUpdate
{
    public MapType Type;    // Axis, Button, Slider, or POV
    public int Index;       // Zero-based index within the type's array
    public int Value;       // New value after the change

    public override string ToString();  // Returns "Type Index = Value"
}

Field Details

Field Type Description
Type MapType The type of input source that changed
Index int Zero-based index within the type's array (e.g., Axis[0], Buttons[5])
Value int New value. Axes/sliders: unsigned 0-65535. POVs: centidegrees or -1. Buttons: 1=pressed, 0=released.

CustomInputHelper

File: PadForge.Engine/Common/CustomInputHelper.cs Namespace: PadForge.Engine

Static helper class providing constants and utility methods for working with CustomInputState.

Constants

Constant Type Value Description
MaxAxis int 24 Mirrors CustomInputState.MaxAxis
MaxSliders int 8 Mirrors CustomInputState.MaxSliders
MaxPovs int 4 Mirrors CustomInputState.MaxPovs
MaxButtons int 256 Mirrors CustomInputState.MaxButtons
AxisCenter int 32767 Unsigned axis center value
AxisMin int 0 Unsigned axis minimum
AxisMax int 65535 Unsigned axis maximum
PovCentered int -1 POV centered value (no direction pressed)

Methods

Method Signature Description
GetUpdates static CustomInputUpdate[] GetUpdates(CustomInputState oldState, CustomInputState newState) Generates an array of CustomInputUpdate items describing every difference between two input states. Compares axes, sliders, POVs, and buttons. Null states treated as all-zero. Returns empty array if no changes.

ISdlInputDevice

File: PadForge.Engine/Common/ISdlInputDevice.cs Namespace: PadForge.Engine

Common interface for all SDL-based input device wrappers (joystick/gamepad, keyboard, mouse, web controller). Allows the input pipeline (Steps 2-5) to read state from any device type uniformly.

public interface ISdlInputDevice : IDisposable
{
    // Identity
    uint SdlInstanceId { get; }
    string Name { get; }
    Guid InstanceGuid { get; }
    Guid ProductGuid { get; }
    string DevicePath { get; }
    string SerialNumber { get; }
    ushort VendorId { get; }
    ushort ProductId { get; }

    // Capabilities
    int NumAxes { get; }
    int NumButtons { get; }
    int RawButtonCount { get; }
    int NumHats { get; }
    bool HasRumble { get; }
    bool HasHaptic { get; }
    bool HasGyro { get; }
    bool HasAccel { get; }
    bool IsAttached { get; }

    // Haptic
    HapticEffectStrategy HapticStrategy { get; }
    IntPtr HapticHandle { get; }
    uint HapticFeatures { get; }
    int NumHapticAxes { get; }

    // State reading
    CustomInputState GetCurrentState(bool forceRaw = false);
    DeviceObjectItem[] GetDeviceObjects();
    int GetInputDeviceType();

    // Force feedback
    bool SetRumble(ushort low, ushort high, uint durationMs = uint.MaxValue);
    bool StopRumble();
}

Property Details

Property Type Description
SdlInstanceId uint SDL instance ID (unique per device connection session). 0 = invalid.
Name string Human-readable device name
InstanceGuid Guid Deterministic GUID for settings matching (derived from path/serial/VID+PID)
ProductGuid Guid Product GUID from VID/PID for device family identification
DevicePath string Device file system path (may be empty)
SerialNumber string Serial number (e.g., Bluetooth MAC). May be empty.
VendorId ushort USB Vendor ID
ProductId ushort USB Product ID
NumAxes int Number of axes. 6 for gamepads (LX, LY, LT, RX, RY, RT).
NumButtons int Number of buttons. 11 for gamepads (standard layout).
RawButtonCount int Total raw joystick buttons before gamepad remapping. May exceed NumButtons.
NumHats int Number of POV hat switches. 1 for gamepads (D-pad).
HasRumble bool Whether the device supports simple rumble vibration
HasHaptic bool Whether the device has an SDL haptic handle open
HasGyro bool Whether the device has a gyroscope sensor
HasAccel bool Whether the device has an accelerometer sensor
IsAttached bool Whether the device handle is still valid and connected
HapticStrategy HapticEffectStrategy Best haptic strategy chosen at open time
HapticHandle IntPtr SDL haptic device handle (IntPtr.Zero if none)
HapticFeatures uint Bitmask of SDL_HAPTIC_* feature flags
NumHapticAxes int Number of haptic axes (1=wheel, 2+=joystick)

Method Details

Method Signature Description
GetCurrentState CustomInputState GetCurrentState(bool forceRaw = false) Reads current input state. forceRaw=true bypasses SDL gamepad remapping.
GetDeviceObjects DeviceObjectItem[] GetDeviceObjects() Returns metadata for each axis, hat, and button on the device.
GetInputDeviceType int GetInputDeviceType() Returns an InputDeviceType constant classifying the device.
SetRumble bool SetRumble(ushort low, ushort high, uint durationMs) Sends rumble. Default duration uint.MaxValue (~49 days). Returns success.
StopRumble bool StopRumble() Stops all rumble (calls SetRumble(0, 0, 0)).

SdlDeviceWrapper

File: PadForge.Engine/Common/SdlDeviceWrapper.cs Namespace: PadForge.Engine

Wraps an SDL joystick (and optionally its Gamepad overlay) to provide unified device access: open/close, state polling, rumble, GUID construction, and device object enumeration. Implements ISdlInputDevice.

Properties (beyond ISdlInputDevice)

Property Type Default Description
Joystick IntPtr IntPtr.Zero Raw SDL joystick handle. Always valid when device is open.
GameController IntPtr IntPtr.Zero SDL Gamepad handle. Zero if not recognized as a gamepad.
Haptic IntPtr IntPtr.Zero SDL haptic device handle. Non-zero when haptic FFB is available.
ProductVersion ushort 0 USB Product Version
JoystickType SDL_JoystickType UNKNOWN SDL joystick type classification
IsGameController bool (computed) true if opened as an SDL Gamepad

Public Methods

Method Signature Description
Open bool Open(uint instanceId) Opens the SDL device. Tries Gamepad first, falls back to raw Joystick. Populates all properties including haptic, sensors, GUIDs. Returns true on success.
GetCurrentState CustomInputState GetCurrentState(bool forceRaw = false) Reads input state. Routes to GetGamepadState() (remapped) or GetJoystickState() (raw) depending on device type and forceRaw flag.
GetDeviceObjects DeviceObjectItem[] GetDeviceObjects() Builds array of DeviceObjectItem describing each axis, hat, and button. First 6 axes get standard GUIDs (X, Y, Z, Rx, Ry, Rz); extras get Slider GUIDs.
GetInputDeviceType int GetInputDeviceType() Maps SDL_JoystickType to InputDeviceType constant.
SetRumble bool SetRumble(ushort lowFreq, ushort highFreq, uint durationMs) Sends rumble via SDL_RumbleJoystick. Returns false if no rumble support.
StopRumble bool StopRumble() Calls SetRumble(0, 0, 0).

Static Methods

Method Signature Description
BuildProductGuid static Guid BuildProductGuid(ushort vid, ushort pid) Builds a synthetic product GUID from VID and PID. Layout: bytes[0-1]=VID LE, bytes[2-3]=PID LE, bytes[4-15]=0x00.
BuildInstanceGuid static Guid BuildInstanceGuid(string devicePath, ushort vid, ushort pid, uint instanceId, string serial = null) Builds a deterministic instance GUID. Priority: VID+PID+Serial (best, stable across reboots), device path (good for wired), VID+PID+SDL ID (last resort, session-specific). Uses MD5 hash.
HatToCentidegrees static int HatToCentidegrees(byte hat) Converts SDL hat bitmask to centidegrees (-1 for centered).
DpadToCentidegrees static int DpadToCentidegrees(bool up, bool down, bool left, bool right) Converts 4 D-pad booleans to centidegrees. Supports 8-way diagonals.

Gamepad State Reading

GetGamepadState() reads through SDL's gamecontrollerdb mapping layer. Produces a standardized layout:

  • Axes: [0]=LX, [1]=LY, [2]=LT, [3]=RX, [4]=RY, [5]=RT
  • Buttons: [0]=A, [1]=B, [2]=X, [3]=Y, [4]=LB, [5]=RB, [6]=Back, [7]=Start, [8]=LS, [9]=RS, [10]=Guide
  • POV[0]: D-pad synthesized from gamepad D-pad buttons
  • Sensors: Gyro and Accel arrays populated if available

Guide button suppression: When Back+Start+Guide are all pressed simultaneously, Guide is suppressed (Windows/XInput synthesizes Guide from this combo).

Extra raw buttons: Raw joystick buttons beyond index 10 are appended (e.g., DualSense touchpad click), but indices already consumed by the gamepad mapping are excluded via ParseMappedButtonIndices().

Joystick State Reading

GetJoystickState() reads raw joystick input (no gamepad remapping):

  • Axes: SDL signed (-32768..32767) converted to unsigned (0..65535) by subtracting short.MinValue. First MaxAxis go to Axis[], overflow to Sliders[].
  • Hats: SDL bitmask converted to centidegrees via HatToCentidegrees.
  • Buttons: Uses RawButtonCount (not NumButtons) for full raw button coverage.

HID Product String Fallback

SDL3 may return a raw VID/PID string (e.g., "0x16c0/0x05e1") for devices not in its database. IsRawVidPidName() detects this, and TryGetHidProductString() queries the Windows HID product string via CreateFile + HidD_GetProductString P/Invoke.

Haptic Open Strategy

OpenHaptic() opens SDL_OpenHapticFromJoystick and picks the best effect strategy:

  1. LeftRight (best match for dual-motor)
  2. Sine (periodic fallback)
  3. Constant (last resort)

For devices that already have simple rumble AND LeftRight haptic support, simple rumble is preferred and haptic is skipped (more reliable for gamepads). Gain is set to 100 if SDL_HAPTIC_GAIN is supported.


HapticEffectStrategy

File: PadForge.Engine/Common/SdlDeviceWrapper.cs Namespace: PadForge.Engine

public enum HapticEffectStrategy
{
    None,       // No haptic support
    LeftRight,  // Best: SDL_HAPTIC_LEFTRIGHT (dual-motor)
    Sine,       // Periodic effect (period varies by motor)
    Constant    // Fallback: constant level from dominant motor
}

SdlKeyboardWrapper

File: PadForge.Engine/Common/SdlKeyboardWrapper.cs Namespace: PadForge.Engine

Wraps a keyboard device for unified input via ISdlInputDevice. State is read from Raw Input (per-device) via RawInputListener.

Properties

Property Type Value/Description
NumAxes int 0
NumButtons int Up to 256 (min of 256 and MaxButtons)
RawButtonCount int 0
NumHats int 0
HasRumble bool false
HasHaptic bool false
HasGyro bool false
HasAccel bool false
RawInputHandle IntPtr The Raw Input device handle for per-device state reading

Methods

Method Signature Description
Open bool Open(RawInputListener.DeviceInfo deviceInfo) Opens from a Raw Input device enumeration result. Builds GUID from device path. Uses path hash as pseudo SDL instance ID.
GetCurrentState CustomInputState GetCurrentState(bool forceRaw) Reads keyboard state from RawInputListener.GetKeyboardState, then merges hooked key state via InputHookManager.MergeHookedKeyState (for suppressed keys that never reach Raw Input).
GetDeviceObjects DeviceObjectItem[] Returns 256 button items with ObjectGuid.Key GUIDs. Names from SDL.VirtualKeyName table.
GetInputDeviceType int Returns InputDeviceType.Keyboard (19).
SetRumble / StopRumble Always returns false.

SdlMouseWrapper

File: PadForge.Engine/Common/SdlMouseWrapper.cs Namespace: PadForge.Engine

Wraps a mouse device for unified input via ISdlInputDevice. State is read from Raw Input (per-device) via RawInputListener.

Constants

Constant Value Description
MouseButtons 5 Left, Middle, Right, X1, X2
MouseAxes 3 X Motion, Y Motion, Scroll
AxisCenter 32767 Center value for mouse axis output
MotionScale 2048f Multiplier for mouse delta to axis value
ScrollScale 128f Multiplier for scroll delta to axis value

Properties

Property Type Value/Description
NumAxes int 3 (X Motion, Y Motion, Scroll)
NumButtons int 5 (Left, Middle, Right, X1, X2)
RawButtonCount int 0
NumHats int 0
HasRumble bool false
RawInputHandle IntPtr The Raw Input device handle

Methods

Method Signature Description
Open bool Open(RawInputListener.DeviceInfo deviceInfo) Opens from a Raw Input device enumeration result.
GetCurrentState CustomInputState GetCurrentState(bool forceRaw) Reads mouse delta from ConsumeMouseDelta, scroll from ConsumeMouseScroll, buttons from GetMouseButtons + InputHookManager.MergeHookedMouseState. Axes are computed as AxisCenter + (delta * Scale) clamped to 0-65535.
GetDeviceObjects DeviceObjectItem[] Returns 3 RelativeAxis items (X Motion, Y Motion, Scroll with XAxis/YAxis/ZAxis GUIDs) + 5 PushButton items (Left Click, Middle Click, Right Click, X1, X2).
GetInputDeviceType int Returns InputDeviceType.Mouse (18).

WebControllerDevice

File: PadForge.Engine/Common/WebControllerDevice.cs Namespace: PadForge.Engine

Virtual input device representing a browser-connected gamepad. Implements ISdlInputDevice so it integrates with the standard input pipeline. State is written by the WebSocket thread and read by the polling thread via volatile reference swaps.

Constants

Constant Value Description
WebVendorId 0xBEEF Distinctive VID to avoid ViGEm filter false positives
WebProductId 0xCA7E Distinctive PID
WebProductGuid {BEBC0000-...} Fixed ProductGuid for all web controller instances

Fixed Capabilities

Property Value
Axes 6 (LX, LY, LT, RX, RY, RT -- 0-65535 range)
Buttons 11 (standard Xbox layout: A, B, X, Y, LB, RB, Back, Start, LS, RS, Guide)
POV Hats 1
HasRumble true (via browser Vibration API)
HasHaptic false
HasGyro false
HasAccel false

Constructor

public WebControllerDevice(string clientId, string displayName)

Creates a new web controller. clientId is a unique identifier from browser localStorage. InstanceGuid is derived from the client ID via MD5. SdlInstanceId is the hash code of the client ID. Stick axes initialized to center (32767), trigger axes to 0.

Events

Event Signature Description
RumbleRequested Action<ushort, ushort> Fired when SetRumble is called. Parameters: (lowFrequency, highFrequency) in 0-65535 range.

State Update Methods

Method Signature Description
UpdateAxis void UpdateAxis(int code, int value) Updates an axis value (0=LX, 1=LY, 2=LT, 3=RX, 4=RY, 5=RT). Thread-safe via clone + lock.
UpdateButton void UpdateButton(int code, bool pressed) Updates a button state (0=A through 10=Guide). Thread-safe.
UpdatePov void UpdatePov(int value) Updates POV hat value (centidegrees or -1). Thread-safe.
SetConnected void SetConnected(bool connected) Sets the connection state (volatile write).

DeviceObjectItem

File: PadForge.Engine/Common/DeviceObjectItem.cs Namespace: PadForge.Engine

Describes a single input object (axis, button, hat, slider) on a device. Used by the mapping UI and pipeline.

public class DeviceObjectItem
{
    // Identity
    public string Name { get; set; }                           // Default: ""
    public Guid ObjectTypeGuid { get; set; }                   // Default: Guid.Empty
    public DeviceObjectTypeFlags ObjectType { get; set; }      // Default: All

    // Position
    public int InputIndex { get; set; }                        // Default: 0
    public int Offset { get; set; }                            // Default: 0

    // Aspect
    public ObjectAspect Aspect { get; set; }                   // Default: Position

    // Computed helpers (read-only)
    public bool IsForceActuator { get; }
    public bool IsAxis { get; }
    public bool IsButton { get; }
    public bool IsPov { get; }
    public bool IsSlider { get; }

    public override string ToString();  // "{Name} ({TypeLabel}, Index {InputIndex})"
}

Property Details

Property Type Default Description
Name string "" Human-readable name (e.g., "X Axis", "Button 3", "Left Stick X")
ObjectTypeGuid Guid Guid.Empty Well-known GUID from ObjectGuid (XAxis, YAxis, Button, etc.)
ObjectType DeviceObjectTypeFlags All Classification flags (AbsoluteAxis, PushButton, etc.)
InputIndex int 0 Zero-based index into CustomInputState arrays
Offset int 0 Byte offset (synthetic for SDL, used for mapping compatibility)
Aspect ObjectAspect Position Object aspect

Computed Properties

Property Logic
IsForceActuator (ObjectType & ForceFeedbackActuator) != 0
IsAxis (ObjectType & Axis) != 0
IsButton (ObjectType & Button) != 0
IsPov (ObjectType & PointOfViewController) != 0
IsSlider ObjectTypeGuid == ObjectGuid.Slider

DeviceEffectItem

File: PadForge.Engine/Common/DeviceEffectItem.cs Namespace: PadForge.Engine

Describes a force feedback effect supported by a device. Under SDL3, rumble is the primary effect type. Kept for UI display and settings compatibility.

Well-Known Effect GUIDs

Field GUID Description
ConstantForce {13541C20-8E33-11D0-9AD0-00A0C9A06E35} GUID_ConstantForce (DirectInput)
Square {13541C22-...} GUID_Square
Sine {13541C23-...} GUID_Sine
Triangle {13541C24-...} GUID_Triangle
Spring {13541C27-...} GUID_Spring
Damper {13541C28-...} GUID_Damper
SdlRumble {53444C52-554D-424C-...} Synthetic GUID for SDL rumble ("SDLRUMBL")

Instance Properties

Property Type Default Description
EffectGuid Guid Guid.Empty GUID identifying the effect type
Name string "" Human-readable name (e.g., "Constant Force", "Rumble")
Parameters EffectParameterFlags None Which parameters the effect supports

Factory Methods

Method Signature Description
CreateRumbleEffect static DeviceEffectItem CreateRumbleEffect() Creates an item representing SDL rumble support (SdlRumble GUID, name "Rumble").

InputTypes

File: PadForge.Engine/Common/InputTypes.cs Namespace: PadForge.Engine

DeviceObjectTypeFlags

[Flags]
public enum DeviceObjectTypeFlags : int
{
    All = 0,
    RelativeAxis = 1,
    AbsoluteAxis = 2,
    Axis = 3,                        // RelativeAxis | AbsoluteAxis
    PushButton = 4,
    ToggleButton = 8,
    Button = 12,                     // PushButton | ToggleButton
    PointOfViewController = 16,
    Collection = 64,
    NoData = 128,
    ForceFeedbackActuator = 0x01000000,
    ForceFeedbackEffectTrigger = 0x02000000
}

ObjectAspect

[Flags]
public enum ObjectAspect : int
{
    Position = 0x100
}

EffectParameterFlags

[Flags]
public enum EffectParameterFlags : int
{
    None = 0
}

ObjectGuid

Static class providing well-known GUIDs for device object types. Values match DirectInput GUID constants.

Field GUID Description
XAxis {A36D02E0-C9F3-11CF-BFC7-444553540000} GUID_XAxis
YAxis {A36D02E1-C9F3-11CF-BFC7-444553540000} GUID_YAxis
ZAxis {A36D02E2-C9F3-11CF-BFC7-444553540000} GUID_ZAxis
RxAxis {A36D02F4-C9F3-11CF-BFC7-444553540000} GUID_RxAxis
RyAxis {A36D02F5-C9F3-11CF-BFC7-444553540000} GUID_RyAxis
RzAxis {A36D02E3-C9F3-11CF-BFC7-444553540000} GUID_RzAxis
Slider {A36D02E4-C9F3-11CF-BFC7-444553540000} GUID_Slider
Button {A36D02F0-C9F3-11CF-BFC7-444553540000} GUID_Button
Key {55728220-D33C-11CF-BFC7-444553540000} GUID_Key
PovController {A36D02F2-C9F3-11CF-BFC7-444553540000} GUID_POV
Unknown Guid.Empty GUID_Unknown

InputDeviceType

Integer constants matching DirectInput device type values. Used for UserDevice.CapType.

Constant Value Description
Device 17 Generic device
Mouse 18 Mouse
Keyboard 19 Keyboard
Joystick 20 Joystick
Gamepad 21 Gamepad
Driving 22 Steering wheel
Flight 23 Flight stick
FirstPerson 24 First-person device
Supplemental 25 Supplemental device (guitar, drum, dance pad)

MapType

public enum MapType : int
{
    None = 0,
    Axis = 1,
    Button = 2,
    Slider = 3,
    POV = 4
}

ForceFeedbackState

File: PadForge.Engine/Common/ForceFeedbackState.cs Namespace: PadForge.Engine

Manages force feedback (rumble) state for a single device with change detection. Uses change-detection to only send rumble when motor values differ, with uint.MaxValue duration (~49 days) to mimic XInput's "set and forget" behavior.

Public Properties

Property Type Description
LeftMotorSpeed ushort Most recent left (low-frequency) motor speed sent to device. 0-65535. Read-only.
RightMotorSpeed ushort Most recent right (high-frequency) motor speed sent to device. 0-65535. Read-only.
IsActive bool Whether force feedback is currently active on the device. Read-only.

Private Fields (Change Detection Cache)

Field Type Description
_cachedLeftMotorSpeed ushort Last sent left motor speed
_cachedRightMotorSpeed ushort Last sent right motor speed
_hapticEffectId int SDL haptic effect ID (-1 = none)
_hapticEffectCreated bool Whether a haptic effect has been created
_cachedEffectType uint Last sent FFB effect type
_cachedSignedMag short Last sent signed magnitude
_cachedDirection ushort Last sent polar direction
_cachedPeriod uint Last sent period
_cachedHasCondition bool Last sent condition data flag
_cachedHasDirectional bool Last sent directional data flag

Public Methods

Method Signature Description
SetDeviceForces void SetDeviceForces(UserDevice ud, ISdlInputDevice device, PadSetting ps, Vibration v) Main entry point. Reads gain settings from PadSetting (ForceOverall, LeftMotorStrength, RightMotorStrength, ForceSwapMotor). Routes to Path 1 (directional haptic) when `v.HasDirectionalData
StopDeviceForces void StopDeviceForces(ISdlInputDevice device) Stops all rumble/haptic and resets all cached state. Routes to StopAndDestroyHapticEffect() for haptic devices or StopRumble() for rumble devices.

Private Methods

Method Description
SetDirectionalHapticForces(device, v, overallGain) Sends directional constant or periodic force. Single-axis (wheels): projects polar direction onto steering axis via sin(angle). Multi-axis (joysticks): full 2D polar. Falls back to scalar if effect type unsupported.
SetConditionHapticForces(device, v, overallGain) Sends condition effects (spring/damper/friction/inertia) with per-axis coefficients. Scales HID ranges (-10000..+10000) to SDL ranges (-32767..+32767). Falls back to scalar if unsupported.
SetHapticForces(device, left, right) Scalar haptic fallback. Translates dual-motor values to SDL haptic effect based on HapticEffectStrategy (LeftRight, Sine, or Constant).
ApplyHapticEffect(device, ref effect) Creates effect on first call (SDL_CreateHapticEffect + SDL_RunHapticEffect), updates in-place on subsequent calls (SDL_UpdateHapticEffect). Avoids create/destroy churn.
StopAndDestroyHapticEffect(device) Stops and destroys the active haptic effect. Resets _hapticEffectId and _hapticEffectCreated.

Scalar Haptic Strategy Mapping

Strategy SDL Effect Large Motor Small Motor
LeftRight SDL_HAPTIC_LEFTRIGHT large_magnitude = left small_magnitude = right
Sine SDL_HAPTIC_SINE magnitude = max/2, period = 120 period = 40
Constant SDL_HAPTIC_CONSTANT level = max/2 N/A

FfbEffectTypes

File: PadForge.Engine/Common/ForceFeedbackState.cs Namespace: PadForge.Engine

Static class with FFB effect type constants matching vJoy FFBEType enum values. Defined in Engine so both Engine and App can reference them.

Constant Value Description
None 0 No effect
Const 1 Constant force
Ramp 2 Ramp force
Square 3 Square wave periodic
Sine 4 Sine wave periodic
Triangle 5 Triangle wave periodic
SawUp 6 Sawtooth up periodic
SawDown 7 Sawtooth down periodic
Spring 8 Spring condition
Damper 9 Damper condition
Inertia 10 Inertia condition
Friction 11 Friction condition

Vibration

File: PadForge.Engine/Common/ForceFeedbackState.cs Namespace: PadForge.Engine

Represents vibration/force feedback state for a virtual controller slot. Carries both scalar motor speeds (for rumble devices) and directional FFB data (for haptic joysticks/wheels).

public class Vibration
{
    // Scalar fields (ViGEm Xbox/DS4 callbacks and rumble path)
    public ushort LeftMotorSpeed { get; set; }       // 0-65535, low-frequency heavy rumble
    public ushort RightMotorSpeed { get; set; }      // 0-65535, high-frequency light buzz

    // Directional FFB fields (vJoy FFB callback for haptic devices)
    public bool HasDirectionalData { get; set; }
    public uint EffectType { get; set; }             // FfbEffectTypes constant
    public short SignedMagnitude { get; set; }        // -10000 to +10000
    public ushort Direction { get; set; }             // Polar 0-32767 (0=North)
    public uint Period { get; set; }                  // ms, for periodic effects
    public byte DeviceGain { get; set; } = 255;       // 0-255, device-level gain

    // Condition effect fields (spring/damper/friction/inertia)
    public bool HasConditionData { get; set; }
    public ConditionAxisData[] ConditionAxes { get; set; }
    public int ConditionAxisCount { get; set; }       // 1 for wheels, 2 for joysticks

    // Constructors
    public Vibration();
    public Vibration(ushort leftMotor, ushort rightMotor);
}

Field Details

Field Type Default Description
LeftMotorSpeed ushort 0 Left motor (low-frequency, heavy rumble) speed. Set by ViGEm callbacks.
RightMotorSpeed ushort 0 Right motor (high-frequency, light buzz) speed. Set by ViGEm callbacks.
HasDirectionalData bool false True when directional FFB data is available (vJoy path)
EffectType uint 0 Primary effect type (see FfbEffectTypes)
SignedMagnitude short 0 -10000 to +10000. Negative = opposite direction for constant force.
Direction ushort 0 Polar direction in HID units 0-32767 (0=North, ~8192=East, ~16384=South, ~24576=West)
Period uint 0 Period in ms for periodic effects
DeviceGain byte 255 Device-level gain 0-255. Applied on top of per-effect gain.
HasConditionData bool false True when per-axis condition data is available
ConditionAxes ConditionAxisData[] null Per-axis condition coefficients. Index 0=X, 1=Y.
ConditionAxisCount int 0 Number of valid entries (1 for wheels, 2 for joysticks)

ConditionAxisData

File: PadForge.Engine/Common/ForceFeedbackState.cs Namespace: PadForge.Engine

Per-axis condition effect parameters for spring/damper/friction/inertia effects.

public struct ConditionAxisData
{
    public short PositiveCoefficient;    // 0-10000, force when displacement > center
    public short NegativeCoefficient;    // 0-10000, force when displacement < center
    public short Offset;                 // -10000 to +10000, center point offset
    public uint DeadBand;                // 0-10000, dead band around center
    public uint PositiveSaturation;      // 0-10000
    public uint NegativeSaturation;      // 0-10000
}

RumbleLogger

File: PadForge.Engine/Common/RumbleLogger.cs Namespace: PadForge.Engine

Lightweight diagnostic logger for force feedback debugging. Disabled by default. Thread-safe.

public static class RumbleLogger
{
    public static bool Enabled { get; set; }      // Default: false
    public static void Log(string message);
    public static void Close();
}

Details

Member Description
Enabled Set to true in InputService.Start() to activate logging.
Log(string) Writes timestamped message to rumble_log.txt next to the executable. Uses Stopwatch for high-resolution timing. Thread-safe via lock. Only writes when Enabled is true. Creates log file on first call.
Close() Closes and disposes the log file StreamWriter. Call on app shutdown.

InputHookManager

File: PadForge.Engine/Common/InputHookManager.cs Namespace: PadForge.Engine.Common

Manages WH_KEYBOARD_LL and WH_MOUSE_LL low-level Windows hooks for suppressing mapped inputs from keyboards and mice. Only suppresses inputs that are in the active suppression sets.

public class InputHookManager : IDisposable
{
    void Start();
    void Stop();
    void SetSuppressedKeys(HashSet<int> vkCodes);
    void SetSuppressedMouseButtons(HashSet<int> buttons);
    bool HasAnySuppression { get; }

    static void MergeHookedKeyState(bool[] dest, int count);
    static void MergeHookedMouseState(bool[] dest, int count);
}

Methods

Method Signature Description
Start void Start() Creates a dedicated background thread with a GetMessage loop and installs both hooks. Blocks (via ManualResetEventSlim) until hooks are installed (5s timeout).
Stop void Stop() Posts WM_QUIT to the hook thread, joins (2s timeout), clears hooked state arrays.
SetSuppressedKeys void SetSuppressedKeys(HashSet<int> vkCodes) Updates the VK codes to suppress. Clears hooked state for keys removed from suppression set. Uses volatile reference swap for thread safety.
SetSuppressedMouseButtons void SetSuppressedMouseButtons(HashSet<int> buttons) Updates mouse button IDs to suppress (0=Left, 1=Right, 2=Middle, 3=X1, 4=X2). Same volatile reference swap pattern.
HasAnySuppression bool (property) Returns true if any keys or mouse buttons are being suppressed.
MergeHookedKeyState static void MergeHookedKeyState(bool[] dest, int count) Merges suppressed-key state into a destination array. For suppressed keys, hook state is authoritative (replaces dest). Called by SdlKeyboardWrapper.GetCurrentState().
MergeHookedMouseState static void MergeHookedMouseState(bool[] dest, int count) Same principle for mouse buttons. Called by SdlMouseWrapper.GetCurrentState().

Hook Callbacks

  • Keyboard: Intercepts WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, WM_SYSKEYUP. Reads KBDLLHOOKSTRUCT.vkCode. Returns (IntPtr)1 to suppress, or CallNextHookEx to pass through. Captures key state into _hookedKeyState[] before suppressing (WH_KEYBOARD_LL runs in RIT before WM_INPUT is generated).
  • Mouse: Intercepts button messages (WM_LBUTTONDOWN/UP, WM_RBUTTONDOWN/UP, WM_MBUTTONDOWN/UP, WM_XBUTTONDOWN/UP). Converts message to button ID via MouseMessageToButtonId(). Captures button state into _hookedMouseState[].

Button ID Mapping

Mouse Message Button ID
WM_LBUTTONDOWN/UP 0 (Left)
WM_RBUTTONDOWN/UP 1 (Right)
WM_MBUTTONDOWN/UP 2 (Middle)
WM_XBUTTONDOWN/UP (XBUTTON1) 3
WM_XBUTTONDOWN/UP (XBUTTON2) 4
Other (move, wheel) -1 (pass through)

P/Invoke

Function DLL Purpose
SetWindowsHookExW user32.dll Install low-level hook
UnhookWindowsHookEx user32.dll Remove hook
CallNextHookEx user32.dll Pass input to next hook
GetModuleHandleW kernel32.dll Get module handle for hook registration
GetMessageW user32.dll Message pump loop
PostThreadMessageW user32.dll Post WM_QUIT to hook thread
GetCurrentThreadId kernel32.dll Get hook thread ID

RawInputListener

File: PadForge.Engine/Common/RawInputListener.cs Namespace: PadForge.Engine

Static class that receives keyboard and mouse input via Windows Raw Input API, even when the application window is not focused (RIDEV_INPUTSINK). Creates a hidden message-only window (HWND_MESSAGE) on a dedicated background thread.

State is tracked per-device via RAWINPUT.header.hDevice, so arcade encoders and other multi-device setups get isolated input.

DeviceInfo Struct

public struct DeviceInfo
{
    public IntPtr Handle;       // Raw Input device handle
    public string Name;         // Device display name
    public string DevicePath;   // Device interface path
    public ushort VendorId;     // USB VID
    public ushort ProductId;    // USB PID
}

Static Fields

Field Type Description
AggregateKeyboardHandle IntPtr Sentinel value new IntPtr(-99). Aggregates state from all keyboards.
AggregateMouseHandle IntPtr Sentinel value new IntPtr(-98). Aggregates state from all mice.

Public Methods

Method Signature Description
Start static void Start() Creates the message-pump thread, registers for Raw Input keyboard and mouse. Blocks until the window is created.
Stop static void Stop() Posts WM_QUIT to the message pump thread, joins it.
EnumerateKeyboards static DeviceInfo[] EnumerateKeyboards() Returns all connected keyboard devices via GetRawInputDeviceList.
EnumerateMice static DeviceInfo[] EnumerateMice() Returns all connected mouse devices.
GetKeyboardState static void GetKeyboardState(IntPtr hDevice, bool[] dest, int count) Copies per-device keyboard key states into dest. Uses aggregate handle for combined output.
ConsumeMouseDelta static void ConsumeMouseDelta(IntPtr hDevice, out int dx, out int dy) Returns and resets accumulated mouse delta for the device.
ConsumeMouseScroll static int ConsumeMouseScroll(IntPtr hDevice) Returns and resets accumulated scroll wheel delta.
GetMouseButtons static void GetMouseButtons(IntPtr hDevice, bool[] dest) Copies per-device mouse button states (5 buttons: L, R, M, X1, X2).

Input Processing

  • Keyboard (WM_INPUT, RIM_TYPEKEYBOARD): Reads RAWKEYBOARD.VKey, handles RI_KEY_E0 extended keys (maps right Ctrl/Alt/Shift to distinct VK codes, NumLock/Insert/Home/etc. to extended versions). Tracks per-device key state in a ConcurrentDictionary<IntPtr, bool[]>.
  • Mouse (WM_INPUT, RIM_TYPEMOUSE): Accumulates lLastX/lLastY deltas. Tracks button up/down via usButtonFlags. Captures scroll wheel via RI_MOUSE_WHEEL.
  • Scroll Wheel: usButtonData is a signed short representing scroll amount. Accumulated per-device, consumed by ConsumeMouseScroll.

PadSetting

File: PadForge.Engine/Data/PadSetting.cs Namespace: PadForge.Engine.Data

Contains the complete mapping configuration for a device-to-slot assignment. All mapping properties are string-typed descriptors in the format: "Button N", "Axis N", "IHAxis N", "POV N Dir", "Slider N", or "" (unmapped). The class is declared partial.

PadSettings are stored separately from UserSettings and linked via PadSettingChecksum. Multiple UserSettings can share the same PadSetting when devices use identical mappings.

Numeric settings (dead zones, gains) are stored as strings for XML serialization consistency.

Identity

Property Type Serialization Default Description
PadSettingChecksum string [XmlElement] "" Checksum computed from all mapping/setting properties. Links UserSettings to PadSettings.

Button Mappings

Property Type Serialization Default
ButtonA string [XmlElement] ""
ButtonB string [XmlElement] ""
ButtonX string [XmlElement] ""
ButtonY string [XmlElement] ""
LeftShoulder string [XmlElement] ""
RightShoulder string [XmlElement] ""
ButtonBack string [XmlElement] ""
ButtonStart string [XmlElement] ""
ButtonGuide string [XmlElement] ""
LeftThumbButton string [XmlElement] ""
RightThumbButton string [XmlElement] ""

D-Pad Mappings

Property Type Serialization Default Description
DPad string [XmlElement] "" Combined D-Pad mapping. If set to a POV descriptor (e.g., "POV 0"), all four directions auto-extracted. Individual overrides take priority.
DPadUp string [XmlElement] ""
DPadDown string [XmlElement] ""
DPadLeft string [XmlElement] ""
DPadRight string [XmlElement] ""

Trigger Mappings and Settings

Property Type Serialization Default Description
LeftTrigger string [XmlElement] "" Mapping descriptor
RightTrigger string [XmlElement] "" Mapping descriptor
LeftTriggerDeadZone string [XmlElement] "0" 0-100%
RightTriggerDeadZone string [XmlElement] "0" 0-100%
LeftTriggerAntiDeadZone string [XmlElement] "0" 0-100%
RightTriggerAntiDeadZone string [XmlElement] "0" 0-100%
LeftTriggerMaxRange string [XmlElement] "100" 1-100%
RightTriggerMaxRange string [XmlElement] "100" 1-100%
LeftTriggerSensitivityCurve string [XmlElement] "0" -100 to 100 (0=linear, +100=exponential, -100=logarithmic)
RightTriggerSensitivityCurve string [XmlElement] "0" -100 to 100

Thumbstick Axis Mappings

Property Type Serialization Default Description
LeftThumbAxisX string [XmlElement] ""
LeftThumbAxisY string [XmlElement] ""
RightThumbAxisX string [XmlElement] ""
RightThumbAxisY string [XmlElement] ""
LeftThumbAxisXNeg string [XmlElement] "" Negative-direction (used when buttons map to bidirectional axes)
LeftThumbAxisYNeg string [XmlElement] ""
RightThumbAxisXNeg string [XmlElement] ""
RightThumbAxisYNeg string [XmlElement] ""

Dead Zone Settings

Property Type Serialization Default Description
LeftThumbDeadZoneX string [XmlElement] "0" Left stick dead zone X (0-100%)
LeftThumbDeadZoneY string [XmlElement] "0" Left stick dead zone Y
RightThumbDeadZoneX string [XmlElement] "0" Right stick dead zone X
RightThumbDeadZoneY string [XmlElement] "0" Right stick dead zone Y
LeftThumbDeadZoneShape string [XmlElement] "2" DeadZoneShape enum value. 2 = ScaledRadial.
RightThumbDeadZoneShape string [XmlElement] "2" DeadZoneShape enum value
LeftThumbAntiDeadZone string [XmlElement] "0" Legacy unified (0-100%). Use per-axis X/Y instead.
RightThumbAntiDeadZone string [XmlElement] "0" Legacy unified
LeftThumbAntiDeadZoneX string [XmlElement] "0" Left stick anti-dead zone X (0-100%)
LeftThumbAntiDeadZoneY string [XmlElement] "0" Left stick anti-dead zone Y
RightThumbAntiDeadZoneX string [XmlElement] "0" Right stick anti-dead zone X
RightThumbAntiDeadZoneY string [XmlElement] "0" Right stick anti-dead zone Y
LeftThumbLinear string [XmlElement] "0" Response curve (0-100%). 0=default, 100=fully linear.
RightThumbLinear string [XmlElement] "0"

Sensitivity Curve Settings

Property Type Serialization Default Description
LeftThumbSensitivityCurveX string [XmlElement] "0" -100 to 100 (0=linear, +100=exponential, -100=logarithmic)
LeftThumbSensitivityCurveY string [XmlElement] "0"
RightThumbSensitivityCurveX string [XmlElement] "0"
RightThumbSensitivityCurveY string [XmlElement] "0"

Max Range Settings

Property Type Serialization Default Description
LeftThumbMaxRangeX string [XmlElement] "100" Left stick X max range (1-100%). Symmetric/positive direction.
LeftThumbMaxRangeY string [XmlElement] "100"
RightThumbMaxRangeX string [XmlElement] "100"
RightThumbMaxRangeY string [XmlElement] "100"
LeftThumbMaxRangeXNeg string [XmlElement] null Left stick X negative (left) direction. Null = inherit symmetric.
LeftThumbMaxRangeYNeg string [XmlElement] null Left stick Y negative (down) direction
RightThumbMaxRangeXNeg string [XmlElement] null
RightThumbMaxRangeYNeg string [XmlElement] null

Stick Center Offset Calibration

Property Type Serialization Default Description
LeftThumbCenterOffsetX string [XmlElement] "0" -100 to 100%. Corrects stick drift before dead zone.
LeftThumbCenterOffsetY string [XmlElement] "0"
RightThumbCenterOffsetX string [XmlElement] "0"
RightThumbCenterOffsetY string [XmlElement] "0"

Force Feedback Settings

Property Type Serialization Default Description
ForceType string [XmlElement] "1" 0=Off, 1=SDL Rumble
ForceOverall string [XmlElement] "100" Overall strength 0-100%. Multiplier for both motors.
ForceSwapMotor string [XmlElement] "0" "0"=no swap, "1"=swap left/right motors
LeftMotorStrength string [XmlElement] "100" Left (low-frequency) motor strength 0-100%
RightMotorStrength string [XmlElement] "100" Right (high-frequency) motor strength 0-100%

Audio Rumble Settings

Property Type Serialization Default Description
AudioRumbleEnabled string [XmlElement] "0" Enable audio bass rumble. "0"=off, "1"=on.
AudioRumbleSensitivity string [XmlElement] "4" Bass detection sensitivity (1-20)
AudioRumbleCutoffHz string [XmlElement] "80" Low-pass cutoff frequency in Hz (40-200)
AudioRumbleLeftMotor string [XmlElement] "100" Left motor strength for audio rumble (0-100%)
AudioRumbleRightMotor string [XmlElement] "100" Right motor strength for audio rumble (0-100%)

Axis Configuration

Property Type Serialization Default Description
AxisToButtonThreshold string [XmlElement] "50" Threshold 0-100% for treating axis as button press
LeftThumbAxisXInvert string [XmlElement] "0" Invert left stick X. "0" or "1".
LeftThumbAxisYInvert string [XmlElement] "0"
RightThumbAxisXInvert string [XmlElement] "0"
RightThumbAxisYInvert string [XmlElement] "0"

vJoy Custom Mappings (Dictionary-based)

For custom vJoy configurations with arbitrary axis/button/POV counts. Keys use target names like "VJoyAxis0", "VJoyAxis0Neg", "VJoyBtn0", "VJoyPov0Up". Values are mapping descriptors.

Property Type Serialization Description
VJoyMappingEntries VJoyMappingEntry[] [XmlArray("VJoyMappings")] [XmlArrayItem("Map")] Serializable array for XML persistence
Method Signature Description
GetVJoyMapping string GetVJoyMapping(string key) Gets a vJoy mapping value by key. Returns "" if not found.
SetVJoyMapping void SetVJoyMapping(string key, string value) Sets a vJoy mapping value. Empty/null removes the key.
FlushVJoyMappings void FlushVJoyMappings() Flushes in-memory dictionary back to serializable array.

MIDI Custom Mappings (Dictionary-based)

Same pattern as vJoy. Keys: "MidiCC0", "MidiCC0Neg", "MidiNote0", etc.

Property Type Serialization Description
MidiMappingEntries VJoyMappingEntry[] [XmlArray("MidiMappings")] [XmlArrayItem("Map")] Serializable array
Method Signature Description
GetMidiMapping string GetMidiMapping(string key) Gets a MIDI mapping value.
SetMidiMapping void SetMidiMapping(string key, string value) Sets a MIDI mapping value.
FlushMidiMappings void FlushMidiMappings() Flushes dictionary to array.

KBM Custom Mappings (Dictionary-based)

Keys: "KbmKey41" (VK_A), "KbmMouseX", "KbmMouseXNeg", "KbmMBtn0", "KbmScroll", etc.

Property Type Serialization Description
KbmMappingEntries VJoyMappingEntry[] [XmlArray("KbmMappings")] [XmlArrayItem("Map")] Serializable array
Method Signature Description
GetKbmMapping string GetKbmMapping(string key) Gets a KBM mapping value.
SetKbmMapping void SetKbmMapping(string key, string value) Sets a KBM mapping value.
FlushKbmMappings void FlushKbmMappings() Flushes dictionary to array.

Game-Specific Override

Property Type Serialization Default Description
GameFileName string [XmlElement] "" Optional game executable name. Empty = global (applies to all games).

Computed Properties

Property Type Serialization Description
HasAnyMapping bool [XmlIgnore] Returns true if at least one mapping property has a non-empty descriptor (checks standard, vJoy, and MIDI).

Methods

Method Signature Description
MigrateAntiDeadZones void MigrateAntiDeadZones() Migrates legacy unified anti-dead zone values to per-axis X/Y properties. Call after deserialization.
MigrateMaxRangeDirections void MigrateMaxRangeDirections() Migrates symmetric max range to per-direction properties. If negative-direction is null/empty, copies the symmetric value.
ComputeChecksum string ComputeChecksum() Computes 8-character hex checksum (first 4 bytes of MD5) from all mapping/setting properties. vJoy/MIDI/KBM keys sorted for deterministic output.
UpdateChecksum void UpdateChecksum() Calls ComputeChecksum() and stores result in PadSettingChecksum.
ClearMappingDescriptors void ClearMappingDescriptors() Clears all mapping descriptors (standard, vJoy, MIDI) while preserving dead zone and FFB settings.
GetAllMappingDescriptors List<string> GetAllMappingDescriptors() Returns all non-empty mapping descriptor strings from standard, vJoy, and MIDI entries.
ToJson string ToJson(VirtualControllerType outputType, bool isCustomVJoy) Serializes to JSON for clipboard copy/paste. Embeds __OutputType and __IsCustomVJoy metadata for cross-layout support. Includes __VJoyMappings, __MidiMappings, __KbmMappings arrays if present.
FromJson static PadSetting FromJson(string json) Deserializes JSON to new PadSetting. Returns null on invalid JSON.
FromJson static PadSetting FromJson(string json, out VirtualControllerType, out bool) Same but also extracts source layout metadata.
CopyFrom void CopyFrom(PadSetting source) Copies all copyable properties. Deep-copies vJoy/MIDI/KBM mapping arrays. Invalidates cached dictionaries.
CopyFromTranslated void CopyFromTranslated(PadSetting source, VirtualControllerType srcType, bool srcCustom, VirtualControllerType tgtType, bool tgtCustom) Cross-layout copy with positional translation via MappingTranslation. Non-mapping settings copied directly; mapping properties translated by canonical position.
CloneDeep PadSetting CloneDeep() Deep copy including checksum and GameFileName.

VJoyMappingEntry

File: PadForge.Engine/Data/PadSetting.cs Namespace: PadForge.Engine.Data

Key-value entry for vJoy/MIDI/KBM mapping persistence in XML. Used by all three dictionary-based mapping systems.

public class VJoyMappingEntry
{
    [XmlAttribute] public string Key { get; set; } = "";
    [XmlAttribute] public string Value { get; set; } = "";
}

UserSetting

File: PadForge.Engine/Data/UserSetting.cs Namespace: PadForge.Engine.Data

Links a physical input device to a virtual controller slot and a mapping configuration. One UserSetting per device-to-slot assignment. Implements INotifyPropertyChanged.

Serialized Properties

Property Type Serialization Default Description
InstanceGuid Guid [XmlElement] Instance GUID of the physical device
InstanceName string [XmlElement] "" Human-readable instance name (for offline display)
ProductGuid Guid [XmlElement] Product GUID for matching when instance GUIDs change
ProductName string [XmlElement] "" Human-readable product name
MapTo int [XmlElement] -1 Virtual controller slot index (0-15). -1 = unmapped. Raises PropertyChanged on set.
PadSettingChecksum string [XmlElement] "" Links to a PadSetting record
IsEnabled bool [XmlElement] true Whether this mapping is enabled. Disabled = skipped in pipeline.
DateCreated DateTime [XmlElement] DateTime.Now Creation timestamp
DateUpdated DateTime [XmlElement] DateTime.Now Last modification timestamp

Runtime-Only Fields (Not Serialized)

Property Type Serialization Description
OutputState Gamepad [XmlIgnore] Mapped gamepad output state from Step 3. Written by background thread.
RawMappedState Gamepad [XmlIgnore] Raw mapped state: axis-selected and Y-negated but BEFORE center offset, dead zone, anti-dead zone, linear, and max range. Used by UI preview.
VJoyRawOutputState VJoyRawState [XmlIgnore] Mapped vJoy raw output for custom vJoy slots.
MidiRawOutputState MidiRawState [XmlIgnore] Mapped MIDI raw output for MIDI slots.
KbmRawOutputState KbmRawState [XmlIgnore] Mapped KBM raw output for KeyboardMouse slots.
_cachedPadSetting PadSetting [XmlIgnore] (internal) Cached PadSetting reference set by SettingsManager.

Methods

Method Signature Description
GetPadSetting PadSetting GetPadSetting() Returns the cached PadSetting.
SetPadSetting void SetPadSetting(PadSetting ps) Sets the cached PadSetting. Called by SettingsManager during load/sync.

UserDevice

File: PadForge.Engine/Data/UserDevice.cs Namespace: PadForge.Engine.Data

Data model for a single physical input device. Contains both serializable (settings-persisted) properties and runtime-only fields used during the input pipeline. Partial class. Implements INotifyPropertyChanged.

Serialized Identity Properties

Property Type Serialization Default Description
InstanceGuid Guid [XmlElement] Unique device instance GUID (deterministic from device path)
InstanceName string [XmlElement] "" Human-readable instance name (e.g., "Xbox Controller")
ProductGuid Guid [XmlElement] Product GUID in PIDVID format
ProductName string [XmlElement] "" Human-readable product name
VendorId ushort [XmlElement] 0 USB Vendor ID
ProdId ushort [XmlElement] 0 USB Product ID
DevRevision ushort [XmlElement] 0 USB Product Version / Revision
DevicePath string [XmlElement] "" Device file system path
SerialNumber string [XmlElement] "" Device serial number (e.g., Bluetooth MAC)

Serialized Capability Properties

Property Type Serialization Default Description
CapAxeCount int [XmlElement] 0 Number of axes
CapButtonCount int [XmlElement] 0 Number of buttons (gamepad-mapped count for gamepad devices)
RawButtonCount int [XmlElement] 0 Total raw joystick buttons before gamepad remapping
CapPovCount int [XmlElement] 0 Number of POV hat switches
CapType int [XmlElement] 0 InputDeviceType constant
HasGyro bool [XmlElement] false Gyroscope sensor support
HasAccel bool [XmlElement] false Accelerometer sensor support

Serialized Metadata

Property Type Serialization Default Description
DateCreated DateTime [XmlElement] DateTime.Now First creation timestamp
DateUpdated DateTime [XmlElement] DateTime.Now Last update timestamp
IsEnabled bool [XmlElement] true Whether device is enabled for mapping
IsHidden bool [XmlElement] false Whether device is hidden from UI
DisplayName string [XmlElement] "" User-assigned display name (overrides InstanceName if set)
HidHideEnabled bool [XmlElement] false Whether device is hidden from games via HidHide when assigned
ConsumeInputEnabled bool [XmlElement] false Whether mapped KB/mouse inputs are suppressed via hooks
ForceRawJoystickMode bool [XmlElement] false Bypass SDL gamepad remapping, read raw joystick indices
HidHideInstanceIds List<string> [XmlArray] [XmlArrayItem("Id")] new() Cached HID instance IDs for HidHide blacklisting (persisted for offline devices)

Runtime-Only Fields (Not Serialized)

Property Type Serialization Description
Device ISdlInputDevice [XmlIgnore] Live device handle for state reading and rumble. Set in Step 1.
IsOnline bool [XmlIgnore] Whether device is currently connected and opened.
InputState CustomInputState [XmlIgnore] Current input state snapshot. Written by Step 2. Atomic reference.
InputUpdates CustomInputUpdate[] [XmlIgnore] Buffered input changes since last poll cycle.
InputStateTime DateTime [XmlIgnore] Timestamp of current InputState.
OldInputState CustomInputState [XmlIgnore] Previous input state for change detection.
OldInputUpdates CustomInputUpdate[] [XmlIgnore] Previous buffered updates.
OldInputStateTime DateTime [XmlIgnore] Timestamp of previous OldInputState.
ActuatorCount int [XmlIgnore] Total number of FFB actuator axes.
DeviceObjects DeviceObjectItem[] [XmlIgnore] Device object metadata populated in Step 1.
ForceFeedbackState ForceFeedbackState [XmlIgnore] Per-device force feedback state tracker.

Computed Convenience Properties

Property Type Serialization Description
IsMouse bool [XmlIgnore] CapType == InputDeviceType.Mouse
IsKeyboard bool [XmlIgnore] CapType == InputDeviceType.Keyboard
HasForceFeedback bool [XmlIgnore] `ActuatorCount > 0
ResolvedName string [XmlIgnore] DisplayName if set, then InstanceName, then ProductName, then "(Unknown Device)"
StatusText string [XmlIgnore] "Disabled", "Online", or "Offline"

Methods

Method Signature Description
LoadInstance void LoadInstance(Guid instanceGuid, string instanceName, Guid productGuid, string productName) Populates identity properties.
LoadCapabilities void LoadCapabilities(int axeCount, int buttonCount, int povCount, int type) Populates capability properties.
LoadFromSdlDevice void LoadFromSdlDevice(SdlDeviceWrapper wrapper) Convenience method: calls LoadFromDevice + sets DevRevision.
LoadFromKeyboardDevice void LoadFromKeyboardDevice(SdlKeyboardWrapper wrapper) Populates from keyboard wrapper.
LoadFromMouseDevice void LoadFromMouseDevice(SdlMouseWrapper wrapper) Populates from mouse wrapper.
LoadFromWebDevice void LoadFromWebDevice(WebControllerDevice wrapper) Populates from web controller.
ClearRuntimeState void ClearRuntimeState() Clears Device, IsOnline, InputState, DeviceObjects, ForceFeedbackState. Preserves serializable properties.
NotifyStateChanged void NotifyStateChanged() Raises PropertyChanged for IsOnline, StatusText, InputState.
ToString string Returns "{ResolvedName} [{InstanceGuid:N}]".

DeadZoneShape

File: PadForge.Engine/Data/DeadZoneShape.cs Namespace: PadForge.Engine.Data

Deadzone algorithm for thumbstick axes.

public enum DeadZoneShape
{
    Axial = 0,              // Independent per-axis (square/cross shape). Legacy behavior.
    Radial = 1,             // Circular/elliptical magnitude check, no output rescaling.
    ScaledRadial = 2,       // Circular/elliptical with output rescaling (industry standard). DEFAULT.
    SlopedAxial = 3,        // Axis-dependent thresholds: DZ grows as other axis increases.
    SlopedScaledAxial = 4,  // Sloped axis-dependent with output rescaling.
    Hybrid = 5,             // Scaled Radial followed by Sloped Scaled Axial (best hybrid).
}

MappingTranslation

File: PadForge.Engine/Data/MappingTranslation.cs Namespace: PadForge.Engine.Data

Static class that translates mapping property names between different virtual controller layouts using positional equivalence.

Key Types

public enum ControlCategory { Button, Axis, AxisNeg, DPad }
public record MappingSlot(ControlCategory Category, int Position);

A MappingSlot represents a canonical position within a control category (e.g., "3rd button", "1st axis negative"). Translation works by converting a source property name to a MappingSlot, then converting that slot to the target layout's property name.

Public Methods

Method Signature Description
GetPosition static MappingSlot GetPosition(string propertyName, VirtualControllerType type, bool isCustomVJoy) Maps a layout-specific property name to its canonical MappingSlot
GetPropertyName static string GetPropertyName(MappingSlot slot, VirtualControllerType type, bool isCustomVJoy) Maps a canonical MappingSlot to a layout-specific property name
IsSameLayout static bool IsSameLayout(VirtualControllerType srcType, bool srcIsCustomVJoy, VirtualControllerType tgtType, bool tgtIsCustomVJoy) Returns true if source and target use the same property names (no translation needed)
GetLayoutLabel static string GetLayoutLabel(VirtualControllerType type, bool isCustomVJoy) Returns display label (e.g., "Xbox 360", "DualShock 4", "vJoy", "MIDI", "KB+M")

Supported Layouts

Layout Property Name Examples Notes
Gamepad (Xbox 360 / DS4 / vJoy gamepad preset) ButtonA, LeftThumbAxisX, DPadUp Xbox 360 and DS4 share the same property names. Maps: A=Btn0, B=Btn1, X=Btn2, Y=Btn3, LB=Btn4, RB=Btn5, Back=Btn6, Start=Btn7, LS=Btn8, RS=Btn9, Guide=Btn10. Axes: LX=0, LY=1, LT=2, RX=3, RY=4, RT=5.
vJoy Custom VJoyBtn0, VJoyAxis2, VJoyAxis2Neg, VJoyPov0Up Indexed by position. POV 0 only maps to D-Pad.
MIDI MidiNote0, MidiCC3, MidiCC3Neg No D-Pad support (returns null).
KB+M KbmMBtn0, KbmMouseX, KbmMouseXNeg, KbmKey20, KbmScroll Mouse buttons 0-4, keyboard VK codes, 3 mouse axes. D-Pad mapped to arrow keys.

Internal Layout Kinds

private enum LayoutKind { Gamepad, VJoyCustom, Midi, Kbm }
  • Xbox360, DS4, and vJoy gamepad preset all resolve to LayoutKind.Gamepad.
  • vJoy with isCustomVJoy=true resolves to LayoutKind.VJoyCustom.
  • IsSameLayout compares resolved LayoutKind values.

SDL3 P/Invoke

File: PadForge.Engine/Common/SDL3Minimal.cs Namespace: SDL3

Minimal SDL3 P/Invoke declarations for joystick, gamepad, keyboard, mouse, and haptic support. Only the functions actually used by PadForge are declared. Native library: "SDL3".

Init Flags

Constant Value Description
SDL_INIT_VIDEO 0x00000020 Required for keyboard/mouse
SDL_INIT_JOYSTICK 0x00000200 Joystick subsystem
SDL_INIT_HAPTIC 0x00001000 Haptic subsystem
SDL_INIT_GAMEPAD 0x00002000 Gamepad subsystem (was SDL_INIT_GAMECONTROLLER)

Hat Constants

Constant Value
SDL_HAT_CENTERED 0x00
SDL_HAT_UP 0x01
SDL_HAT_RIGHT 0x02
SDL_HAT_DOWN 0x04
SDL_HAT_LEFT 0x08
SDL_HAT_RIGHTUP 0x03
SDL_HAT_RIGHTDOWN 0x06
SDL_HAT_LEFTUP 0x09
SDL_HAT_LEFTDOWN 0x0C

Hint Strings

Constant Value Description
SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS "SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS" Allow events when app not focused
SDL_HINT_JOYSTICK_RAWINPUT "SDL_JOYSTICK_RAWINPUT" Do NOT set (conflicts with XInput enumeration)
SDL_HINT_JOYSTICK_XINPUT "SDL_JOYSTICK_XINPUT" Enables Xbox controller enumeration
SDL_HINT_JOYSTICK_HIDAPI_SWITCH2 "SDL_JOYSTICK_HIDAPI_SWITCH2" Switch 2 controller support
SDL_HINT_VIDEO_ALLOW_SCREENSAVER "SDL_VIDEO_ALLOW_SCREENSAVER" Allow screensaver

Enums

SDL_JoystickType:

Value Name
0 SDL_JOYSTICK_TYPE_UNKNOWN
1 SDL_JOYSTICK_TYPE_GAMEPAD
2 SDL_JOYSTICK_TYPE_WHEEL
3 SDL_JOYSTICK_TYPE_ARCADE_STICK
4 SDL_JOYSTICK_TYPE_FLIGHT_STICK
5 SDL_JOYSTICK_TYPE_DANCE_PAD
6 SDL_JOYSTICK_TYPE_GUITAR
7 SDL_JOYSTICK_TYPE_DRUM_KIT
8 SDL_JOYSTICK_TYPE_ARCADE_PAD
9 SDL_JOYSTICK_TYPE_THROTTLE
10 SDL_JOYSTICK_TYPE_COUNT

SDL_PowerState:

Value Name
-1 SDL_POWERSTATE_ERROR
0 SDL_POWERSTATE_UNKNOWN
1 SDL_POWERSTATE_ON_BATTERY
2 SDL_POWERSTATE_NO_BATTERY
3 SDL_POWERSTATE_CHARGING
4 SDL_POWERSTATE_CHARGED

Structs

SDL_GUID (16 bytes): data0 through data15. Methods: ToGuid() (converts to .NET Guid), ToByteArray().

SDL_HapticDirection (16 bytes): type (byte), dir0, dir1, dir2 (int).

SDL_HapticLeftRight (12 bytes): type, length, large_magnitude, small_magnitude.

SDL_HapticConstant (40 bytes): type, direction, length, delay, button, interval, level, attack_length, attack_level, fade_length, fade_level.

SDL_HapticPeriodic (44 bytes): type, direction, length, delay, button, interval, period, magnitude, offset, phase, attack_length, attack_level, fade_length, fade_level.

SDL_HapticCondition (68 bytes): type, direction, length, delay, button, interval, per-axis arrays (3 axes): right_sat[0-2], left_sat[0-2], right_coeff[0-2], left_coeff[0-2], deadband[0-2], center[0-2].

SDL_HapticRamp (44 bytes): type, direction, length, delay, button, interval, start, end, attack_length, attack_level, fade_length, fade_level.

SDL_HapticEffect (72 bytes, explicit layout): Union overlaying type, leftright, constant, periodic, condition, ramp all at FieldOffset(0).

Haptic Constants

Constant Value Description
SDL_HAPTIC_CONSTANT 1 << 0 Constant force
SDL_HAPTIC_SINE 1 << 1 Sine wave
SDL_HAPTIC_SQUARE 1 << 2 Square wave
SDL_HAPTIC_TRIANGLE 1 << 3 Triangle wave
SDL_HAPTIC_SAWTOOTHUP 1 << 4 Sawtooth up
SDL_HAPTIC_SAWTOOTHDOWN 1 << 5 Sawtooth down
SDL_HAPTIC_RAMP 1 << 6 Ramp
SDL_HAPTIC_SPRING 1 << 7 Spring condition
SDL_HAPTIC_DAMPER 1 << 8 Damper condition
SDL_HAPTIC_INERTIA 1 << 9 Inertia condition
SDL_HAPTIC_FRICTION 1 << 10 Friction condition
SDL_HAPTIC_LEFTRIGHT 1 << 11 Left/right dual-motor
SDL_HAPTIC_CUSTOM 1 << 15 Custom effect
SDL_HAPTIC_GAIN 1 << 16 Gain control supported
SDL_HAPTIC_AUTOCENTER 1 << 17 Auto-center supported
SDL_HAPTIC_INFINITY 0xFFFFFFFF Infinite duration
SDL_HAPTIC_POLAR 0 (byte) Polar direction type
SDL_HAPTIC_CARTESIAN 1 (byte) Cartesian direction type
SDL_HAPTIC_SPHERICAL 2 (byte) Spherical direction type
SDL_HAPTIC_STEERING_AXIS 3 (byte) Steering axis direction type

Gamepad Axis Constants

Constant Value Description
SDL_GAMEPAD_AXIS_LEFTX 0 Left stick X
SDL_GAMEPAD_AXIS_LEFTY 1 Left stick Y
SDL_GAMEPAD_AXIS_RIGHTX 2 Right stick X
SDL_GAMEPAD_AXIS_RIGHTY 3 Right stick Y
SDL_GAMEPAD_AXIS_LEFT_TRIGGER 4 Left trigger
SDL_GAMEPAD_AXIS_RIGHT_TRIGGER 5 Right trigger
SDL_GAMEPAD_AXIS_COUNT 6 Total axis count

Gamepad Button Constants

Constant Value Description
SDL_GAMEPAD_BUTTON_SOUTH 0 A
SDL_GAMEPAD_BUTTON_EAST 1 B
SDL_GAMEPAD_BUTTON_WEST 2 X
SDL_GAMEPAD_BUTTON_NORTH 3 Y
SDL_GAMEPAD_BUTTON_BACK 4 Back/Select
SDL_GAMEPAD_BUTTON_GUIDE 5 Guide/Home
SDL_GAMEPAD_BUTTON_START 6 Start
SDL_GAMEPAD_BUTTON_LEFT_STICK 7 Left stick click
SDL_GAMEPAD_BUTTON_RIGHT_STICK 8 Right stick click
SDL_GAMEPAD_BUTTON_LEFT_SHOULDER 9 Left bumper
SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER 10 Right bumper
SDL_GAMEPAD_BUTTON_DPAD_UP 11 D-pad up
SDL_GAMEPAD_BUTTON_DPAD_DOWN 12 D-pad down
SDL_GAMEPAD_BUTTON_DPAD_LEFT 13 D-pad left
SDL_GAMEPAD_BUTTON_DPAD_RIGHT 14 D-pad right
SDL_GAMEPAD_BUTTON_COUNT 21 Total button count

Sensor Type Constants

Constant Value Description
SDL_SENSOR_ACCEL 1 Accelerometer
SDL_SENSOR_GYRO 2 Gyroscope
SDL_SENSOR_ACCEL_L 3 Left accelerometer
SDL_SENSOR_GYRO_L 4 Left gyroscope
SDL_SENSOR_ACCEL_R 5 Right accelerometer
SDL_SENSOR_GYRO_R 6 Right gyroscope

Mouse Button Masks

Constant Value Description
SDL_BUTTON_LMASK 1 << 0 Left button
SDL_BUTTON_MMASK 1 << 1 Middle button
SDL_BUTTON_RMASK 1 << 2 Right button
SDL_BUTTON_X1MASK 1 << 3 X1 button
SDL_BUTTON_X2MASK 1 << 4 X2 button

VirtualKeyName Array

Static string[256] array providing human-readable names for Windows Virtual Key codes. Populated by BuildVirtualKeyNames(). Covers: Backspace, Tab, Enter, Shift/Ctrl/Alt, Escape, Space, navigation keys, 0-9, A-Z, LWin/RWin/Apps, Numpad 0-9 and operators, F1-F24, NumLock, ScrollLock, LShift/RShift/LCtrl/RCtrl/LAlt/RAlt, OEM keys (Semicolon, Equals, Comma, Minus, Period, Slash, Grave, Brackets, Backslash, Apostrophe). Used by SdlKeyboardWrapper.GetDeviceObjects() for button naming.

Core Function Categories

Lifecycle: SDL_Init, SDL_Quit, SDL_EnableScreenSaver, SDL_GetError, SDL_SetHint, SDL_free

Joystick Enumeration: SDL_GetJoysticks, SDL_GetJoystickGUIDForID, SDL_GetJoystickVendorForID, SDL_GetJoystickProductForID, SDL_GetJoystickProductVersionForID, SDL_GetJoystickTypeForID, SDL_GetJoystickNameForID, SDL_GetJoystickPathForID, SDL_IsGamepad

Gamepad Mappings: SDL_AddGamepadMappingsFromFile, SDL_AddGamepadMapping, GetGamepadMapping

Joystick Instance: SDL_OpenJoystick, SDL_CloseJoystick, SDL_GetJoystickID, SDL_JoystickConnected

Gamepad Instance: SDL_OpenGamepad, SDL_CloseGamepad, SDL_GetGamepadJoystick

Gamepad State: SDL_GetGamepadAxis, SDL_GetGamepadButton

Joystick State: SDL_UpdateJoysticks, SDL_PumpEvents, SDL_GetJoystickAxis, SDL_GetJoystickButton, SDL_GetJoystickHat, SDL_GetNumJoystickAxes, SDL_GetNumJoystickButtons, SDL_GetNumJoystickHats

Joystick Properties: SDL_GetJoystickName, SDL_GetJoystickVendor, SDL_GetJoystickProduct, SDL_GetJoystickProductVersion, SDL_GetJoystickType, SDL_GetJoystickPath, SDL_GetJoystickSerial, SDL_GetJoystickGUID, SDL_GetJoystickProperties, SDL_GetBooleanProperty, SDL_GetJoystickPowerInfo

Sensors: SDL_GamepadHasSensor, SDL_SetGamepadSensorEnabled, SDL_GetGamepadSensorData

Rumble: SDL_RumbleJoystick

Haptic: SDL_OpenHapticFromJoystick, SDL_CloseHaptic, SDL_GetHapticFeatures, SDL_CreateHapticEffect, SDL_UpdateHapticEffect, SDL_RunHapticEffect, SDL_StopHapticEffect, SDL_DestroyHapticEffect, SDL_SetHapticGain, SDL_GetNumHapticAxes

Keyboard: SDL_GetKeyboards, SDL_GetKeyboardNameForID, SDL_GetKeyboardState

Mouse: SDL_GetMice, SDL_GetMouseNameForID, SDL_GetMouseState, SDL_GetRelativeMouseState

Version: SDL_GetVersion, SDL_Linked_Version (returns (major, minor, patch) tuple)

Clone this wiki locally