Kraxie Posted April 18, 2015 Share Posted April 18, 2015 Hi! So, I have been looking around for a way to make a controller or gamepad work in Leadwerks, but most of the posts here seems to be outdated... Have anyone actually got this working right? Thanks! Regards, KraXarN Quote Windows 7 | Intel Core i7-4790K | 16 GB RAM | Nvidia GTX 980 Link to comment Share on other sites More sharing options...
Skrakle Posted April 18, 2015 Share Posted April 18, 2015 I've been writing a c++ class using SDL in the last few days and it's almost finished. There were issues with my xbox controller, keys aren't mapped the same as regular controllers but i managed to fix it and implement a button mapping feature and now it behaves like normal controllers. It can automatically re-acquire controllers that are unplugged/replugged. I will post the code once i'ts done, after that, i'll add lua support. 1 Quote Link to comment Share on other sites More sharing options...
Skrakle Posted April 18, 2015 Share Posted April 18, 2015 (edited) Here's the game controller class i just finished. Copy the SDL folder in your source directory (currently SDL2-2.0.3). Include SDL2.lib in your project and copy SDL2.DLL in the same folder as your executable. Edit: Added 2 parameters in the init method to enable/disable auto reacquire. App.h #pragma once #include "Leadwerks.h" #include "Game_Controller.h" using namespace Leadwerks; class App { public: Leadwerks::Window* window; Context* context; World* world; Camera* camera; Game_Controller* joysticks[8]; App(); virtual ~App(); virtual bool Start(); virtual bool Loop(); }; App.cpp #include "App.h" using namespace Leadwerks; App::App() : window(NULL), context(NULL), world(NULL), camera(NULL) {} App::~App() { delete world; delete window; } bool App::Start() { window = Leadwerks::Window::Create("Joystick"); context = Context::Create(window); world = World::Create(); camera = Camera::Create(); window->HideMouse(); if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0) { System::Print("Unable to init joystick system"); } else { joysticks[0] = new Game_Controller(); if (joysticks[0]->Init(0, 15000, true, true)) { System::Print("** Using joystick : " + joysticks[0]->GetName()); } } window->ShowMouse(); return true; } bool App::Loop() { //Close the window to end the program if (window->KeyDown(Key::Escape)) return false; if (joysticks[0]) { joysticks[0]->ProcessEvents(); if (joysticks[0]->AXIS_UP) System::Print("AXIS UP ; " + std::to_string(joysticks[0]->axis_y)); if (joysticks[0]->AXIS_DOWN) System::Print("AXIS DOWN ; " + std::to_string(joysticks[0]->axis_y)); if (joysticks[0]->AXIS_LEFT) System::Print("AXIS LEFT ; " + std::to_string(joysticks[0]->axis_x)); if (joysticks[0]->AXIS_RIGHT) System::Print("AXIS RIGHT ; " + std::to_string(joysticks[0]->axis_x)); if (joysticks[0]->DPAD_UP) System::Print("DPAD UP"); if (joysticks[0]->DPAD_DOWN) System::Print("DPAD DOWN"); if (joysticks[0]->DPAD_LEFT) System::Print("DPAD LEFT"); if (joysticks[0]->DPAD_RIGHT) System::Print("DPAD RIGHT"); for (int b = 0; b < sizeof(joysticks[0]->Button) / sizeof(*joysticks[0]->Button); b++) { if (joysticks[0]->Button[b] == true) { System::Print("Button pressed: " + std::to_string(B)); } } if (joysticks[0]->trigger_left > 0) System::Print("Trigger left: " + std::to_string(joysticks[0]->trigger_left)); if (joysticks[0]->trigger_right > 0) System::Print("Trigger right: " + std::to_string(joysticks[0]->trigger_right)); } Leadwerks::Time::Update(); world->Update(); world->Render(); context->Sync(false); return true; } Game_Controller.h /* Game controller class using SDL2 - Added better support for XInput. - Button remapping. - Automatic re-acquiring when controller is unplugged/replugged. Download SDL2 and copy the SDL2-2.0.3 folder in your Source directory. Add SDL2.lib to your project and copy SDL2.dll where your executable is. */ #include "Leadwerks.h" #include "SDL2-2.0.3/include/SDL.h" #undef main class Game_Controller { private: SDL_Joystick* m_joy; SDL_Event m_event; uint8 m_total_joysticks; uint8 m_index; std::string m_name; int16 m_threshold; bool m_xinput; uint8 m_mapped_buttons[32]; bool m_auto_reacquire; bool m_reacquire_alternate_controller; uint8 FindControllerByName(std::string controller_name) { SDL_JoystickUpdate(); int8 alternate_controller = -1; for (int c = 0; c < SDL_NumJoysticks(); c++) { SDL_Joystick* joy = SDL_JoystickOpen(c); if (joy) { if (SDL_JoystickName(joy) == m_name || controller_name == "") { //System::Print("Joystick found, reacquiring " + m_name); return c; } else if (m_reacquire_alternate_controller == true) { if (alternate_controller == -1) alternate_controller = c; // Use another controller if the one we're looking for can't be found // } SDL_JoystickClose(joy); } joy = NULL; } return alternate_controller; } public: Game_Controller() { m_index = -1; } ~Game_Controller() { Close(); } bool DPAD_UP, DPAD_DOWN, DPAD_LEFT, DPAD_RIGHT; bool AXIS_UP, AXIS_DOWN, AXIS_LEFT, AXIS_RIGHT; int16 axis_x, axis_y; uint8 trigger_left, trigger_right; bool Button[32]; bool Init(uint8 index, int16 axis_threshold, bool auto_require, bool reacquire_alternate_controller) { if (index < 0 || index > SDL_NumJoysticks() - 1) return false; m_total_joysticks = SDL_NumJoysticks(); m_index = index; m_threshold = axis_threshold; m_xinput = false; m_auto_reacquire = auto_require; m_reacquire_alternate_controller = reacquire_alternate_controller; DPAD_UP = false, DPAD_DOWN = false, DPAD_LEFT = false, DPAD_RIGHT = false; AXIS_UP = false, AXIS_DOWN = false, AXIS_LEFT = false, AXIS_RIGHT = false; for (int b = 0; b < sizeof(Button) / sizeof(*Button); b++) { Button[b] = false; m_mapped_buttons[b] = b; } trigger_left = 0; trigger_right = 0; axis_x = 0; axis_y = 0; if (m_joy) m_joy = NULL; SDL_JoystickEventState(SDL_ENABLE); m_joy = SDL_JoystickOpen(index); if (m_joy) { m_name = SDL_JoystickName(m_joy); if (m_name.length() > 0) { if (m_name.find("XInput") == 0) { // XInput devices have different button mapping // m_xinput = true; m_mapped_buttons[5] = 8; // select m_mapped_buttons[4] = 9; // start m_mapped_buttons[8] = 4; m_mapped_buttons[9] = 5; m_mapped_buttons[10] = 0; m_mapped_buttons[11] = 1; m_mapped_buttons[13] = 2; m_mapped_buttons[12] = 3; } } return true; } return false; } bool Reacquire() { m_total_joysticks = SDL_NumJoysticks(); Close(); if (m_auto_reacquire == true && m_total_joysticks > 0 && m_name.length() > 0) { uint8 index = FindControllerByName(m_name); if (index > -1) { Init(index, m_threshold, m_auto_reacquire, m_reacquire_alternate_controller); return true; } } return false; } void Close() { if (m_index > -1) { if (m_joy) { SDL_JoystickClose(m_joy); m_joy = NULL; } } } std::string GetName() { return m_name; } void ProcessEvents() { SDL_JoystickUpdate(); if (SDL_NumJoysticks() != m_total_joysticks) // Controller changes detected, attempt to re-acquire // Reacquire(); if (m_joy) { if (SDL_JoystickGetAttached(m_joy)) { while (SDL_PollEvent(&m_event)) { switch (m_event.type) { case SDL_JOYAXISMOTION: //if (m_event.jaxis.which == m_index) { if (m_event.jaxis.axis == 0) { if (m_event.jaxis.value < -m_threshold) AXIS_LEFT = true; if (m_event.jaxis.value > m_threshold) AXIS_RIGHT = true; if (m_event.jaxis.value > -m_threshold && m_event.jaxis.value < m_threshold) { AXIS_LEFT = false; AXIS_RIGHT = false; } axis_x = m_event.jaxis.value; } if (m_event.jaxis.axis == 1) { if (m_event.jaxis.value < -m_threshold) AXIS_UP = true; if (m_event.jaxis.value > m_threshold) AXIS_DOWN = true; if (m_event.jaxis.value > -m_threshold && m_event.jaxis.value < m_threshold) { AXIS_UP = false; AXIS_DOWN = false; } axis_y = m_event.jaxis.value; } //if (m_event.cbutton.which == m_index) { if (m_event.cbutton.button == 4) { Button[m_mapped_buttons[6]] = (m_event.button.button > 0); // Left trigger trigger_left = m_event.button.button; } if (m_event.cbutton.button == 5) { Button[m_mapped_buttons[7]] = (m_event.button.button > 0); // Right trigger trigger_right = m_event.button.button; } //} break; //} case SDL_JOYHATMOTION: //if (m_event.jaxis.which == m_index) { DPAD_UP = false; DPAD_DOWN = false; DPAD_LEFT = false; DPAD_RIGHT = false; if (m_event.jhat.value & SDL_HAT_UP) DPAD_UP = true; if (m_event.jhat.value & SDL_HAT_DOWN) DPAD_DOWN = true; if (m_event.jhat.value & SDL_HAT_LEFT) DPAD_LEFT = true; if (m_event.jhat.value & SDL_HAT_RIGHT) DPAD_RIGHT = true; //} break; case SDL_JOYBUTTONDOWN: //if (m_event.jaxis.which == m_index) { if (m_xinput) { if (m_event.jbutton.button < 4) { // Directional pad (hat) on Xbox controllers are recognized as buttons // if (m_event.jbutton.button == 0) DPAD_UP = true; if (m_event.jbutton.button == 1) DPAD_DOWN = true; if (m_event.jbutton.button == 2) DPAD_LEFT = true; if (m_event.jbutton.button == 3) DPAD_RIGHT = true; } else { Button[m_mapped_buttons[m_event.jbutton.button]] = true; } } else { Button[m_mapped_buttons[m_event.jbutton.button]] = true; } //} break; case SDL_JOYBUTTONUP: //if (m_event.jaxis.which == m_index) { if (m_xinput) { if (m_event.jbutton.button < 4) { if (m_event.jbutton.button == 0) DPAD_UP = false; if (m_event.jbutton.button == 1) DPAD_DOWN = false; if (m_event.jbutton.button == 2) DPAD_LEFT = false; if (m_event.jbutton.button == 3) DPAD_RIGHT = false; } else { Button[m_mapped_buttons[m_event.jbutton.button]] = false; } } else { Button[m_mapped_buttons[m_event.jbutton.button]] = false; } //} break; } } } } } }; Edited April 19, 2015 by Skrakle Quote Link to comment Share on other sites More sharing options...
Kraxie Posted April 18, 2015 Author Share Posted April 18, 2015 I've been writing a c++ class using SDL in the last few days and it's almost finished. There were issues with my xbox controller, keys aren't mapped the same as regular controllers but i managed to fix it and implement a button mapping feature and now it behaves like normal controllers. It can automatically re-acquire controllers that are unplugged/replugged. I will post the code once i'ts done, after that, i'll add lua support. Thanks, but I'm using Lua, yea... When you get Lua working, let me know Quote Windows 7 | Intel Core i7-4790K | 16 GB RAM | Nvidia GTX 980 Link to comment Share on other sites More sharing options...
Skrakle Posted April 18, 2015 Share Posted April 18, 2015 If you only have the indie version it won't work but i think there's the possibility to make a dll accessible to lua like luasqldbi but i don't know how to do that yet. I'll let you know if i'm successful. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.