10 #include <input_manager.hpp>
14 static bool singleton_initialized =
false;
16 input_manager::~input_manager() {
17 singleton_initialized =
false;
26 gTask_manager(gTask_manager) {
28 if (singleton_initialized) {
29 throw std::runtime_error(
"The input manager cannot be initialized more than once!");
31 singleton_initialized =
true;
34 if (SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC) < 0) {
36 new message(LOG_ERROR, make_data<std::string>(
"Could not initialize gamepad subsystem!")));
41 keyboard_sdl_raw =
reinterpret_cast<bool *
>(
const_cast<uint8_t *
>(SDL_GetKeyboardState(&length)));
42 controls.buttons =
static_cast<bool *
>(malloc(
static_cast<size_t>(length)));
43 controls_prev_frame.buttons =
static_cast<bool *
>(malloc(
static_cast<size_t>(length)));
44 SDL_PollEvent(&event);
47 gMessage_bus.
subscribe(VIRTUAL_SCREEN_COORDINATES, &msg_sub);
48 gMessage_bus.
subscribe(REAL_SCREEN_COORDINATES, &msg_sub);
49 gMessage_bus.
subscribe(START_TEXT_INPUT, &msg_sub);
50 gMessage_bus.
subscribe(STOP_TEXT_INPUT, &msg_sub);
51 gMessage_bus.
subscribe(CLEAR_TEXT_STREAM, &msg_sub);
52 gMessage_bus.
subscribe(REGISTER_KEY, &msg_sub);
53 gMessage_bus.
subscribe(UNREGISTER_KEY, &msg_sub);
54 gMessage_bus.
subscribe(CONTROLLER_RUMBLE, &msg_sub);
55 gMessage_bus.
subscribe(SET_LEFT_JOYSTICK_HORIZONTAL_THRESHOLD, &msg_sub);
56 gMessage_bus.
subscribe(SET_LEFT_JOYSTICK_VERTICAL_THRESHOLD, &msg_sub);
57 gMessage_bus.
subscribe(SET_RIGHT_JOYSTICK_HORIZONTAL_THRESHOLD, &msg_sub);
58 gMessage_bus.
subscribe(SET_RIGHT_JOYSTICK_VERTICAL_THRESHOLD, &msg_sub);
59 gMessage_bus.
subscribe(SET_LEFT_TRIGGER_THRESHOLD, &msg_sub);
60 gMessage_bus.
subscribe(SET_RIGHT_TRIGGER_THRESHOLD, &msg_sub);
69 void input_manager::update_task(
void* mngr){
71 self->handle_messages();
96 void input_manager::take_input() {
97 while (SDL_PollEvent(&event) != 0) {
98 if (event.type == SDL_QUIT) {
101 if (event.type == SDL_MOUSEWHEEL) {
102 controls.mouse_scroll +=
event.wheel.y;
103 if (controls.mouse_scroll < 0) {
104 controls.mouse_scroll = 0;
106 gMessage_bus.
send_msg(
new message(MOUSE_SCROLL, controls.mouse_scroll));
108 if (event.type == SDL_TEXTINPUT) {
110 composition +=
event.edit.text;
112 while (!composition.empty() && composition.at(composition.size() - 1) == CONSOLE_TOGGLE_KEY) {
113 composition.pop_back();
115 gMessage_bus.
send_msg(
new message(TEXT_STREAM, make_data(composition)));
118 if (event.type == SDL_KEYDOWN) {
119 if (event.key.keysym.sym == SDLK_BACKSPACE) {
120 if (composition.length() > 0) {
121 composition.pop_back();
122 gMessage_bus.
send_msg(
new message(TEXT_STREAM, make_data(composition)));
126 if (event.type == SDL_MOUSEMOTION) {
127 SDL_GetMouseState(&controls.mouse_x, &controls.mouse_y);
128 controls.mouse_x =
static_cast<int>(
static_cast<float>(controls.mouse_x) * ratio_w);
129 controls.mouse_y =
static_cast<int>(
static_cast<float>(controls.mouse_y) * ratio_h);
131 if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
132 r_width =
event.window.data1;
133 r_height =
event.window.data2;
134 ratio_w =
static_cast<float>(v_width) /
static_cast<float>(r_width);
135 ratio_h =
static_cast<float>(v_height) /
static_cast<float>(r_height);
137 if (event.cdevice.type == SDL_CONTROLLERDEVICEADDED) {
138 SDL_GameController *controller = SDL_GameControllerOpen(
static_cast<int>(controllers.size()));
139 controllers.emplace_back(controller);
141 "Found a controller: " + std::string(SDL_GameControllerName(controller)))));
142 SDL_Haptic *haptic = SDL_HapticOpen(
static_cast<int32_t
>(controllers.size() - 1));
143 if (haptic !=
nullptr) {
144 if (SDL_HapticRumbleInit(haptic) < 0) {
146 "Unable to initialize rumble for controller " +
147 std::string(SDL_GameControllerName(controller)))));
150 "The controller \"" + std::string(SDL_GameControllerName(controller)) +
151 "\" supports haptic feedback")));
152 controllers_haptic.emplace_back(haptic);
156 "The controller \"" + std::string(SDL_GameControllerName(controller)) +
157 "\" does not support haptic feedback")));
160 if (event.cdevice.type == SDL_CONTROLLERDEVICEREMOVED) {
162 for (uint8_t i = 0; i < controllers.size() && i < 8; i++) {
163 if (SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(controllers.at(i))) == event.cdevice.which) {
167 SDL_GameControllerClose(controllers.at(number));
168 controllers.erase(controllers.begin() + number);
169 if (number < controllers_haptic.size()) {
170 SDL_HapticClose(controllers_haptic.at(number));
171 controllers_haptic.erase(controllers_haptic.begin() + number);
174 "Controller " + std::to_string(number + 1) +
" disconnected")));
178 memcpy(controls_prev_frame.buttons, controls.buttons, 512);
179 memcpy(controls.buttons, keyboard_sdl_raw, 512);
180 take_controller_input();
184 for (
auto i: registered_keys) {
185 if (key_event(i.first, ST::key_event::PRESS)) {
186 gMessage_bus.
send_msg(
new message(KEY_PRESSED,
static_cast<uint8_t
>(i.first)));
188 if (key_event(i.first, ST::key_event::HOLD)) {
189 gMessage_bus.
send_msg(
new message(KEY_HELD,
static_cast<uint8_t
>(i.first)));
191 if (key_event(i.first, ST::key_event::RELEASE)) {
192 gMessage_bus.
send_msg(
new message(KEY_RELEASED,
static_cast<uint8_t
>(i.first)));
197 void input_manager::take_mouse_input() {
199 uint32_t mouse_state = SDL_GetMouseState(
nullptr,
nullptr);
200 controls.buttons[1] = mouse_state & SDL_BUTTON(SDL_BUTTON_LEFT);
201 controls.buttons[2] = mouse_state & SDL_BUTTON(SDL_BUTTON_MIDDLE);
202 controls.buttons[3] = mouse_state & SDL_BUTTON(SDL_BUTTON_RIGHT);
205 if (controls.mouse_x != controls_prev_frame.mouse_x) {
206 gMessage_bus.
send_msg(
new message(MOUSE_X,
static_cast<uint32_t
>(controls.mouse_x)));
207 controls_prev_frame.mouse_x = controls.mouse_x;
209 if (controls.mouse_y != controls_prev_frame.mouse_y) {
210 gMessage_bus.
send_msg(
new message(MOUSE_Y,
static_cast<uint32_t
>(controls.mouse_y)));
211 controls_prev_frame.mouse_y = controls.mouse_y;
220 void input_manager::take_controller_input() {
221 controller_analog_inputs_prev_frame = controller_analog_inputs;
222 for (SDL_GameController *c: controllers) {
223 controls.buttons[
static_cast<uint8_t
>(ST::key::CONTROLLER_BUTTON_A)] = SDL_GameControllerGetButton(c,
224 SDL_CONTROLLER_BUTTON_A);
225 controls.buttons[
static_cast<uint8_t
>(ST::key::CONTROLLER_BUTTON_B)] = SDL_GameControllerGetButton(c,
226 SDL_CONTROLLER_BUTTON_B);
227 controls.buttons[
static_cast<uint8_t
>(ST::key::CONTROLLER_BUTTON_X)] = SDL_GameControllerGetButton(c,
228 SDL_CONTROLLER_BUTTON_X);
229 controls.buttons[
static_cast<uint8_t
>(ST::key::CONTROLLER_BUTTON_Y)] = SDL_GameControllerGetButton(c,
230 SDL_CONTROLLER_BUTTON_Y);
231 controls.buttons[
static_cast<uint8_t
>(ST::key::CONTROLLER_BUTTON_DPAD_UP)] = SDL_GameControllerGetButton(c,
232 SDL_CONTROLLER_BUTTON_DPAD_UP);
233 controls.buttons[
static_cast<uint8_t
>(ST::key::CONTROLLER_BUTTON_DPAD_DOWN)] = SDL_GameControllerGetButton(c,
234 SDL_CONTROLLER_BUTTON_DPAD_DOWN);
235 controls.buttons[
static_cast<uint8_t
>(ST::key::CONTROLLER_BUTTON_DPAD_LEFT)] = SDL_GameControllerGetButton(c,
236 SDL_CONTROLLER_BUTTON_DPAD_LEFT);
237 controls.buttons[
static_cast<uint8_t
>(ST::key::CONTROLLER_BUTTON_DPAD_RIGHT)] = SDL_GameControllerGetButton(c,
238 SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
239 controls.buttons[
static_cast<uint8_t
>(ST::key::CONTROLLER_BUTTON_LEFTSTICK)] = SDL_GameControllerGetButton(c,
240 SDL_CONTROLLER_BUTTON_LEFTSTICK);
241 controls.buttons[
static_cast<uint8_t
>(ST::key::CONTROLLER_BUTTON_RIGHTSTICK)] = SDL_GameControllerGetButton(c,
242 SDL_CONTROLLER_BUTTON_RIGHTSTICK);
243 controls.buttons[
static_cast<uint8_t
>(ST::key::CONTROLLER_BUTTON_LEFTSHOULDER)] = SDL_GameControllerGetButton(c,
244 SDL_CONTROLLER_BUTTON_LEFTSHOULDER);
245 controls.buttons[
static_cast<uint8_t
>(ST::key::CONTROLLER_BUTTON_RIGHTSHOULDER)] = SDL_GameControllerGetButton(
246 c, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER);
247 controls.buttons[
static_cast<uint8_t
>(ST::key::CONTROLLER_BUTTON_START)] = SDL_GameControllerGetButton(c,
248 SDL_CONTROLLER_BUTTON_START);
249 controls.buttons[
static_cast<uint8_t
>(ST::key::CONTROLLER_BUTTON_SELECT)] = SDL_GameControllerGetButton(c,
250 SDL_CONTROLLER_BUTTON_BACK);
252 controller_analog_inputs.left_trigger = SDL_GameControllerGetAxis(c, SDL_CONTROLLER_AXIS_TRIGGERLEFT);
253 controller_analog_inputs.right_trigger = SDL_GameControllerGetAxis(c, SDL_CONTROLLER_AXIS_TRIGGERRIGHT);
254 controller_analog_inputs.right_stick_horizontal = SDL_GameControllerGetAxis(c, SDL_CONTROLLER_AXIS_RIGHTX);
255 controller_analog_inputs.right_stick_vertical = SDL_GameControllerGetAxis(c, SDL_CONTROLLER_AXIS_RIGHTY);
256 controller_analog_inputs.left_stick_horizontal = SDL_GameControllerGetAxis(c, SDL_CONTROLLER_AXIS_LEFTX);
257 controller_analog_inputs.left_stick_vertical = SDL_GameControllerGetAxis(c, SDL_CONTROLLER_AXIS_LEFTY);
259 controls.buttons[
static_cast<uint8_t
>(ST::key::CONTROLLER_BUTTON_LEFT_TRIGGER)] =
260 controller_analog_inputs.left_trigger > 0;
261 controls.buttons[
static_cast<uint8_t
>(ST::key::CONTROLLER_BUTTON_RIGHT_TRIGGER)] =
262 controller_analog_inputs.right_trigger > 0;
267 controller_analog_inputs.left_trigger = (controller_analog_inputs.left_trigger >= left_trigger_threshold) *
268 controller_analog_inputs.left_trigger;
269 controller_analog_inputs.right_trigger = (controller_analog_inputs.right_trigger >= right_trigger_threshold) *
270 controller_analog_inputs.right_trigger;
272 if (controller_analog_inputs.left_trigger != controller_analog_inputs_prev_frame.left_trigger) {
273 gMessage_bus.
send_msg(
new message(LEFT_TRIGGER, controller_analog_inputs.left_trigger));
276 if (controller_analog_inputs.right_trigger != controller_analog_inputs_prev_frame.right_trigger) {
277 gMessage_bus.
send_msg(
new message(RIGHT_TRIGGER, controller_analog_inputs.right_trigger));
281 controller_analog_inputs.left_stick_vertical = (controller_analog_inputs.left_stick_vertical >
282 left_stick_vertical_threshold
283 || controller_analog_inputs.left_stick_vertical <
284 -left_stick_vertical_threshold) *
285 controller_analog_inputs.left_stick_vertical;
288 controller_analog_inputs.left_stick_horizontal = (controller_analog_inputs.left_stick_horizontal >
289 left_stick_horizontal_threshold
290 || controller_analog_inputs.left_stick_horizontal <
291 -left_stick_horizontal_threshold) *
292 controller_analog_inputs.left_stick_horizontal;
295 controller_analog_inputs.right_stick_horizontal = (controller_analog_inputs.right_stick_horizontal >
296 right_stick_horizontal_threshold
297 || controller_analog_inputs.right_stick_horizontal <
298 -right_stick_horizontal_threshold) *
299 controller_analog_inputs.right_stick_horizontal;
302 controller_analog_inputs.right_stick_vertical = (controller_analog_inputs.right_stick_vertical >
303 right_stick_vertical_threshold
304 || controller_analog_inputs.right_stick_vertical <
305 -right_stick_vertical_threshold) *
306 controller_analog_inputs.right_stick_vertical;
308 if (controller_analog_inputs.left_stick_vertical != controller_analog_inputs_prev_frame.left_stick_vertical) {
309 gMessage_bus.
send_msg(
new message(LEFT_STICK_VERTICAL, controller_analog_inputs.left_stick_vertical));
312 if (controller_analog_inputs.left_stick_horizontal != controller_analog_inputs_prev_frame.left_stick_horizontal) {
313 gMessage_bus.
send_msg(
new message(LEFT_STICK_HORIZONTAL, controller_analog_inputs.left_stick_horizontal));
316 if (controller_analog_inputs.right_stick_vertical != controller_analog_inputs_prev_frame.right_stick_vertical) {
317 gMessage_bus.
send_msg(
new message(RIGHT_STICK_VERTICAL, controller_analog_inputs.right_stick_vertical));
320 if (controller_analog_inputs.right_stick_horizontal != controller_analog_inputs_prev_frame.right_stick_horizontal) {
321 gMessage_bus.
send_msg(
new message(RIGHT_STICK_HORIZONTAL, controller_analog_inputs.right_stick_horizontal));
329 void input_manager::handle_messages() {
331 while (temp !=
nullptr) {
332 switch (temp->msg_name) {
333 case VIRTUAL_SCREEN_COORDINATES: {
334 auto data = temp->base_data0;
335 v_width = data & 0xffffU;
336 v_height = (data >> 16U) & 0xffffU;
337 ratio_w =
static_cast<float>(v_width) /
static_cast<float>(r_width);
338 ratio_h =
static_cast<float>(v_height) /
static_cast<float>(r_height);
341 case REAL_SCREEN_COORDINATES: {
342 auto data = temp->base_data0;
343 r_width = data & 0xffffU;
344 r_height = (data >> 16U) & 0xffffU;
345 ratio_w =
static_cast<float>(v_width) /
static_cast<float>(r_width);
346 ratio_h =
static_cast<float>(v_height) /
static_cast<float>(r_height);
349 case START_TEXT_INPUT:
352 case STOP_TEXT_INPUT:
355 case CLEAR_TEXT_STREAM:
359 auto key_val =
static_cast<ST::key
>(temp->base_data0);
360 ++registered_keys[key_val];
363 case UNREGISTER_KEY: {
364 auto key_val =
static_cast<ST::key
>(temp->base_data0);
365 if (registered_keys[key_val] > 1) {
366 --registered_keys[key_val];
367 }
else if (registered_keys[key_val] == 1) {
368 registered_keys.erase(key_val);
372 case CONTROLLER_RUMBLE: {
373 if (!controllers.empty() && !controllers_haptic.empty()) {
374 float strength = *
reinterpret_cast<float *
>(&temp->base_data0);
375 uint16_t duration = temp->base_data1;
376 for (SDL_Haptic *haptic: controllers_haptic) {
377 SDL_HapticRumblePlay(haptic, strength, duration);
383 uint8_t left_stick_hor_check = (temp->msg_name == SET_LEFT_JOYSTICK_HORIZONTAL_THRESHOLD);
384 this->left_stick_horizontal_threshold = left_stick_hor_check *
static_cast<int16_t
>(temp->base_data0) +
386 !left_stick_hor_check * this->left_stick_horizontal_threshold;
388 uint8_t left_stick_ver_check = (temp->msg_name == SET_LEFT_JOYSTICK_VERTICAL_THRESHOLD);
389 this->left_stick_vertical_threshold = left_stick_ver_check *
static_cast<int16_t
>(temp->base_data0) +
391 !left_stick_ver_check * this->left_stick_vertical_threshold;
393 uint8_t right_stick_hor_check = (temp->msg_name == SET_RIGHT_JOYSTICK_HORIZONTAL_THRESHOLD);
394 this->right_stick_horizontal_threshold =
395 right_stick_hor_check *
static_cast<int16_t
>(temp->base_data0) +
397 !right_stick_hor_check * this->right_stick_horizontal_threshold;
399 uint8_t right_stick_ver_check = (temp->msg_name == SET_RIGHT_JOYSTICK_VERTICAL_THRESHOLD);
400 this->right_stick_vertical_threshold = right_stick_ver_check *
static_cast<int16_t
>(temp->base_data0) +
402 !right_stick_ver_check * this->right_stick_vertical_threshold;
404 uint8_t right_trigger_check = (temp->msg_name == SET_RIGHT_TRIGGER_THRESHOLD);
405 this->right_trigger_threshold = right_trigger_check *
static_cast<int16_t
>(temp->base_data0) +
407 !right_trigger_check * this->right_trigger_threshold;
409 uint8_t left_trigger_check = (temp->msg_name == SET_LEFT_TRIGGER_THRESHOLD);
410 this->left_trigger_threshold = left_trigger_check *
static_cast<int16_t
>(temp->base_data0) +
412 !left_trigger_check * this->left_trigger_threshold;
427 bool input_manager::key_event(ST::key arg, ST::key_event k_event)
const {
428 auto key =
static_cast<uint8_t
>(arg);
429 return (controls.buttons[key] ^ (k_event == ST::key_event::RELEASE))
430 && (controls_prev_frame.buttons[key] ^ (k_event == ST::key_event::PRESS));
An object representing a task to be run by the task manager.
The central messaging system of the engine. All subsystem make extensive use of it.
void subscribe(uint8_t msg, subscriber *sub)
void send_msg(message *msg)
A message object passed around in the message bus. Holds anything created with make_data<>().
message * get_next_message()
The Task Manager handles all things multi-threaded in the engine.
void start_task_lockfree(ST::task *arg)