Browse Source

Add working game controller mapping

master
Krisjanis Rijnieks 8 years ago
parent
commit
0b440add14
  1. 272
      example-gamepad/src/InputHandler.cpp
  2. 60
      example-gamepad/src/InputHandler.h
  3. 33
      example-gamepad/src/ofApp.cpp
  4. 4
      example-gamepad/src/ofApp.h

272
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<ControllerCommand, ControllerItem> 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<int, std::map<ControllerCommand, ControllerItem>>::iterator it;
it = _controllerMap.find(controllerIndex);
if(it == _controllerMap.end()){
return ControllerCommand::COMMAND_NONE;
}
std::map<ControllerCommand, ControllerItem>::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{
}
}

60
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 <vector>
#include <string>
#include <sstream>
#include <iostream>
#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<SDL_Joystick *> _joysticks;
std::map<int, std::map<ControllerCommand, ControllerItem>> _controllerMap;
};

33
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);
}
}

4
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;
};
Loading…
Cancel
Save