2023-07-09 19:22:29 -07:00
/*
2026-01-01 09:48:19 -08:00
Copyright ( C ) 1997 - 2026 Sam Lantinga < slouken @ libsdl . org >
2023-07-09 19:22:29 -07:00
This software is provided ' as - is ' , without any express or implied
warranty . In no event will the authors be held liable for any damages
arising from the use of this software .
Permission is granted to anyone to use this software for any purpose ,
including commercial applications , and to alter it and redistribute it
freely .
*/
/* Gamepad image */
2025-08-01 02:00:08 +02:00
# ifndef gamepadutils_h_
# define gamepadutils_h_
2023-07-09 19:22:29 -07:00
typedef struct GamepadImage GamepadImage ;
2023-07-13 22:57:32 -07:00
typedef enum
{
CONTROLLER_MODE_TESTING ,
CONTROLLER_MODE_BINDING ,
} ControllerDisplayMode ;
2023-07-15 00:00:53 -07:00
enum
{
SDL_GAMEPAD_ELEMENT_INVALID = - 1 ,
/* ... SDL_GamepadButton ... */
2024-09-11 08:08:18 -07:00
SDL_GAMEPAD_ELEMENT_AXIS_LEFTX_NEGATIVE = SDL_GAMEPAD_BUTTON_COUNT ,
2023-07-15 00:00:53 -07:00
SDL_GAMEPAD_ELEMENT_AXIS_LEFTX_POSITIVE ,
SDL_GAMEPAD_ELEMENT_AXIS_LEFTY_NEGATIVE ,
SDL_GAMEPAD_ELEMENT_AXIS_LEFTY_POSITIVE ,
SDL_GAMEPAD_ELEMENT_AXIS_RIGHTX_NEGATIVE ,
SDL_GAMEPAD_ELEMENT_AXIS_RIGHTX_POSITIVE ,
SDL_GAMEPAD_ELEMENT_AXIS_RIGHTY_NEGATIVE ,
SDL_GAMEPAD_ELEMENT_AXIS_RIGHTY_POSITIVE ,
SDL_GAMEPAD_ELEMENT_AXIS_LEFT_TRIGGER ,
SDL_GAMEPAD_ELEMENT_AXIS_RIGHT_TRIGGER ,
SDL_GAMEPAD_ELEMENT_AXIS_MAX ,
SDL_GAMEPAD_ELEMENT_NAME = SDL_GAMEPAD_ELEMENT_AXIS_MAX ,
SDL_GAMEPAD_ELEMENT_TYPE ,
SDL_GAMEPAD_ELEMENT_MAX ,
} ;
# define HIGHLIGHT_COLOR 224, 255, 255, SDL_ALPHA_OPAQUE
# define HIGHLIGHT_TEXTURE_MOD 224, 255, 255
# define PRESSED_COLOR 175, 238, 238, SDL_ALPHA_OPAQUE
# define PRESSED_TEXTURE_MOD 175, 238, 238
# define SELECTED_COLOR 224, 255, 224, SDL_ALPHA_OPAQUE
2025-06-13 14:01:52 -07:00
# define GYRO_COLOR_RED 255, 0, 0, SDL_ALPHA_OPAQUE
# define GYRO_COLOR_GREEN 0, 255, 0, SDL_ALPHA_OPAQUE
# define GYRO_COLOR_BLUE 0, 0, 255, SDL_ALPHA_OPAQUE
# define GYRO_COLOR_ORANGE 255, 128, 0, SDL_ALPHA_OPAQUE
/* Shared layout constants */
# define BUTTON_PADDING 12.0f
# define MINIMUM_BUTTON_WIDTH 96.0f
/* Symbol */
# define DEGREE_UTF8 "\xC2\xB0"
# define SQUARED_UTF8 "\xC2\xB2"
# define MICRO_UTF8 "\xC2\xB5"
2023-07-15 00:00:53 -07:00
/* Gamepad image display */
2023-07-09 19:22:29 -07:00
extern GamepadImage * CreateGamepadImage ( SDL_Renderer * renderer ) ;
2024-06-12 09:21:02 -07:00
extern void SetGamepadImagePosition ( GamepadImage * ctx , float x , float y ) ;
extern void GetGamepadImageArea ( GamepadImage * ctx , SDL_FRect * area ) ;
extern void GetGamepadTouchpadArea ( GamepadImage * ctx , SDL_FRect * area ) ;
2024-09-18 07:52:28 -07:00
extern void SetGamepadImageShowingFront ( GamepadImage * ctx , bool showing_front ) ;
2023-11-06 13:07:12 -08:00
extern SDL_GamepadType GetGamepadImageType ( GamepadImage * ctx ) ;
2023-07-13 22:57:32 -07:00
extern void SetGamepadImageDisplayMode ( GamepadImage * ctx , ControllerDisplayMode display_mode ) ;
2024-06-12 09:21:02 -07:00
extern float GetGamepadImageButtonWidth ( GamepadImage * ctx ) ;
extern float GetGamepadImageButtonHeight ( GamepadImage * ctx ) ;
extern float GetGamepadImageAxisWidth ( GamepadImage * ctx ) ;
extern float GetGamepadImageAxisHeight ( GamepadImage * ctx ) ;
2023-07-15 00:00:53 -07:00
extern int GetGamepadImageElementAt ( GamepadImage * ctx , float x , float y ) ;
2023-07-09 19:22:29 -07:00
extern void ClearGamepadImage ( GamepadImage * ctx ) ;
2024-09-18 07:52:28 -07:00
extern void SetGamepadImageElement ( GamepadImage * ctx , int element , bool active ) ;
2023-07-09 19:22:29 -07:00
extern void UpdateGamepadImageFromGamepad ( GamepadImage * ctx , SDL_Gamepad * gamepad ) ;
extern void RenderGamepadImage ( GamepadImage * ctx ) ;
extern void DestroyGamepadImage ( GamepadImage * ctx ) ;
2023-07-10 17:06:42 -07:00
/* Gamepad element display */
typedef struct GamepadDisplay GamepadDisplay ;
extern GamepadDisplay * CreateGamepadDisplay ( SDL_Renderer * renderer ) ;
2023-07-13 22:57:32 -07:00
extern void SetGamepadDisplayDisplayMode ( GamepadDisplay * ctx , ControllerDisplayMode display_mode ) ;
2024-06-12 09:21:02 -07:00
extern void SetGamepadDisplayArea ( GamepadDisplay * ctx , const SDL_FRect * area ) ;
2025-06-13 14:01:52 -07:00
extern void SetGamepadDisplayGyroDriftCorrection ( GamepadDisplay * ctx , float * gyro_drift_correction ) ;
2023-07-15 00:00:53 -07:00
extern int GetGamepadDisplayElementAt ( GamepadDisplay * ctx , SDL_Gamepad * gamepad , float x , float y ) ;
2024-09-18 07:52:28 -07:00
extern void SetGamepadDisplayHighlight ( GamepadDisplay * ctx , int element , bool pressed ) ;
2023-07-15 00:00:53 -07:00
extern void SetGamepadDisplaySelected ( GamepadDisplay * ctx , int element ) ;
2023-07-10 17:06:42 -07:00
extern void RenderGamepadDisplay ( GamepadDisplay * ctx , SDL_Gamepad * gamepad ) ;
extern void DestroyGamepadDisplay ( GamepadDisplay * ctx ) ;
2023-07-17 12:14:37 -07:00
/* Gamepad type display */
enum
{
SDL_GAMEPAD_TYPE_UNSELECTED = - 1
} ;
typedef struct GamepadTypeDisplay GamepadTypeDisplay ;
extern GamepadTypeDisplay * CreateGamepadTypeDisplay ( SDL_Renderer * renderer ) ;
2024-06-12 09:21:02 -07:00
extern void SetGamepadTypeDisplayArea ( GamepadTypeDisplay * ctx , const SDL_FRect * area ) ;
2023-07-17 12:14:37 -07:00
extern int GetGamepadTypeDisplayAt ( GamepadTypeDisplay * ctx , float x , float y ) ;
2024-09-18 07:52:28 -07:00
extern void SetGamepadTypeDisplayHighlight ( GamepadTypeDisplay * ctx , int type , bool pressed ) ;
2023-07-17 12:14:37 -07:00
extern void SetGamepadTypeDisplaySelected ( GamepadTypeDisplay * ctx , int type ) ;
extern void SetGamepadTypeDisplayRealType ( GamepadTypeDisplay * ctx , SDL_GamepadType type ) ;
extern void RenderGamepadTypeDisplay ( GamepadTypeDisplay * ctx ) ;
extern void DestroyGamepadTypeDisplay ( GamepadTypeDisplay * ctx ) ;
2023-07-10 17:06:42 -07:00
/* Joystick element display */
typedef struct JoystickDisplay JoystickDisplay ;
extern JoystickDisplay * CreateJoystickDisplay ( SDL_Renderer * renderer ) ;
2024-06-12 09:21:02 -07:00
extern void SetJoystickDisplayArea ( JoystickDisplay * ctx , const SDL_FRect * area ) ;
2023-07-15 00:00:53 -07:00
extern char * GetJoystickDisplayElementAt ( JoystickDisplay * ctx , SDL_Joystick * joystick , float x , float y ) ;
2024-09-18 07:52:28 -07:00
extern void SetJoystickDisplayHighlight ( JoystickDisplay * ctx , const char * element , bool pressed ) ;
2023-07-10 17:06:42 -07:00
extern void RenderJoystickDisplay ( JoystickDisplay * ctx , SDL_Joystick * joystick ) ;
extern void DestroyJoystickDisplay ( JoystickDisplay * ctx ) ;
2023-07-11 10:04:25 -07:00
/* Simple buttons */
typedef struct GamepadButton GamepadButton ;
extern GamepadButton * CreateGamepadButton ( SDL_Renderer * renderer , const char * label ) ;
2025-06-13 14:01:52 -07:00
extern void SetGamepadButtonLabel ( GamepadButton * ctx , const char * label ) ;
2024-06-12 09:21:02 -07:00
extern void SetGamepadButtonArea ( GamepadButton * ctx , const SDL_FRect * area ) ;
extern void GetGamepadButtonArea ( GamepadButton * ctx , SDL_FRect * area ) ;
2024-09-18 07:52:28 -07:00
extern void SetGamepadButtonHighlight ( GamepadButton * ctx , bool highlight , bool pressed ) ;
2024-06-12 09:21:02 -07:00
extern float GetGamepadButtonLabelWidth ( GamepadButton * ctx ) ;
extern float GetGamepadButtonLabelHeight ( GamepadButton * ctx ) ;
2024-09-18 07:52:28 -07:00
extern bool GamepadButtonContains ( GamepadButton * ctx , float x , float y ) ;
2023-07-11 10:04:25 -07:00
extern void RenderGamepadButton ( GamepadButton * ctx ) ;
extern void DestroyGamepadButton ( GamepadButton * ctx ) ;
2023-07-15 00:00:53 -07:00
2025-06-13 14:01:52 -07:00
/* Gyro element Display */
2025-07-21 16:39:32 -07:00
2025-07-22 11:01:57 -07:00
/* This is used as the initial noise tolerance threshold. It's set very close to zero to avoid divide by zero while we're evaluating the noise profile. Each controller may have a very different noise profile.*/
2025-07-21 16:39:32 -07:00
# define ACCELEROMETER_NOISE_THRESHOLD 1e-6f
2025-07-22 11:01:57 -07:00
/* The value below is based on observation of a Dualshock controller. Of all gamepads observed, the Dualshock (PS4) tends to have one of the noisiest accelerometers. Increase this threshold if a controller is failing to pass the noise profiling stage while stationary on a table. */
# define ACCELEROMETER_MAX_NOISE_G 0.075f
# define ACCELEROMETER_MAX_NOISE_G_SQ (ACCELEROMETER_MAX_NOISE_G * ACCELEROMETER_MAX_NOISE_G)
2025-07-21 16:39:32 -07:00
/* Gyro Calibration Phases */
typedef enum
{
GYRO_CALIBRATION_PHASE_OFF , /* Calibration has not yet been evaluated - signal to the user to put the controller on a flat surface before beginning the calibration process */
GYRO_CALIBRATION_PHASE_NOISE_PROFILING , /* Find the max accelerometer noise for a fixed period */
GYRO_CALIBRATION_PHASE_DRIFT_PROFILING , /* Find the drift while the accelerometer is below the accelerometer noise tolerance */
GYRO_CALIBRATION_PHASE_COMPLETE , /* Calibration has finished */
} EGyroCalibrationPhase ;
2025-06-13 14:01:52 -07:00
typedef struct Quaternion Quaternion ;
typedef struct GyroDisplay GyroDisplay ;
2025-07-26 19:03:54 +02:00
extern void InitCirclePoints3D ( void ) ;
2025-06-13 14:01:52 -07:00
extern GyroDisplay * CreateGyroDisplay ( SDL_Renderer * renderer ) ;
extern void SetGyroDisplayArea ( GyroDisplay * ctx , const SDL_FRect * area ) ;
2025-07-21 16:39:32 -07:00
extern void SetGamepadDisplayIMUValues ( GyroDisplay * ctx , float * gyro_drift_solution , float * euler_displacement_angles , Quaternion * gyro_quaternion , int reported_senor_rate_hz , int estimated_sensor_rate_hz , EGyroCalibrationPhase calibration_phase , float drift_calibration_progress_frac , float accelerometer_noise_sq , float accelerometer_noise_tolerance_sq ) ;
2025-06-13 14:01:52 -07:00
extern GamepadButton * GetGyroResetButton ( GyroDisplay * ctx ) ;
extern GamepadButton * GetGyroCalibrateButton ( GyroDisplay * ctx ) ;
extern void RenderGyroDisplay ( GyroDisplay * ctx , GamepadDisplay * gamepadElements , SDL_Gamepad * gamepad ) ;
extern void DestroyGyroDisplay ( GyroDisplay * ctx ) ;
2023-07-15 00:00:53 -07:00
/* Working with mappings and bindings */
/* Return whether a mapping has any bindings */
2024-09-18 07:52:28 -07:00
extern bool MappingHasBindings ( const char * mapping ) ;
2023-07-15 00:00:53 -07:00
/* Return true if the mapping has a controller name */
2024-09-18 07:52:28 -07:00
extern bool MappingHasName ( const char * mapping ) ;
2023-07-15 00:00:53 -07:00
/* Return the name from a mapping, which should be freed using SDL_free(), or NULL if there is no name specified */
extern char * GetMappingName ( const char * mapping ) ;
/* Set the name in a mapping, freeing the mapping passed in and returning a new mapping */
extern char * SetMappingName ( char * mapping , const char * name ) ;
2023-07-17 12:14:37 -07:00
/* Get the friendly string for an SDL_GamepadType */
extern const char * GetGamepadTypeString ( SDL_GamepadType type ) ;
2023-07-15 00:00:53 -07:00
/* Return the type from a mapping, which should be freed using SDL_free(), or NULL if there is no type specified */
2023-07-17 12:14:37 -07:00
extern SDL_GamepadType GetMappingType ( const char * mapping ) ;
2023-07-15 00:00:53 -07:00
2023-07-16 12:14:52 -07:00
/* Set the type in a mapping, freeing the mapping passed in and returning a new mapping */
2023-07-17 12:14:37 -07:00
extern char * SetMappingType ( char * mapping , SDL_GamepadType type ) ;
2023-07-15 00:00:53 -07:00
2023-07-16 12:14:52 -07:00
/* Return true if a mapping has this element bound */
2024-09-18 07:52:28 -07:00
extern bool MappingHasElement ( const char * mapping , int element ) ;
2023-07-16 12:14:52 -07:00
2023-07-15 00:00:53 -07:00
/* Get the binding for an element, which should be freed using SDL_free(), or NULL if the element isn't bound */
extern char * GetElementBinding ( const char * mapping , int element ) ;
2023-07-16 12:14:52 -07:00
/* Set the binding for an element, or NULL to clear it, freeing the mapping passed in and returning a new mapping */
2023-07-15 00:00:53 -07:00
extern char * SetElementBinding ( char * mapping , int element , const char * binding ) ;
2023-07-16 12:14:52 -07:00
/* Get the element for a binding, or SDL_GAMEPAD_ELEMENT_INVALID if that binding isn't used */
extern int GetElementForBinding ( char * mapping , const char * binding ) ;
2023-07-15 00:00:53 -07:00
/* Return true if a mapping contains this binding */
2024-09-18 07:52:28 -07:00
extern bool MappingHasBinding ( const char * mapping , const char * binding ) ;
2023-07-15 00:00:53 -07:00
/* Clear any previous binding */
extern char * ClearMappingBinding ( char * mapping , const char * binding ) ;
2025-08-01 02:00:08 +02:00
# endif /* gamepadutils_h_ */