1 #include "../ControllerInterface.h"
3 #ifdef CIFACE_USE_XINPUT
14 const char* const name
;
18 { "Button A", XINPUT_GAMEPAD_A
},
19 { "Button B", XINPUT_GAMEPAD_B
},
20 { "Button X", XINPUT_GAMEPAD_X
},
21 { "Button Y", XINPUT_GAMEPAD_Y
},
22 { "Pad N", XINPUT_GAMEPAD_DPAD_UP
},
23 { "Pad S", XINPUT_GAMEPAD_DPAD_DOWN
},
24 { "Pad W", XINPUT_GAMEPAD_DPAD_LEFT
},
25 { "Pad E", XINPUT_GAMEPAD_DPAD_RIGHT
},
26 { "Start", XINPUT_GAMEPAD_START
},
27 { "Back", XINPUT_GAMEPAD_BACK
},
28 { "Shoulder L", XINPUT_GAMEPAD_LEFT_SHOULDER
},
29 { "Shoulder R", XINPUT_GAMEPAD_RIGHT_SHOULDER
},
30 { "Thumb L", XINPUT_GAMEPAD_LEFT_THUMB
},
31 { "Thumb R", XINPUT_GAMEPAD_RIGHT_THUMB
}
34 static const char* const named_triggers
[] =
40 static const char* const named_axes
[] =
48 static const char* const named_motors
[] =
54 void Init( std::vector
<ControllerInterface::Device
*>& devices
)
56 XINPUT_CAPABILITIES caps
;
57 for ( int i
= 0; i
< 4; ++i
)
58 if ( ERROR_SUCCESS
== XInputGetCapabilities( i
, 0, &caps
) )
59 devices
.push_back( new Device( &caps
, i
) );
63 Device::Device( const XINPUT_CAPABILITIES
* const caps
, const unsigned int index
)
64 : m_index(index
), m_subtype(caps
->SubType
)
66 ZeroMemory( &m_state_out
, sizeof(m_state_out
) );
67 ZeroMemory( &m_current_state_out
, sizeof(m_current_state_out
) );
69 // XInputGetCaps seems to always claim all capabilities are supported
70 // but i will leave all this stuff in, incase m$ fixes xinput up a bit
72 // get supported buttons
73 for ( int i
= 0; i
< sizeof(named_buttons
)/sizeof(*named_buttons
); ++i
)
74 if ( named_buttons
[i
].bitmask
& caps
->Gamepad
.wButtons
)
75 AddInput( new Button( /*xinput_named_buttons[i].bitmask, */i
) );
77 // get supported triggers
78 for ( int i
= 0; i
< sizeof(named_triggers
)/sizeof(*named_triggers
); ++i
)
80 //BYTE val = (&caps->Gamepad.bLeftTrigger)[i]; // should be max value / msdn lies
81 if ( (&caps
->Gamepad
.bLeftTrigger
)[i
] )
82 AddInput( new Trigger( i
, 255 ) );
86 for ( int i
= 0; i
< sizeof(named_axes
)/sizeof(*named_axes
); ++i
)
88 //SHORT val = (&caps->Gamepad.sThumbLX)[i]; // xinput doesnt give the range / msdn is lier
89 if ( (&caps
->Gamepad
.sThumbLX
)[i
] )
91 // each axis gets a negative and a positive input instance associated with it
92 AddInput( new Axis( i
, -32768 ) );
93 AddInput( new Axis( i
, 32767 ) );
97 // get supported motors
98 for ( int i
= 0; i
< sizeof(named_motors
)/sizeof(*named_motors
); ++i
)
100 //WORD val = (&caps->Vibration.wLeftMotorSpeed)[i]; // should be max value / nope, more lies
101 if ( (&caps
->Vibration
.wLeftMotorSpeed
)[i
] )
102 AddOutput( new Motor(i
, 65535 ) );
109 void Device::ClearInputState()
111 ZeroMemory( &m_state_in
, sizeof(m_state_in
) );
114 std::string
Device::GetName() const
116 // why aren't these defined
117 // subtype doesn't seem to work, i tested with 2 diff arcade sticks, both were shown as gamepad
118 // ill leave it in anyway, maybe m$ will fix it
122 case XINPUT_DEVSUBTYPE_GAMEPAD
: return "Gamepad"; break;
123 case 0x02 /*XINPUT_DEVSUBTYPE_WHEEL*/ : return "Wheel"; break;
124 case 0x03 /*XINPUT_DEVSUBTYPE_ARCADE_STICK*/ : return "Arcade Stick"; break;
125 case 0x04 /*XINPUT_DEVSUBTYPE_FLIGHT_STICK*/ : return "Flight Stick"; break;
126 case 0x05 /*XINPUT_DEVSUBTYPE_DANCE_PAD*/ : return "Dance Pad"; break;
127 case 0x06 /*XINPUT_DEVSUBTYPE_GUITAR*/ : return "Guitar"; break;
128 case 0x08 /*XINPUT_DEVSUBTYPE_DRUM_KIT*/ : return "Drum Kit"; break;
129 default : return "Device"; break;
133 int Device::GetId() const
138 std::string
Device::GetSource() const
145 bool Device::UpdateInput()
147 return ( ERROR_SUCCESS
== XInputGetState( m_index
, &m_state_in
) );
150 bool Device::UpdateOutput()
152 // this if statement is to make rumble work better when multiple ControllerInterfaces are using the device
153 // only calls XInputSetState if the state changed
154 if ( memcmp( &m_state_out
, &m_current_state_out
, sizeof(m_state_out
) ) )
156 m_current_state_out
= m_state_out
;
157 return ( ERROR_SUCCESS
== XInputSetState( m_index
, &m_state_out
) );
163 // GET name/source/id
166 std::string
Device::Button::GetName() const
168 return named_buttons
[m_index
].name
;
171 std::string
Device::Axis::GetName() const
173 return std::string(named_axes
[m_index
]) + (m_range
<0 ? '-' : '+');
176 std::string
Device::Trigger::GetName() const
178 return named_triggers
[m_index
];
181 std::string
Device::Motor::GetName() const
183 return named_motors
[m_index
];
186 // get/set control state
188 ControlState
Device::GetInputState( const ControllerInterface::Device::Input
* const input
) const
190 return ((Input
*)input
)->GetState( &m_state_in
.Gamepad
);
193 void Device::SetOutputState( const ControllerInterface::Device::Output
* const output
, const ControlState state
)
195 return ((Output
*)output
)->SetState( state
, &m_state_out
);
200 ControlState
Device::Button::GetState( const XINPUT_GAMEPAD
* const gamepad
) const
202 return (gamepad
->wButtons
& named_buttons
[m_index
].bitmask
) > 0;
205 ControlState
Device::Trigger::GetState( const XINPUT_GAMEPAD
* const gamepad
) const
207 return ControlState((&gamepad
->bLeftTrigger
)[m_index
]) / m_range
;
210 ControlState
Device::Axis::GetState( const XINPUT_GAMEPAD
* const gamepad
) const
212 return std::max( 0.0f
, ControlState((&gamepad
->sThumbLX
)[m_index
]) / m_range
);
215 void Device::Motor::SetState( const ControlState state
, XINPUT_VIBRATION
* const vibration
)
217 (&vibration
->wLeftMotorSpeed
)[m_index
] = (WORD
)(state
* m_range
);