// // Lol Engine // // Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net> // This program is free software; you can redistribute it and/or // modify it under the terms of the Do What The Fuck You Want To // Public License, Version 2, as published by Sam Hocevar. See // http://www.wtfpl.net/ for more details. // #if defined HAVE_CONFIG_H # include "config.h" #endif #if defined USE_SDL # if defined HAVE_SDL_SDL_H # include <SDL/SDL.h> # else # include <SDL.h> # endif #endif #include "core.h" #include "sdlinput.h" /* We force joystick polling because no events are received when * there is no SDL display (eg. on the Raspberry Pi). */ #define SDL_FORCE_POLL_JOYSTICK 1 namespace lol { /* * SDL Input implementation class */ class SdlInputData { friend class SdlInput; private: void Tick(float seconds); static ivec2 GetMousePos(); #if defined USE_SDL Array<SDL_Joystick *, Stick *> m_joysticks; #endif }; /* * Public SdlInput class */ SdlInput::SdlInput() : m_data(new SdlInputData()) { #if defined USE_SDL /* Enable Unicode translation of keyboard events */ SDL_EnableUNICODE(1); SDL_Init(SDL_INIT_TIMER | SDL_INIT_JOYSTICK); # if SDL_FORCE_POLL_JOYSTICK SDL_JoystickEventState(SDL_QUERY); # else SDL_JoystickEventState(SDL_ENABLE); # endif /* Register all the joysticks we can find, and let the input * system decide what it wants to track. */ for (int i = 0; i < SDL_NumJoysticks(); i++) { SDL_Joystick *sdlstick = SDL_JoystickOpen(i); /* Blacklist some devices: * - HDAPS, it's not a real joystick. * - X360 controllers, Xinput handles them better since * it won't think there is only one trigger axis. */ char const *name = SDL_JoystickName(i); if (strstr(name, "HDAPS") # if defined USE_XINPUT || strstr(name, "XBOX 360 For Windows") # endif || false) { SDL_JoystickClose(sdlstick); continue; } Stick *stick = Input::CreateStick(); stick->SetAxisCount(SDL_JoystickNumAxes(sdlstick)); stick->SetButtonCount(SDL_JoystickNumButtons(sdlstick)); /* It's possible to remap axes */ //stick->RemapAxis(4, 2); //stick->RemapAxis(2, 4); m_data->m_joysticks.Push(sdlstick, stick); } #endif m_gamegroup = GAMEGROUP_BEFORE; } SdlInput::~SdlInput() { #if defined USE_SDL /* Unregister all the joysticks we added */ while (m_data->m_joysticks.Count()) { SDL_JoystickClose(m_data->m_joysticks[0].m1); Input::DestroyStick(m_data->m_joysticks[0].m2); m_data->m_joysticks.Remove(0); } #endif delete m_data; } void SdlInput::TickGame(float seconds) { Entity::TickGame(seconds); #if !defined _WIN32 m_data->Tick(seconds); #endif } void SdlInput::TickDraw(float seconds) { Entity::TickDraw(seconds); #if defined _WIN32 m_data->Tick(seconds); #endif } void SdlInputData::Tick(float seconds) { #if defined USE_SDL /* Handle mouse input */ ivec2 mouse = SdlInputData::GetMousePos();; Input::SetMousePos(mouse); # if SDL_FORCE_POLL_JOYSTICK /* Pump all joystick events because no event is coming to us. */ SDL_JoystickUpdate(); for (int j = 0; j < m_joysticks.Count(); j++) { for (int i = 0; i < SDL_JoystickNumButtons(m_joysticks[j].m1); i++) m_joysticks[j].m2->SetButton(i, SDL_JoystickGetButton(m_joysticks[j].m1, i)); for (int i = 0; i < SDL_JoystickNumAxes(m_joysticks[j].m1); i++) m_joysticks[j].m2->SetAxis(i, (float)SDL_JoystickGetAxis(m_joysticks[j].m1, i) / 32768.f); } # endif /* Handle keyboard and WM events */ SDL_Event event; while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: Ticker::Shutdown(); break; #if 0 case SDL_KEYDOWN: if (event.key.keysym.unicode) fprintf(stderr, "%c (0x%04X)\n", event.key.keysym.unicode, event.key.keysym.unicode); break; #endif case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: { ivec2 newmouse = SdlInputData::GetMousePos(); if (newmouse != mouse) Input::SetMousePos(mouse = newmouse); if (event.type == SDL_MOUSEBUTTONDOWN) Input::SetMouseButton(event.button.button - 1); else Input::UnsetMouseButton(event.button.button - 1); break; } # if !SDL_FORCE_POLL_JOYSTICK case SDL_JOYAXISMOTION: m_joysticks[event.jaxis.which].m2->SetAxis(event.jaxis.axis, (float)event.jaxis.value / 32768.f); break; case SDL_JOYBUTTONUP: case SDL_JOYBUTTONDOWN: m_joysticks[event.jbutton.which].m2->SetButton(event.jbutton.button, event.jbutton.state); break; # endif } } /* Send the whole keyboard state to the input system */ #if 0 Uint8 *keystate = SDL_GetKeyState(nullptr); for (int i = 0; i < 256; i++) if (keystate[i]) Input::KeyPressed(i, seconds); #else UNUSED(seconds); #endif #endif } ivec2 SdlInputData::GetMousePos() { ivec2 ret(-1, -1); #if defined USE_SDL if (SDL_GetAppState() & SDL_APPMOUSEFOCUS) { SDL_GetMouseState(&ret.x, &ret.y); ret.y = Video::GetSize().y - 1 - ret.y; } #endif return ret; } } /* namespace lol */