@ -19,6 +19,8 @@ limitations under the License.
# include <SFML/System/Sleep.hpp>
# include <spdlog/spdlog.h>
# include "Overlay.h"
InputRedirector : : InputRedirector ( )
{
# ifdef _WIN32
@ -47,6 +49,34 @@ void InputRedirector::run()
{
run_ = vigem_connected_ ;
controller_thread_ = std : : thread ( & InputRedirector : : runLoop , this ) ;
# ifdef _WIN32
Overlay : : AddOverlayElem ( [ this ] ( ) {
ImGui : : SetNextWindowPos ( { 650 , 450 } , ImGuiCond_FirstUseEver ) ;
ImGui : : SetNextWindowSizeConstraints ( { 400 , 270 } , { 1000 , 1000 } ) ;
ImGui : : Begin ( " Controller Emulation " ) ;
int countcopy = max_controller_count_ ;
ImGui : : SliderInt ( " Max. controller count " , & countcopy , 0 , XUSER_MAX_COUNT ) ;
max_controller_count_ = countcopy ;
bool enable_rumbe_copy = enable_rumble_ ;
ImGui : : Checkbox ( " Enable Rumble " , & enable_rumbe_copy ) ;
enable_rumble_ = enable_rumbe_copy ;
if ( ImGui : : CollapsingHeader ( " Advanced " ) ) {
ImGui : : Text ( " GlosSI uses different USB-IDs for it's emulated controllers " ) ;
ImGui : : Text ( " This can cause issues with some games " ) ;
ImGui : : Text ( " When changing this, it's advised to also set Max. controller count " ) ;
ImGui : : Text ( " to prevent having multiple mirrored controllers plugged in " ) ;
ImGui : : Spacing ( ) ;
ImGui : : Text ( " If enabled, Device hiding can't show if a controller is emulated. " ) ;
bool use_real_copy = use_real_vid_pid_ ;
ImGui : : Checkbox ( " Use real USB-IDs " , & use_real_copy ) ;
if ( use_real_vid_pid_ ! = use_real_copy ) {
use_real_vid_pid_changed_ = true ;
}
use_real_vid_pid_ = use_real_copy ;
}
ImGui : : End ( ) ;
} ) ;
# endif
}
void InputRedirector : : stop ( )
@ -69,8 +99,19 @@ void InputRedirector::runLoop()
}
while ( run_ ) {
# ifdef _WIN32
for ( int i = 0 ; i < XUSER_MAX_COUNT ; i + + ) {
if ( use_real_vid_pid_changed_ ) {
// unplug all.
use_real_vid_pid_changed_ = false ;
for ( int i = 0 ; i < XUSER_MAX_COUNT ; i + + ) {
unplugVigemX360 ( i ) ;
}
}
if ( max_controller_count_ < XUSER_MAX_COUNT ) {
for ( int i = max_controller_count_ ; i < XUSER_MAX_COUNT ; i + + ) {
unplugVigemX360 ( i ) ;
}
}
for ( int i = 0 ; i < XUSER_MAX_COUNT & & i < max_controller_count_ ; i + + ) {
XINPUT_STATE state { } ;
if ( XInputGetState ( i , & state ) = = ERROR_SUCCESS ) {
if ( vt_x360_ [ i ] ! = nullptr ) {
@ -90,8 +131,12 @@ void InputRedirector::runLoop()
// Additonaly, Steam does pick up the emulated controller this way, and Hides it from our application
// but Steam ONLY does this if it is configured to support X360 controller rebinding!!!
// Otherwise, this application (GloSC/GlosSI) will pickup the emulated controller as well!
vigem_target_set_vid ( vt_x360_ [ i ] , 0x28de ) ; //VALVE_DIRECTINPUT_GAMEPAD_VID
// vigem_target_set_pid(vt_x360_[i], 0x11FF); //VALVE_DIRECTINPUT_GAMEPAD_PID
// This however is configurable withon GlosSI overlay;
// Multiple controllers can be worked around with by setting max count.
if ( ! use_real_vid_pid_ ) {
vigem_target_set_vid ( vt_x360_ [ i ] , 0x28de ) ; //VALVE_DIRECTINPUT_GAMEPAD_VID
// vigem_target_set_pid(vt_x360_[i], 0x11FF); //VALVE_DIRECTINPUT_GAMEPAD_PID
}
// TODO: MAYBE!: In a future version, use something like OpenXInput
//and filter out emulated controllers to support a greater amount of controllers simultaneously
@ -113,12 +158,7 @@ void InputRedirector::runLoop()
}
}
else {
if ( vt_x360_ [ i ] ! = nullptr ) {
if ( VIGEM_SUCCESS ( vigem_target_remove ( driver_ , vt_x360_ [ i ] ) ) ) {
spdlog : : info ( " Unplugged controller {}, {} " , i , vigem_target_get_index ( vt_x360_ [ i ] ) ) ;
vt_x360_ [ i ] = nullptr ;
}
}
unplugVigemX360 ( i ) ;
}
}
sf : : sleep ( sf : : milliseconds ( 1 ) ) ;
@ -130,6 +170,9 @@ void InputRedirector::runLoop()
# ifdef _WIN32
void InputRedirector : : controllerCallback ( PVIGEM_CLIENT client , PVIGEM_TARGET Target , UCHAR LargeMotor , UCHAR SmallMotor , UCHAR LedNumber , LPVOID UserData )
{
if ( ! enable_rumble_ ) {
return ;
}
XINPUT_VIBRATION vibration ;
ZeroMemory ( & vibration , sizeof ( XINPUT_VIBRATION ) ) ;
vibration . wLeftMotorSpeed = LargeMotor * 0xff ; //Controllers only use 1 byte, XInput-API uses two, ViGEm also only uses one, like the hardware does, so we have to multiply
@ -137,4 +180,14 @@ void InputRedirector::controllerCallback(PVIGEM_CLIENT client, PVIGEM_TARGET Tar
XInputSetState ( reinterpret_cast < int > ( UserData ) , & vibration ) ;
}
void InputRedirector : : unplugVigemX360 ( int idx )
{
if ( vt_x360_ [ idx ] ! = nullptr ) {
if ( VIGEM_SUCCESS ( vigem_target_remove ( driver_ , vt_x360_ [ idx ] ) ) ) {
spdlog : : info ( " Unplugged controller {}, {} " , idx , vigem_target_get_index ( vt_x360_ [ idx ] ) ) ;
vt_x360_ [ idx ] = nullptr ;
}
}
}
# endif