diff --git a/example-gamepad/src/InputHandler.cpp b/example-gamepad/src/InputHandler.cpp index 00f32e5..8d6ca7d 100644 --- a/example-gamepad/src/InputHandler.cpp +++ b/example-gamepad/src/InputHandler.cpp @@ -10,12 +10,7 @@ InputHandler * InputHandler::instance(){ } void InputHandler::initialise(){ - /* - if(SDL_WasInit(SDL_INIT_JOYSTICK) == 0){ - SDL_InitSubSystem(SDL_INIT_JOYSTICK); - } - */ - + if(SDL_Init(SDL_INIT_JOYSTICK) >= 0){ std::cout << "Joystick INIT success" << std::endl; } @@ -44,99 +39,128 @@ void InputHandler::initialise(){ }else{ _initialised = false; std::cout << "No joysticks initialised" << std::endl; + return; + } + + // Load the controllers.xml file if exists. + if(ofFile::doesFileExist("controllers.xml")){ + ofxXmlSettings xml; + if(!xml.load("controllers.xml")){ + std::cout << "Failed to load controllers.xml" << std::endl; + } + + std::cout << "Loaded controllers.xml" << std::endl; + + // Find the right map for each initialized controller + for(int i = 0; i < _joysticks.size(); ++i){ + + // Get controller GUID first + SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(i); + char guid_str[1024]; + SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str)); + std::string guidString(guid_str); + + // Search for GUID in XML + if(xml.tagExists("controllers")){ + xml.pushTag("controllers"); + + for(int ci = 0; ci < xml.getNumTags("controller"); ci++){ + if(xml.tagExists("controller", ci)){ + xml.pushTag("controller", ci); + + if(xml.getValue("guid_osx", "") == guidString || + xml.getValue("guid_linux", "") == guidString || + xml.getValue("guid_windows", "") == guidString){ + + std::cout << "Found map for GUID: " << guidString << std::endl; + + // We found our controller for the initialized joystick, let's map it + std::map map; + map[COMMAND_LEFT] = getControllerItem(xml.getValue("left", "")); + map[COMMAND_RIGHT] = getControllerItem(xml.getValue("right", "")); + map[COMMAND_UP] = getControllerItem(xml.getValue("up", "")); + map[COMMAND_DOWN] = getControllerItem(xml.getValue("down", "")); + map[COMMAND_A] = getControllerItem(xml.getValue("a", "")); + map[COMMAND_B] = getControllerItem(xml.getValue("b", "")); + map[COMMAND_X] = getControllerItem(xml.getValue("x", "")); + map[COMMAND_Y] = getControllerItem(xml.getValue("y", "")); + map[COMMAND_SELECT] = getControllerItem(xml.getValue("select", "")); + map[COMMAND_START] = getControllerItem(xml.getValue("start", "")); + + // Add map to our database for a controller only if it is found + _controllerMap[i] = map; + + // Return the xml oblect to the state before the for loop + xml.popTag(); // controller[ci] + + // Break the for loop as we found what we wanted + break; + } + + // Return the xml oblect to the state before the for loop + xml.popTag(); // controller[ci] + } + } + xml.popTag(); // controllers + } // if(xml.tagExists("controllers")) + } // ofFile::doesFileExist("controllers.xml") + }else{ + std::cout << "controllers.xml does not exist" << std::endl; } } void InputHandler::update(){ SDL_Event event; while(SDL_PollEvent(&event)){ - - if(event.type == SDL_QUIT){ - std::cout << "SDL_QUIT on InputHandler::update()" << std::endl; - } - - if(event.type == SDL_JOYBALLMOTION){ - std::cout << "SDL_JOYBALLMOTION" << std::endl; - } + + ControllerCommand command = ControllerCommand::COMMAND_NONE; if(event.type == SDL_JOYHATMOTION){ std::cout << "SDL_JOYHATMOTION" << std::endl; - if(event.jhat.value == SDL_HAT_CENTERED){ - std::cout << "value: centered" << std::endl; - }else if(event.jhat.value == SDL_HAT_LEFT){ - std::cout << "value: left" << std::endl; - }else if(event.jhat.value == SDL_HAT_RIGHT){ - std::cout << "value: right" << std::endl; - }else if(event.jhat.value == SDL_HAT_UP){ - std::cout << "value: up" << std::endl; - }else if(event.jhat.value == SDL_HAT_DOWN){ - std::cout << "value: down" << std::endl; - }else if(event.jhat.value == SDL_HAT_RIGHTUP){ - std::cout << "value: rightup" << std::endl; - }else if(event.jhat.value == SDL_HAT_RIGHTDOWN){ - std::cout << "value: rightdown" << std::endl; - }else if(event.jhat.value == SDL_HAT_LEFTUP){ - std::cout << "value: leftup" << std::endl; - }else if(event.jhat.value == SDL_HAT_LEFTDOWN){ - std::cout << "value: leftdown" << std::endl; - } + + ControllerItem item; + item.type = CONTROLLER_HAT; + item.index = (int)event.jhat.hat; + item.value = (int)event.jhat.value; + + command = getControllerCommand((int)event.jhat.which, item); + std::cout << "hat value: " << item.value << std::endl; + std::cout << "command: " << controllerCommandToString(command) << std::endl; std::cout << "----------" << std::endl; } if(event.type == SDL_JOYAXISMOTION){ if((event.jaxis.value < -3200) || (event.jaxis.value > 3200)){ std::cout << "SDL_JOYAXISMOTION" << std::endl; - std::cout << "type: " << event.jaxis.type << std::endl; - std::cout << "which: " << event.jaxis.which << std::endl; - std::cout << "axis: " << event.jaxis.axis << std::endl; - std::cout << "value: " << event.jaxis.value << std::endl; - - if(event.jaxis.axis == 0){ - std::cout << "axis check: left-right" << std::endl; - } - - if(event.jaxis.axis == 1){ - std::cout << "axis check: up-down" << std::endl; - } - - if(event.jaxis.axis == 2){ - std::cout << "axis check: 2" << std::endl; - } - - if(event.jaxis.axis == 3){ - std::cout << "axis check: 3" << std::endl; - } - - // Sony PlayStation Wireless controller - if(event.jaxis.axis == 4){ - std::cout << "axis check: 4" << std::endl; - } - - if(event.jaxis.axis == 5){ - std::cout << "axis check: 5" << std::endl; - } + ControllerItem item; + item.type = CONTROLLER_AXIS; + item.index = (int)event.jaxis.axis; + item.value = (int)event.jaxis.value; + + command = getControllerCommand((int)event.jaxis.which, item); + std::cout << "command: " << controllerCommandToString(command) << std::endl; std::cout << "----------" << std::endl; + } } if(event.type == SDL_JOYBUTTONDOWN){ std::cout << "SDL_JOYBUTTONDOWN" << std::endl; - std::cout << "type: " << event.jbutton.type << std::endl; - std::cout << "which: " << event.jbutton.which << std::endl; - std::cout << "button: " << (int)event.jbutton.button << std::endl; - /* - std::cout << "button: "; - if(event.jbutton.button == SDL_BUTTON_X1){ - std::cout << "SDL_BUTTON_X1"; - } - std::cout << std::endl; - */ + ControllerItem item; + item.type = CONTROLLER_BUTTON; + item.index = (int)event.jbutton.button; + item.value = 1; // Button has only one value - std::cout << "state: " << event.jbutton.state << std::endl; + command = getControllerCommand((int)event.jbutton.which, item); + std::cout << "command: " << controllerCommandToString(command) << std::endl; std::cout << "----------" << std::endl; } + + if(command != ControllerCommand::COMMAND_NONE){ + ofSendMessage(ofMessage(ofToString(command))); + } } } @@ -152,3 +176,105 @@ void InputHandler::clean(){ bool InputHandler::initialised(){ return _initialised; } + +ControllerItem InputHandler::getControllerItem(std::string code){ + ControllerItem item; + + // Determine type + if(code.substr(0, 1) == "b"){ + item.type = CONTROLLER_BUTTON; + }else if(code.substr(0, 1) == "h"){ + item.type = CONTROLLER_HAT; + }else if(code.substr(0, 1) == "a"){ + item.type = CONTROLLER_AXIS; + } + + // If it is a hat, we need a value, otherwise set it to -1 + if(item.type == CONTROLLER_HAT){ + item.index = ofToInt(code.substr(1, 1)); + item.value = ofToInt(code.substr(3)); + }else{ + item.index = ofToInt(code.substr(1)); + item.value = -1; + } + + return item; +} + +ControllerCommand InputHandler::getControllerCommand(int controllerIndex, ControllerItem & item){ + std::cout << "controllerIndex: " << controllerIndex << std::endl; + + std::map>::iterator it; + it = _controllerMap.find(controllerIndex); + if(it == _controllerMap.end()){ + return ControllerCommand::COMMAND_NONE; + } + + std::map::iterator mit; + for(mit = it->second.begin(); mit != it->second.end(); mit++){ + if(mit->second.type == item.type && mit->second.index == item.index){ + + // In case of axes, we need to check the sign + if(mit->second.type == CONTROLLER_AXIS){ + if(mit->first == ControllerCommand::COMMAND_LEFT && item.value > 0){ + continue; // value must be negative for left + } + + if(mit->first == ControllerCommand::COMMAND_RIGHT && item.value < 0){ + continue; // value must be positive for right + } + + if(mit->first == ControllerCommand::COMMAND_UP && item.value > 0){ + continue; // value must be negative for up + } + + if(mit->first == ControllerCommand::COMMAND_DOWN && item.value < 0){ + continue; // value must be positive for down + } + + return mit->first; + } + + // In case of hat, we need to compare hat values + if(mit->second.type == CONTROLLER_HAT){ + if(mit->second.value == item.value){ + return mit->first; + }else{ + continue; + } + } + + // In case of buttons type and index is enough + return mit->first; + } + } +} + +std::string InputHandler::controllerCommandToString(ControllerCommand com){ + if(com == COMMAND_NONE){ + return "COMMAND_NONE"; + }else if(com == COMMAND_LEFT){ + return "COMMAND_LEFT"; + }else if(com == COMMAND_RIGHT){ + return "COMMAND_RIGHT"; + }else if(com == COMMAND_UP){ + return "COMMAND_UP"; + }else if(com == COMMAND_DOWN){ + return "COMMAND_DOWN"; + }else if(com == COMMAND_A){ + return "COMMAND_A"; + }else if(com == COMMAND_B){ + return "COMMAND_B"; + }else if(com == COMMAND_X){ + return "COMMAND_X"; + }else if(com == COMMAND_Y){ + return "COMMAND_Y"; + }else if(com == COMMAND_SELECT){ + return "COMMAND_SELECT"; + }else if(com == COMMAND_START){ + return "COMMAND_START"; + }else{ + + } +} + diff --git a/example-gamepad/src/InputHandler.h b/example-gamepad/src/InputHandler.h index d33e712..9b7ff15 100644 --- a/example-gamepad/src/InputHandler.h +++ b/example-gamepad/src/InputHandler.h @@ -1,47 +1,61 @@ #pragma once -/* -Joystick num axes: 5 -Joystick ID: 0 -Joystick Name: Generic USB Joystick -Joystick GUID: 79000000000000000600000000000000 -Joystick num axes: 2 -Joystick ID: 1 -Joystick Name: USB gamepad -Joystick GUID: 1f0800000000000001e4000000000000 -Joystick num axes: 6 -Joystick ID: 2 -Joystick Name: Wireless Controller -Joystick GUID: 4c05000000000000c405000000000000 -Initialised 3 joysticks - // These are the strings reported by SDL2's SDL_JoystickGetGUIDString: // https://wiki.libsdl.org/SDL_JoystickGetGUIDString -4c05c405000000000000504944564944 // Windows. Note characters 1-8. -4c05000000000000c405000000000000 // OSX. Note characters 1-4 and 17-20. -030000004c050000c405000011010000 // Linux. Note characters 9-12 and 17-20. - -4c05c405 // This is the GUID string returned by FNA. Get it? - - -*/ #include +#include +#include #include #include "SDL2/SDL.h" +#include "ofMain.h" +#include "ofxXmlSettings.h" + +enum ControllerItemType{ + CONTROLLER_BUTTON, + CONTROLLER_AXIS, + CONTROLLER_HAT +}; + +enum ControllerCommand{ + COMMAND_NONE, + COMMAND_LEFT, + COMMAND_RIGHT, + COMMAND_UP, + COMMAND_DOWN, + COMMAND_A, + COMMAND_B, + COMMAND_X, + COMMAND_Y, + COMMAND_SELECT, + COMMAND_START +}; + +struct ControllerItem{ + ControllerItemType type; + int index; + int value; +}; class InputHandler{ public: static InputHandler * instance(); + void initialise(); void update(); void clean(); + bool initialised(); + ControllerItem getControllerItem(std::string code); + ControllerCommand getControllerCommand(int controllerIndex, ControllerItem & item); + std::string controllerCommandToString(ControllerCommand com); + private: InputHandler(){} ~InputHandler(){} static InputHandler * _instance; bool _initialised; std::vector _joysticks; + std::map> _controllerMap; }; diff --git a/example-gamepad/src/ofApp.cpp b/example-gamepad/src/ofApp.cpp index 1db0462..ada66fa 100644 --- a/example-gamepad/src/ofApp.cpp +++ b/example-gamepad/src/ofApp.cpp @@ -35,6 +35,11 @@ void ofApp::mouseReleased(int x, int y, int button){ mapper.mouseReleased(x, y, button); } +void ofApp::messageReceived(ofMessage & message){ + ControllerCommand com = (ControllerCommand)ofToInt(message.message); + handleController(com); +} + /* These values we take into consideration ↖ ↑ ↗ y @@ -42,12 +47,26 @@ void ofApp::mouseReleased(int x, int y, int button){ ↙ ↓ ↘ a */ -void ofApp::handleJoystick(){ - if("value" == "left"){ - - }else if("value" == "leftup"){ - - }else if("value" == "A"){ - +void ofApp::handleController(ControllerCommand com){ + if(com == ControllerCommand::COMMAND_LEFT){ + mapper.moveSelection(ofVec2f(-5.0f, 0.0f)); + }else if(com == ControllerCommand::COMMAND_RIGHT){ + mapper.moveSelection(ofVec2f(5.0f, 0.0f)); + }else if(com == ControllerCommand::COMMAND_UP){ + mapper.moveSelection(ofVec2f(0.0f, -5.0f)); + }else if(com == ControllerCommand::COMMAND_DOWN){ + mapper.moveSelection(ofVec2f(0.0f, 5.0f)); + }else if(com == ControllerCommand::COMMAND_A){ + mapper.selectNextVertex(); + }else if(com == ControllerCommand::COMMAND_B){ + mapper.selectNextSurface(); + }else if(com == ControllerCommand::COMMAND_X){ + mapper.setMode(ofx::piMapper::Mode::MAPPING_MODE); + }else if(com == ControllerCommand::COMMAND_Y){ + mapper.setMode(ofx::piMapper::Mode::TEXTURE_MODE); + }else if(com == ControllerCommand::COMMAND_SELECT){ + mapper.setNextSource(); + }else if(com == ControllerCommand::COMMAND_START){ + mapper.setMode(ofx::piMapper::Mode::PRESENTATION_MODE); } } diff --git a/example-gamepad/src/ofApp.h b/example-gamepad/src/ofApp.h index 2da2a9b..748b58c 100644 --- a/example-gamepad/src/ofApp.h +++ b/example-gamepad/src/ofApp.h @@ -17,7 +17,9 @@ class ofApp : public ofBaseApp { void mouseDragged(int x, int y, int button); void mouseReleased(int x, int y, int button); - void handleJoystick(); + void messageReceived(ofMessage & message); + + void handleController(ControllerCommand com); ofxPiMapper mapper; }; \ No newline at end of file