You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
282 lines
8.4 KiB
282 lines
8.4 KiB
#include "InputHandler.h"
|
|
|
|
InputHandler * InputHandler::_instance = 0;
|
|
|
|
InputHandler * InputHandler::instance(){
|
|
if(_instance == 0){
|
|
_instance = new InputHandler();
|
|
}
|
|
return _instance;
|
|
}
|
|
|
|
void InputHandler::initialise(){
|
|
|
|
if(SDL_Init(SDL_INIT_JOYSTICK) >= 0){
|
|
std::cout << "Joystick INIT success" << std::endl;
|
|
}
|
|
|
|
if(SDL_NumJoysticks() > 0){
|
|
for(int i = 0; i < SDL_NumJoysticks(); ++i){
|
|
SDL_Joystick * joystick = SDL_JoystickOpen(i);
|
|
if(SDL_JoystickGetAttached(joystick) == SDL_TRUE){
|
|
std::cout << "Joystick num axes: " << SDL_JoystickNumAxes(joystick) << std::endl;
|
|
std::cout << "Joystick ID: " << SDL_JoystickInstanceID(joystick) << std::endl;
|
|
std::cout << "Joystick Name: " << SDL_JoystickName(joystick) << std::endl;
|
|
|
|
SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(i);
|
|
char guid_str[1024];
|
|
SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str));
|
|
std::cout << "Joystick GUID: " << guid_str << std::endl;
|
|
|
|
_joysticks.push_back(joystick);
|
|
}else{
|
|
std::cout << SDL_GetError() << std::endl;
|
|
}
|
|
}
|
|
SDL_JoystickEventState(SDL_ENABLE);
|
|
_initialised = true;
|
|
std::cout << "Initialised " << _joysticks.size() << " joysticks" << std::endl;
|
|
}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)){
|
|
|
|
ControllerCommand command = ControllerCommand::COMMAND_NONE;
|
|
|
|
if(event.type == SDL_JOYHATMOTION){
|
|
std::cout << "SDL_JOYHATMOTION" << 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;
|
|
|
|
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;
|
|
|
|
ControllerItem item;
|
|
item.type = CONTROLLER_BUTTON;
|
|
item.index = (int)event.jbutton.button;
|
|
item.value = 1; // Button has only one value
|
|
|
|
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)));
|
|
}
|
|
}
|
|
}
|
|
|
|
void InputHandler::clean(){
|
|
if(_initialised){
|
|
for(int i = 0; i < _joysticks.size(); ++i){
|
|
SDL_JoystickClose(_joysticks[i]);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
return ControllerCommand::COMMAND_NONE;
|
|
}
|
|
|
|
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{
|
|
|
|
}
|
|
}
|
|
|
|
|