1 #include "gamecontroller.h"
2 #include "gamecontroller_platform.h"
3 #include <msp/core/application.h>
4 #include <msp/strings/format.h>
11 vector<unsigned> GameController::Private::detected_controllers;
13 GameController::GameController(unsigned index):
14 Device(GAME_CONTROLLER)
18 if(index>=Private::detected_controllers.size())
19 throw device_not_available(format("GameController(%d)", index));
21 unsigned user_index = Private::detected_controllers[index];
24 DWORD err = XInputGetState(user_index, &state);
25 if(err!=ERROR_SUCCESS)
26 throw device_not_available(format("GameController(%d)", index));
29 priv->index = user_index;
30 priv->update_state(*this, state, false);
32 name = format("Controller %d", user_index);
35 GameController::~GameController()
37 use_event_dispatcher(nullptr);
42 unsigned GameController::detect()
44 Private::detected_controllers.clear();
47 for(unsigned i=0; i<XUSER_MAX_COUNT; ++i)
48 if(XInputGetState(i, &state)==ERROR_SUCCESS)
49 Private::detected_controllers.push_back(i);
52 n_detected_controllers = Private::detected_controllers.size();
54 return Private::detected_controllers.size();
57 void GameController::use_event_dispatcher(IO::EventDispatcher *ed)
60 event_disp->remove(*priv->event_pipe);
67 priv->event_pipe = new IO::Pipe;
68 priv->event_pipe->signal_data_available.connect(sigc::mem_fun(this, static_cast<void (GameController::*)()>(&GameController::tick)));
69 priv->timer_slot = &GameControllerTimerThread::add_slot();
70 priv->timer_slot->signal_timeout.connect(sigc::mem_fun(priv, &Private::generate_event));
73 event_disp->add(*priv->event_pipe);
75 else if(priv->event_pipe)
77 GameControllerTimerThread::remove_slot(*priv->timer_slot);
78 priv->timer_slot = nullptr;
79 delete priv->event_pipe;
80 priv->event_pipe = nullptr;
84 void GameController::tick()
89 priv->event_pipe->read(buf, sizeof(buf));
93 DWORD err = XInputGetState(priv->index, &state);
94 if(err==ERROR_SUCCESS)
95 priv->update_state(*this, state, true);
98 void GameController::tick(const Time::TimeDelta &)
104 bool GameController::Private::generate_event()
110 void GameController::Private::update_state(GameController &ctrl, const XINPUT_STATE &state, bool event)
112 if(state.dwPacketNumber==last_packet_number)
114 last_packet_number = state.dwPacketNumber;
116 ctrl.set_axis_value(0, state.Gamepad.sThumbLX/32768.0, event);
117 ctrl.set_axis_value(1, -state.Gamepad.sThumbLY/32768.0, event);
118 ctrl.set_axis_value(3, state.Gamepad.sThumbRX/32768.0, event);
119 ctrl.set_axis_value(4, -state.Gamepad.sThumbRY/32768.0, event);
120 WORD dpad_x = state.Gamepad.wButtons&(XINPUT_GAMEPAD_DPAD_LEFT|XINPUT_GAMEPAD_DPAD_RIGHT);
121 WORD dpad_y = state.Gamepad.wButtons&(XINPUT_GAMEPAD_DPAD_UP|XINPUT_GAMEPAD_DPAD_DOWN);
122 ctrl.set_axis_value(6, (dpad_x==XINPUT_GAMEPAD_DPAD_LEFT ? -1 : dpad_x==XINPUT_GAMEPAD_DPAD_RIGHT ? 1 : 0), event);
123 ctrl.set_axis_value(7, (dpad_y==XINPUT_GAMEPAD_DPAD_UP ? -1 : dpad_y==XINPUT_GAMEPAD_DPAD_DOWN ? 1 : 0), event);
124 ctrl.set_button_state(0, state.Gamepad.wButtons&XINPUT_GAMEPAD_A, event);
125 ctrl.set_button_state(1, state.Gamepad.wButtons&XINPUT_GAMEPAD_B, event);
126 ctrl.set_button_state(2, state.Gamepad.wButtons&XINPUT_GAMEPAD_X, event);
127 ctrl.set_button_state(3, state.Gamepad.wButtons&XINPUT_GAMEPAD_Y, event);
128 ctrl.set_button_state(4, state.Gamepad.wButtons&XINPUT_GAMEPAD_LEFT_SHOULDER, event);
129 ctrl.set_button_state(5, state.Gamepad.wButtons&XINPUT_GAMEPAD_RIGHT_SHOULDER, event);
130 ctrl.set_button_state(6, state.Gamepad.wButtons&XINPUT_GAMEPAD_BACK, event);
131 ctrl.set_button_state(7, state.Gamepad.wButtons&XINPUT_GAMEPAD_START, event);
132 ctrl.set_button_state(8, state.Gamepad.wButtons&XINPUT_GAMEPAD_LEFT_THUMB, event);
133 ctrl.set_button_state(9, state.Gamepad.wButtons&XINPUT_GAMEPAD_RIGHT_THUMB, event);
137 GameControllerTimerThread *GameControllerTimerThread::thread = nullptr;
139 GameControllerTimerThread::GameControllerTimerThread():
140 Thread("GameController")
145 GameControllerTimerThread::~GameControllerTimerThread()
147 timer.add(Time::zero);
151 Time::Timer::Slot &GameControllerTimerThread::add_slot()
154 thread = new GameControllerTimerThread;
156 return thread->timer.add(100*Time::msec);
159 void GameControllerTimerThread::remove_slot(Time::Timer::Slot &slot)
161 thread->timer.cancel(slot);
162 if(!--thread->n_users)
164 thread->timer.add(Time::zero);
170 void GameControllerTimerThread::main()