2019-05-16 21:14:33 +02:00
# pragma once
2012-11-15 00:39:56 +01:00
2017-11-27 22:31:15 +01:00
# include <cmath>
2017-08-15 14:03:07 +02:00
# include <vector>
# include <memory>
2017-11-27 22:31:15 +01:00
# include "stdafx.h"
2018-09-18 12:07:33 +02:00
# include "Utilities/Config.h"
# include "Utilities/types.h"
2017-12-23 22:25:51 +01:00
# include "Emu/System.h"
2018-11-20 16:35:06 +01:00
# include "Emu/GameInfo.h"
2017-08-15 14:03:07 +02:00
2016-02-01 22:51:09 +01:00
// TODO: HLE info (constants, structs, etc.) should not be available here
2018-12-30 02:34:15 +01:00
enum SystemInfo
{
CELL_PAD_INFO_INTERCEPTED = 0x00000001
} ;
2012-11-15 00:39:56 +01:00
enum PortStatus
{
2014-04-04 15:25:38 +02:00
CELL_PAD_STATUS_DISCONNECTED = 0x00000000 ,
CELL_PAD_STATUS_CONNECTED = 0x00000001 ,
CELL_PAD_STATUS_ASSIGN_CHANGES = 0x00000002 ,
2012-11-15 00:39:56 +01:00
} ;
enum PortSettings
{
2014-04-04 15:25:38 +02:00
CELL_PAD_SETTING_PRESS_ON = 0x00000002 ,
CELL_PAD_SETTING_SENSOR_ON = 0x00000004 ,
CELL_PAD_SETTING_PRESS_OFF = 0x00000000 ,
CELL_PAD_SETTING_SENSOR_OFF = 0x00000000 ,
2012-11-15 00:39:56 +01:00
} ;
enum Digital1Flags
{
2014-04-04 15:25:38 +02:00
CELL_PAD_CTRL_LEFT = 0x00000080 ,
CELL_PAD_CTRL_DOWN = 0x00000040 ,
CELL_PAD_CTRL_RIGHT = 0x00000020 ,
CELL_PAD_CTRL_UP = 0x00000010 ,
CELL_PAD_CTRL_START = 0x00000008 ,
CELL_PAD_CTRL_R3 = 0x00000004 ,
CELL_PAD_CTRL_L3 = 0x00000002 ,
CELL_PAD_CTRL_SELECT = 0x00000001 ,
2012-11-15 00:39:56 +01:00
} ;
enum Digital2Flags
{
2014-04-04 15:25:38 +02:00
CELL_PAD_CTRL_SQUARE = 0x00000080 ,
CELL_PAD_CTRL_CROSS = 0x00000040 ,
CELL_PAD_CTRL_CIRCLE = 0x00000020 ,
CELL_PAD_CTRL_TRIANGLE = 0x00000010 ,
CELL_PAD_CTRL_R1 = 0x00000008 ,
CELL_PAD_CTRL_L1 = 0x00000004 ,
CELL_PAD_CTRL_R2 = 0x00000002 ,
CELL_PAD_CTRL_L2 = 0x00000001 ,
2012-11-15 00:39:56 +01:00
} ;
enum DeviceCapability
{
CELL_PAD_CAPABILITY_PS3_CONFORMITY = 0x00000001 , //PS3 Conformity Controller
CELL_PAD_CAPABILITY_PRESS_MODE = 0x00000002 , //Press mode supported
CELL_PAD_CAPABILITY_SENSOR_MODE = 0x00000004 , //Sensor mode supported
CELL_PAD_CAPABILITY_HP_ANALOG_STICK = 0x00000008 , //High Precision analog stick
CELL_PAD_CAPABILITY_ACTUATOR = 0x00000010 , //Motor supported
} ;
enum DeviceType
{
2014-04-04 15:25:38 +02:00
CELL_PAD_DEV_TYPE_STANDARD = 0 ,
CELL_PAD_DEV_TYPE_BD_REMOCON = 4 ,
CELL_PAD_DEV_TYPE_LDD = 5 ,
2012-11-15 00:39:56 +01:00
} ;
enum ButtonDataOffset
{
2014-04-04 15:25:38 +02:00
CELL_PAD_BTN_OFFSET_DIGITAL1 = 2 ,
CELL_PAD_BTN_OFFSET_DIGITAL2 = 3 ,
CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X = 4 ,
CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y = 5 ,
CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X = 6 ,
CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y = 7 ,
CELL_PAD_BTN_OFFSET_PRESS_RIGHT = 8 ,
CELL_PAD_BTN_OFFSET_PRESS_LEFT = 9 ,
CELL_PAD_BTN_OFFSET_PRESS_UP = 10 ,
CELL_PAD_BTN_OFFSET_PRESS_DOWN = 11 ,
CELL_PAD_BTN_OFFSET_PRESS_TRIANGLE = 12 ,
CELL_PAD_BTN_OFFSET_PRESS_CIRCLE = 13 ,
CELL_PAD_BTN_OFFSET_PRESS_CROSS = 14 ,
CELL_PAD_BTN_OFFSET_PRESS_SQUARE = 15 ,
CELL_PAD_BTN_OFFSET_PRESS_L1 = 16 ,
CELL_PAD_BTN_OFFSET_PRESS_R1 = 17 ,
CELL_PAD_BTN_OFFSET_PRESS_L2 = 18 ,
CELL_PAD_BTN_OFFSET_PRESS_R2 = 19 ,
CELL_PAD_BTN_OFFSET_SENSOR_X = 20 ,
CELL_PAD_BTN_OFFSET_SENSOR_Y = 21 ,
CELL_PAD_BTN_OFFSET_SENSOR_Z = 22 ,
CELL_PAD_BTN_OFFSET_SENSOR_G = 23 ,
2012-11-15 00:39:56 +01:00
} ;
2018-06-07 15:26:07 +02:00
enum
{
CELL_PAD_ACTUATOR_MAX = 2 ,
CELL_PAD_MAX_PORT_NUM = 7 ,
CELL_PAD_MAX_CAPABILITY_INFO = 32 ,
CELL_PAD_MAX_CODES = 64 ,
CELL_MAX_PADS = 127 ,
} ;
2012-11-15 00:39:56 +01:00
struct Button
{
u32 m_offset ;
u32 m_keyCode ;
u32 m_outKeyCode ;
2014-05-07 06:04:47 +02:00
u16 m_value ;
2012-11-15 00:39:56 +01:00
bool m_pressed ;
2013-08-26 16:18:59 +02:00
bool m_flush ;
2012-11-15 00:39:56 +01:00
Button ( u32 offset , u32 keyCode , u32 outKeyCode )
: m_pressed ( false )
2013-08-26 16:18:59 +02:00
, m_flush ( false )
2012-11-15 00:39:56 +01:00
, m_offset ( offset )
, m_keyCode ( keyCode )
, m_outKeyCode ( outKeyCode )
2014-05-07 06:04:47 +02:00
, m_value ( 0 )
2012-11-15 00:39:56 +01:00
{
}
} ;
2014-01-14 20:03:48 +01:00
struct AnalogStick
{
u32 m_offset ;
u32 m_keyCodeMin ;
u32 m_keyCodeMax ;
2014-05-07 06:04:47 +02:00
u16 m_value ;
2014-01-14 20:03:48 +01:00
AnalogStick ( u32 offset , u32 keyCodeMin , u32 keyCodeMax )
2014-05-09 00:20:16 +02:00
: m_offset ( offset )
2014-01-14 20:03:48 +01:00
, m_keyCodeMin ( keyCodeMin )
, m_keyCodeMax ( keyCodeMax )
2014-05-07 06:04:47 +02:00
, m_value ( 128 )
2014-01-14 20:03:48 +01:00
{
}
} ;
2017-04-29 03:02:28 +02:00
struct AnalogSensor
{
u32 m_offset ;
u16 m_value ;
AnalogSensor ( u32 offset , u16 value )
: m_offset ( offset )
, m_value ( value )
{ }
} ;
struct VibrateMotor
{
bool m_isLargeMotor ;
u16 m_value ;
VibrateMotor ( bool largeMotor , u16 value )
: m_isLargeMotor ( largeMotor )
, m_value ( value )
{ }
} ;
2012-11-15 00:39:56 +01:00
struct Pad
{
2014-05-21 02:56:36 +02:00
bool m_buffer_cleared ;
2012-11-15 00:39:56 +01:00
u32 m_port_status ;
u32 m_device_capability ;
u32 m_device_type ;
2019-02-25 18:47:16 +01:00
u32 m_class_type ;
2012-11-15 00:39:56 +01:00
2017-11-27 22:31:15 +01:00
// Cable State: 0 - 1 plugged in ?
u8 m_cable_state ;
2019-05-16 20:49:48 +02:00
// DS4: 0 - 9 while unplugged, 0 - 10 while plugged in, 11 charge complete
2017-11-27 22:31:15 +01:00
// XInput: 0 = Empty, 1 = Low, 2 = Medium, 3 = Full
u8 m_battery_level ;
2014-03-31 16:18:44 +02:00
std : : vector < Button > m_buttons ;
std : : vector < AnalogStick > m_sticks ;
2017-04-29 03:02:28 +02:00
std : : vector < AnalogSensor > m_sensors ;
std : : vector < VibrateMotor > m_vibrateMotors ;
2012-11-15 00:39:56 +01:00
2014-05-07 06:04:47 +02:00
//These hold bits for their respective buttons
u16 m_digital_1 ;
u16 m_digital_2 ;
//All sensors go from 0-255
u16 m_analog_left_x ;
u16 m_analog_left_y ;
u16 m_analog_right_x ;
u16 m_analog_right_y ;
2012-11-15 00:39:56 +01:00
u16 m_press_right ;
u16 m_press_left ;
u16 m_press_up ;
u16 m_press_down ;
u16 m_press_triangle ;
u16 m_press_circle ;
u16 m_press_cross ;
u16 m_press_square ;
u16 m_press_L1 ;
u16 m_press_L2 ;
u16 m_press_R1 ;
u16 m_press_R2 ;
2014-05-07 06:04:47 +02:00
//Except for these...0-1023
//~399 on sensor y is a level non moving controller
2012-11-15 00:39:56 +01:00
u16 m_sensor_x ;
u16 m_sensor_y ;
u16 m_sensor_z ;
u16 m_sensor_g ;
2019-02-25 18:47:16 +01:00
void Init ( u32 port_status , u32 device_capability , u32 device_type , u32 class_type )
2017-08-15 14:03:07 +02:00
{
m_port_status = port_status ;
m_device_capability = device_capability ;
m_device_type = device_type ;
2019-02-25 18:47:16 +01:00
m_class_type = class_type ;
2017-08-15 14:03:07 +02:00
}
2018-12-13 06:24:17 +01:00
Pad ( u32 port_status , u32 device_capability , u32 device_type )
2014-05-21 02:56:36 +02:00
: m_buffer_cleared ( true )
, m_port_status ( port_status )
2012-11-15 00:39:56 +01:00
, m_device_capability ( device_capability )
, m_device_type ( device_type )
2019-05-16 20:49:48 +02:00
, m_class_type ( 0 )
, m_cable_state ( 0 )
, m_battery_level ( 0 )
2012-11-15 00:39:56 +01:00
2014-05-07 06:04:47 +02:00
, m_digital_1 ( 0 )
, m_digital_2 ( 0 )
2013-12-31 12:10:24 +01:00
, m_analog_left_x ( 128 )
, m_analog_left_y ( 128 )
, m_analog_right_x ( 128 )
, m_analog_right_y ( 128 )
2012-11-15 00:39:56 +01:00
, m_press_right ( 0 )
, m_press_left ( 0 )
, m_press_up ( 0 )
, m_press_down ( 0 )
, m_press_triangle ( 0 )
, m_press_circle ( 0 )
, m_press_cross ( 0 )
, m_press_square ( 0 )
, m_press_L1 ( 0 )
, m_press_L2 ( 0 )
, m_press_R1 ( 0 )
, m_press_R2 ( 0 )
2017-04-29 03:02:28 +02:00
, m_sensor_x ( 512 )
2014-05-07 06:04:47 +02:00
, m_sensor_y ( 399 )
2017-04-29 03:02:28 +02:00
, m_sensor_z ( 512 )
, m_sensor_g ( 512 )
2012-11-15 00:39:56 +01:00
{
}
} ;
2017-12-23 22:25:51 +01:00
struct cfg_player final : cfg : : node
{
pad_handler def_handler = pad_handler : : null ;
2019-05-11 10:14:56 +02:00
cfg_player ( node * owner , const std : : string & name , pad_handler type ) : cfg : : node ( owner , name ) , def_handler ( type ) { }
2017-12-23 22:25:51 +01:00
cfg : : _enum < pad_handler > handler { this , " Handler " , def_handler } ;
cfg : : string device { this , " Device " , handler . to_string ( ) } ;
cfg : : string profile { this , " Profile " , " Default Profile " } ;
} ;
struct cfg_input final : cfg : : node
{
2018-11-20 16:35:06 +01:00
std : : string cfg_name = fs : : get_config_dir ( ) + " /config_input.yml " ;
2017-12-23 22:25:51 +01:00
cfg_player player1 { this , " Player 1 Input " , pad_handler : : keyboard } ;
cfg_player player2 { this , " Player 2 Input " , pad_handler : : null } ;
cfg_player player3 { this , " Player 3 Input " , pad_handler : : null } ;
cfg_player player4 { this , " Player 4 Input " , pad_handler : : null } ;
cfg_player player5 { this , " Player 5 Input " , pad_handler : : null } ;
cfg_player player6 { this , " Player 6 Input " , pad_handler : : null } ;
cfg_player player7 { this , " Player 7 Input " , pad_handler : : null } ;
cfg_player * player [ 7 ] { & player1 , & player2 , & player3 , & player4 , & player5 , & player6 , & player7 } ; // Thanks gcc!
2018-11-20 16:35:06 +01:00
bool load ( const std : : string & title_id = " " )
2017-12-23 22:25:51 +01:00
{
2019-06-01 15:52:39 +02:00
cfg_name = Emulator : : GetCustomInputConfigPath ( title_id ) ;
2018-11-20 16:35:06 +01:00
if ( ! fs : : is_file ( cfg_name ) )
2017-12-23 22:25:51 +01:00
{
2018-11-20 16:35:06 +01:00
cfg_name = fs : : get_config_dir ( ) + " /config_input.yml " ;
2017-12-23 22:25:51 +01:00
}
2018-11-20 16:35:06 +01:00
if ( fs : : file cfg_file { cfg_name , fs : : read } )
{
return from_string ( cfg_file . to_string ( ) ) ;
}
2017-12-23 22:25:51 +01:00
return false ;
2019-05-11 10:14:56 +02:00
}
2017-12-23 22:25:51 +01:00
2018-11-20 16:35:06 +01:00
void save ( const std : : string & title_id = " " )
2017-12-23 22:25:51 +01:00
{
2018-11-20 16:35:06 +01:00
if ( title_id . empty ( ) )
{
cfg_name = fs : : get_config_dir ( ) + " /config_input.yml " ;
}
else
{
2019-06-01 15:52:39 +02:00
cfg_name = Emulator : : GetCustomInputConfigPath ( title_id ) ;
2018-11-20 16:35:06 +01:00
}
2017-12-23 22:25:51 +01:00
fs : : file ( cfg_name , fs : : rewrite ) . write ( to_string ( ) ) ;
2019-05-11 10:14:56 +02:00
}
2017-12-23 22:25:51 +01:00
} ;
extern cfg_input g_cfg_input ;
struct pad_config final : cfg : : node
2017-11-27 22:31:15 +01:00
{
std : : string cfg_name = " " ;
cfg : : string ls_left { this , " Left Stick Left " , " " } ;
cfg : : string ls_down { this , " Left Stick Down " , " " } ;
cfg : : string ls_right { this , " Left Stick Right " , " " } ;
cfg : : string ls_up { this , " Left Stick Up " , " " } ;
cfg : : string rs_left { this , " Right Stick Left " , " " } ;
cfg : : string rs_down { this , " Right Stick Down " , " " } ;
cfg : : string rs_right { this , " Right Stick Right " , " " } ;
cfg : : string rs_up { this , " Right Stick Up " , " " } ;
cfg : : string start { this , " Start " , " " } ;
cfg : : string select { this , " Select " , " " } ;
cfg : : string ps { this , " PS Button " , " " } ;
cfg : : string square { this , " Square " , " " } ;
cfg : : string cross { this , " Cross " , " " } ;
cfg : : string circle { this , " Circle " , " " } ;
cfg : : string triangle { this , " Triangle " , " " } ;
cfg : : string left { this , " Left " , " " } ;
cfg : : string down { this , " Down " , " " } ;
cfg : : string right { this , " Right " , " " } ;
cfg : : string up { this , " Up " , " " } ;
cfg : : string r1 { this , " R1 " , " " } ;
cfg : : string r2 { this , " R2 " , " " } ;
cfg : : string r3 { this , " R3 " , " " } ;
cfg : : string l1 { this , " L1 " , " " } ;
cfg : : string l2 { this , " L2 " , " " } ;
cfg : : string l3 { this , " L3 " , " " } ;
2019-05-16 21:14:33 +02:00
cfg : : _int < 0 , 200 > lstickmultiplier { this , " Left Stick Multiplier " , 100 } ;
cfg : : _int < 0 , 200 > rstickmultiplier { this , " Right Stick Multiplier " , 100 } ;
2017-11-27 22:31:15 +01:00
cfg : : _int < 0 , 1000000 > lstickdeadzone { this , " Left Stick Deadzone " , 0 } ;
cfg : : _int < 0 , 1000000 > rstickdeadzone { this , " Right Stick Deadzone " , 0 } ;
cfg : : _int < 0 , 1000000 > ltriggerthreshold { this , " Left Trigger Threshold " , 0 } ;
cfg : : _int < 0 , 1000000 > rtriggerthreshold { this , " Right Trigger Threshold " , 0 } ;
cfg : : _int < 0 , 1000000 > padsquircling { this , " Pad Squircling Factor " , 0 } ;
cfg : : _int < 0 , 255 > colorR { this , " Color Value R " , 0 } ;
cfg : : _int < 0 , 255 > colorG { this , " Color Value G " , 0 } ;
cfg : : _int < 0 , 255 > colorB { this , " Color Value B " , 0 } ;
cfg : : _bool enable_vibration_motor_large { this , " Enable Large Vibration Motor " , true } ;
cfg : : _bool enable_vibration_motor_small { this , " Enable Small Vibration Motor " , true } ;
cfg : : _bool switch_vibration_motors { this , " Switch Vibration Motors " , false } ;
2018-11-17 04:17:32 +01:00
cfg : : _int < 0 , 255 > mouse_deadzone_x { this , " Mouse Deadzone X Axis " , 60 } ;
cfg : : _int < 0 , 255 > mouse_deadzone_y { this , " Mouse Deadzone Y Axis " , 60 } ;
2019-06-20 09:12:04 +02:00
cfg : : _int < 0 , 1000 > mouse_acceleration_x { this , " Mouse Acceleration X Axis " , 200 } ;
cfg : : _int < 0 , 1000 > mouse_acceleration_y { this , " Mouse Acceleration Y Axis " , 250 } ;
2018-11-17 04:17:32 +01:00
2018-12-29 15:56:18 +01:00
cfg : : _int < 0 , 100 > l_stick_lerp_factor { this , " Left Stick Lerp Factor " , 100 } ;
cfg : : _int < 0 , 100 > r_stick_lerp_factor { this , " Right Stick Lerp Factor " , 100 } ;
2019-02-25 18:47:16 +01:00
cfg : : _int < 0 , 5 > device_class_type { this , " Device Class Type " , 0 } ;
2017-11-27 22:31:15 +01:00
bool load ( )
{
if ( fs : : file cfg_file { cfg_name , fs : : read } )
{
return from_string ( cfg_file . to_string ( ) ) ;
}
return false ;
}
void save ( )
{
fs : : file ( cfg_name , fs : : rewrite ) . write ( to_string ( ) ) ;
}
bool exist ( )
{
return fs : : is_file ( cfg_name ) ;
}
} ;
2012-11-15 00:39:56 +01:00
class PadHandlerBase
{
protected :
2017-11-27 22:31:15 +01:00
static const u32 MAX_GAMEPADS = 7 ;
2017-12-10 10:41:55 +01:00
std : : array < bool , MAX_GAMEPADS > last_connection_status { { false , false , false , false , false , false , false } } ;
2018-01-17 02:23:50 +01:00
std : : string m_name_string ;
2018-01-16 14:07:57 +01:00
int m_max_devices = 0 ;
2017-11-27 22:31:15 +01:00
int m_trigger_threshold = 0 ;
int m_thumb_threshold = 0 ;
2019-05-09 21:31:43 +02:00
bool b_has_led = false ;
2017-11-27 22:31:15 +01:00
bool b_has_deadzones = false ;
bool b_has_rumble = false ;
2017-08-15 14:03:07 +02:00
bool b_has_config = false ;
2017-12-23 22:25:51 +01:00
std : : array < pad_config , MAX_GAMEPADS > m_pad_configs ;
2017-11-27 22:31:15 +01:00
template < typename T >
T lerp ( T v0 , T v1 , T t ) {
return std : : fma ( t , v1 , std : : fma ( - t , v0 , v0 ) ) ;
}
// Search an unordered map for a string value and return found keycode
2017-12-23 22:25:51 +01:00
int FindKeyCode ( std : : unordered_map < u32 , std : : string > map , const cfg : : string & name , bool fallback = true ) ;
2017-11-27 22:31:15 +01:00
2017-12-01 16:03:17 +01:00
// Search an unordered map for a string value and return found keycode
2017-12-23 22:25:51 +01:00
long FindKeyCode ( std : : unordered_map < u64 , std : : string > map , const cfg : : string & name , bool fallback = true ) ;
2017-12-01 16:03:17 +01:00
2017-12-01 14:21:27 +01:00
// Search an unordered map for a string value and return found keycode
2017-12-23 22:25:51 +01:00
int FindKeyCodeByString ( std : : unordered_map < u32 , std : : string > map , const std : : string & name , bool fallback = true ) ;
2017-12-01 14:21:27 +01:00
2017-12-23 22:25:51 +01:00
// Search an unordered map for a string value and return found keycode
long FindKeyCodeByString ( std : : unordered_map < u64 , std : : string > map , const std : : string & name , bool fallback = true ) ;
2017-11-27 22:31:15 +01:00
// Get new scaled value between 0 and 255 based on its minimum and maximum
2017-12-23 22:25:51 +01:00
float ScaleStickInput ( s32 raw_value , int minimum , int maximum ) ;
2017-11-27 22:31:15 +01:00
2017-12-01 10:16:48 +01:00
// Get new scaled value between -255 and 255 based on its minimum and maximum
2017-12-23 22:25:51 +01:00
float ScaleStickInput2 ( s32 raw_value , int minimum , int maximum ) ;
// Get normalized trigger value based on the range defined by a threshold
u16 NormalizeTriggerInput ( u16 value , int threshold ) ;
2017-12-01 10:16:48 +01:00
2017-11-27 22:31:15 +01:00
// normalizes a directed input, meaning it will correspond to a single "button" and not an axis with two directions
// the input values must lie in 0+
2019-05-16 21:14:33 +02:00
u16 NormalizeDirectedInput ( s32 raw_value , s32 threshold , s32 maximum ) ;
2017-11-27 22:31:15 +01:00
2019-05-16 21:14:33 +02:00
u16 NormalizeStickInput ( u16 raw_value , int threshold , int multiplier , bool ignore_threshold = false ) ;
2017-11-27 22:31:15 +01:00
// This function normalizes stick deadzone based on the DS3's deadzone, which is ~13%
// X and Y is expected to be in (-255) to 255 range, deadzone should be in terms of thumb stick range
// return is new x and y values in 0-255 range
2017-12-23 22:25:51 +01:00
std : : tuple < u16 , u16 > NormalizeStickDeadzone ( s32 inX , s32 inY , u32 deadzone ) ;
2017-11-27 22:31:15 +01:00
// get clamped value between 0 and 255
2017-12-23 22:25:51 +01:00
u16 Clamp0To255 ( f32 input ) ;
2017-11-27 22:31:15 +01:00
// get clamped value between 0 and 1023
2017-12-23 22:25:51 +01:00
u16 Clamp0To1023 ( f32 input ) ;
2017-11-27 22:31:15 +01:00
// input has to be [-1,1]. result will be [0,255]
2017-12-23 22:25:51 +01:00
u16 ConvertAxis ( float value ) ;
2017-11-27 22:31:15 +01:00
// The DS3, (and i think xbox controllers) give a 'square-ish' type response, so that the corners will give (almost)max x/y instead of the ~30x30 from a perfect circle
// using a simple scale/sensitivity increase would *work* although it eats a chunk of our usable range in exchange
// this might be the best for now, in practice it seems to push the corners to max of 20x20, with a squircle_factor of 8000
2017-12-23 22:25:51 +01:00
// This function assumes inX and inY is already in 0-255
std : : tuple < u16 , u16 > ConvertToSquirclePoint ( u16 inX , u16 inY , int squircle_factor ) ;
2012-11-15 00:39:56 +01:00
public :
2017-11-27 22:31:15 +01:00
s32 thumb_min = 0 ;
s32 thumb_max = 255 ;
s32 trigger_min = 0 ;
s32 trigger_max = 255 ;
s32 vibration_min = 0 ;
s32 vibration_max = 255 ;
2017-12-10 10:41:55 +01:00
u32 connected = 0 ;
2017-11-27 22:31:15 +01:00
2017-12-23 22:25:51 +01:00
pad_handler m_type = pad_handler : : null ;
2018-01-17 02:23:50 +01:00
std : : string name_string ( ) ;
2018-01-16 14:07:57 +01:00
int max_devices ( ) ;
2017-12-23 22:25:51 +01:00
bool has_config ( ) ;
bool has_rumble ( ) ;
bool has_deadzones ( ) ;
2019-05-09 21:31:43 +02:00
bool has_led ( ) ;
2017-12-23 22:25:51 +01:00
2018-11-20 16:35:06 +01:00
static std : : string get_config_dir ( pad_handler type , const std : : string & title_id = " " ) ;
static std : : string get_config_filename ( int i , const std : : string & title_id = " " ) ;
2017-12-23 22:25:51 +01:00
2019-05-11 10:14:56 +02:00
virtual bool Init ( ) { return true ; }
2017-12-23 22:25:51 +01:00
PadHandlerBase ( pad_handler type = pad_handler : : null ) ;
2014-04-15 16:12:15 +02:00
virtual ~ PadHandlerBase ( ) = default ;
2017-08-15 14:03:07 +02:00
//Sets window to config the controller(optional)
2019-05-11 10:14:56 +02:00
virtual void GetNextButtonPress ( const std : : string & /*padId*/ , const std : : function < void ( u16 , std : : string , std : : string , int [ ] ) > & /*callback*/ , const std : : function < void ( std : : string ) > & /*fail_callback*/ , bool /*get_blacklist*/ = false , const std : : vector < std : : string > & /*buttons*/ = { } ) { }
2019-05-26 09:43:04 +02:00
virtual void SetPadData ( const std : : string & /*padId*/ , u32 /*largeMotor*/ , u32 /*smallMotor*/ , s32 /*r*/ , s32 /*g*/ , s32 /*b*/ ) { }
2017-08-15 14:03:07 +02:00
//Return list of devices for that handler
virtual std : : vector < std : : string > ListDevices ( ) = 0 ;
//Callback called during pad_thread::ThreadFunc
virtual void ThreadProc ( ) = 0 ;
//Binds a Pad to a device
2017-12-23 22:25:51 +01:00
virtual bool bindPadToDevice ( std : : shared_ptr < Pad > /*pad*/ , const std : : string & /*device*/ ) = 0 ;
virtual void init_config ( pad_config * /*cfg*/ , const std : : string & /*name*/ ) = 0 ;
2017-11-27 22:31:15 +01:00
private :
2019-05-11 10:14:56 +02:00
virtual void TranslateButtonPress ( u64 /*keyCode*/ , bool & /*pressed*/ , u16 & /*val*/ , bool /*ignore_threshold*/ = false ) { }
2017-12-23 22:25:51 +01:00
protected :
void init_configs ( ) ;
2015-09-26 22:46:04 +02:00
} ;