Commit 474d97b0 authored by Robert Menzel's avatar Robert Menzel

added gamepad support

parent 4ca2d2d3
/***********************************************************************
* Copyright 2011-2013 Computer Graphics Group RWTH Aachen University. *
* All rights reserved. *
* Distributed under the terms of the MIT License (see LICENSE.TXT). *
**********************************************************************/
#pragma once
#include <ACGL/ACGL.hh>
#include <string>
namespace ACGL{
namespace HardwareSupport{
/**
* NOTE: Will not work unless ACGL_COMPILE_WITH_GLFW is defined!
*/
class GamePad {
public:
enum GamePadButton {
SELECT = 0,
START = 1,
LEFT_PAD_NORTH = 2,
LEFT_PAD_EAST = 3,
LEFT_PAD_SOUTH = 4,
LEFT_PAD_WEST = 5,
RIGHT_PAD_NORTH = 6,
RIGHT_PAD_EAST = 7,
RIGHT_PAD_SOUTH = 8,
RIGHT_PAD_WEST = 9,
LEFT_SHOULDER = 10,
RIGHT_SHOULDER = 11,
LEFT_TRIGGER = 12,
RIGHT_TRIGGER = 13,
// number of elements in this enum (itself not included):
GAMEPAD_BUTTON_ENUM_SIZE = 14
};
enum GamePadAxis {
LEFT_ANALOG_TRIGGER = 0,
RIGHT_ANALOG_TRIGGER = 1,
LEFT_ANALOG_STICK_X = 2, // aka left-right
LEFT_ANALOG_STICK_Y = 3, // aka up-down / front-back
RIGHT_ANALOG_STICK_X = 4, // aka left-right
RIGHT_ANALOG_STICK_Y = 5, // aka up-down / front-back
// number of elements in this enum (itself not included):
GAMEPAD_AXIS_ENUM_SIZE = 6
};
//! connects to the _n-th joystick, start counting at 1!
GamePad( int _n = 1 );
~GamePad();
//! true if the joystick was found, note that unplugging the GamePad at runtime can not be detected!
bool ok() { return mGamePadOK; }
///////////// Buttons
//! true if the button with the internal number _button is pressed
bool isPressedRaw( unsigned int _button );
//! only returns true if the button was mapped first!
bool isPressed( GamePadButton _button );
//! true if the button was just pressed or released
bool buttonStateChanged( unsigned int _button );
//! true if the button was just pressed or released
bool buttonStateChanged( GamePadButton _button );
//! define the mapping of one button
void setButtonMapping( GamePadButton _button, unsigned int _rawButtonNumber );
///////////// Axes
//! analog sticks and analog trigger, values are from -1..1. An unknown axis will return 0.0
float getAxisRaw( unsigned int _axis );
float getAxis( GamePadAxis _axis );
//! define the mapping of one button
void setAxisMapping( GamePadAxis _axis, unsigned int _rawAxisNumber );
//! print the button and axes state for debugging:
void printState();
//! fetches the current device state, will do nothing if the joystick is not ok
void update();
private:
bool mGamePadOK;
int mNumberOfButtons;
int mNumberOfAxes;
int mButtonMap[GAMEPAD_BUTTON_ENUM_SIZE];
int mAxisMap[GAMEPAD_AXIS_ENUM_SIZE];
//
// GLFW specifics: replace this to support joysticks with other APIs
//
#ifdef ACGL_COMPILE_WITH_GLFW
const unsigned char *mGLFWButtons;
const float *mGLFWAxes;
unsigned char *mLastGLFWButtonState;
int mGLFWGamePadNumber;
#endif
};
ACGL_SMARTPOINTER_TYPEDEFS(GamePad)
}
}
/***********************************************************************
* Copyright 2011-2013 Computer Graphics Group RWTH Aachen University. *
* All rights reserved. *
* Distributed under the terms of the MIT License (see LICENSE.TXT). *
**********************************************************************/
#include <ACGL/HardwareSupport/GamePad.hh>
#include <ACGL/Utils/Log.hh>
#include <cassert>
#include <cstring>
#ifdef ACGL_COMPILE_WITH_GLFW
#include <GLFW/glfw3.h>
#endif
using namespace std;
using namespace ACGL;
using namespace ACGL::Utils;
using namespace ACGL::HardwareSupport;
//! connects to the _n-th joystick
GamePad::GamePad( int _n )
{
assert( _n != 0 );
mGamePadOK = false;
mLastGLFWButtonState = NULL;
#ifdef ACGL_COMPILE_WITH_GLFW
int numberOfJoysticksFound = 0;
for (int i = GLFW_JOYSTICK_1; i <= GLFW_JOYSTICK_LAST; ++i) {
if (glfwJoystickPresent(i) == GL_TRUE) {
numberOfJoysticksFound++;
if ( numberOfJoysticksFound == _n) {
mGamePadOK = true;
mGLFWGamePadNumber = i;
break;
}
}
}
#endif
if (!mGamePadOK) {
mNumberOfButtons = 0;
mNumberOfAxes = 0;
#ifdef ACGL_COMPILE_WITH_GLFW
mGLFWButtons = NULL;
mGLFWAxes = NULL;
mGLFWGamePadNumber = 0;
#endif
} else {
update();
}
//
// prepare button mapping
//
for (int i = 0; i < GAMEPAD_BUTTON_ENUM_SIZE; ++i) {
// set to an invalid button number so it will always get reported as false:
mButtonMap[i] = GAMEPAD_BUTTON_ENUM_SIZE;
}
for (int i = 0; i < GAMEPAD_AXIS_ENUM_SIZE; ++i) {
// set to an invalid button number so it will always get reported as false:
mAxisMap[i] = GAMEPAD_AXIS_ENUM_SIZE;
}
#ifdef ACGL_COMPILE_WITH_GLFW
if (mGamePadOK) {
string joystickName = string( glfwGetJoystickName(mGLFWGamePadNumber) );
if (joystickName == "Sony PLAYSTATION(R)3 Controller") {
setButtonMapping( SELECT, 0);
setButtonMapping( START, 3);
setButtonMapping( LEFT_PAD_NORTH , 4);
setButtonMapping( LEFT_PAD_EAST , 5);
setButtonMapping( LEFT_PAD_SOUTH , 6);
setButtonMapping( LEFT_PAD_WEST , 7);
setButtonMapping( RIGHT_PAD_NORTH , 12);
setButtonMapping( RIGHT_PAD_EAST , 13);
setButtonMapping( RIGHT_PAD_SOUTH , 14);
setButtonMapping( RIGHT_PAD_WEST , 15);
setButtonMapping( LEFT_SHOULDER , 10);
setButtonMapping( RIGHT_SHOULDER , 11);
setButtonMapping( LEFT_TRIGGER , 8);
setButtonMapping( RIGHT_TRIGGER , 9);
setAxisMapping( LEFT_ANALOG_TRIGGER , 12);
setAxisMapping( RIGHT_ANALOG_TRIGGER , 13);
setAxisMapping( LEFT_ANALOG_STICK_X , 0);
setAxisMapping( LEFT_ANALOG_STICK_Y , 1);
setAxisMapping( RIGHT_ANALOG_STICK_X , 2);
setAxisMapping( RIGHT_ANALOG_STICK_Y , 3);
}
}
#endif
}
GamePad::~GamePad()
{
delete[] mLastGLFWButtonState;
}
bool GamePad::isPressedRaw( unsigned int _button )
{
if ( (int)_button > mNumberOfButtons) return false;
return ( mGLFWButtons[_button] == 1 );
}
bool GamePad::isPressed( GamePadButton _button )
{
return isPressedRaw( mButtonMap[_button] );
}
void GamePad::setButtonMapping( GamePadButton _button, unsigned int _rawButtonNumber )
{
assert(_button < GAMEPAD_BUTTON_ENUM_SIZE);
mButtonMap[_button] = _rawButtonNumber;
}
bool GamePad::buttonStateChanged( unsigned int _button )
{
if ( (int)_button > mNumberOfButtons) return false;
return (mGLFWButtons[_button] != mLastGLFWButtonState[_button]);
}
bool GamePad::buttonStateChanged( GamePadButton _button )
{
return buttonStateChanged( mButtonMap[_button] );
}
float GamePad::getAxisRaw( unsigned int _axis )
{
if ( (int)_axis > mNumberOfAxes) return 0.0f;
return mGLFWAxes[_axis];
}
float GamePad::getAxis( GamePadAxis _axis )
{
return getAxisRaw( mAxisMap[_axis] );
}
void GamePad::setAxisMapping( GamePadAxis _axis, unsigned int _rawAxisNumber )
{
assert(_axis < GAMEPAD_AXIS_ENUM_SIZE);
mAxisMap[_axis] = _rawAxisNumber;
}
void GamePad::update()
{
if (!ok()) return;
#ifdef ACGL_COMPILE_WITH_GLFW
if (!mLastGLFWButtonState) {
mGLFWButtons = glfwGetJoystickButtons( mGLFWGamePadNumber, &mNumberOfButtons );
mGLFWAxes = glfwGetJoystickAxes( mGLFWGamePadNumber, &mNumberOfAxes );
mLastGLFWButtonState = new unsigned char[mNumberOfButtons];
}
memcpy( mLastGLFWButtonState, mGLFWButtons, mNumberOfButtons );
mGLFWButtons = glfwGetJoystickButtons( mGLFWGamePadNumber, &mNumberOfButtons );
mGLFWAxes = glfwGetJoystickAxes( mGLFWGamePadNumber, &mNumberOfAxes );
#endif
}
void GamePad::printState()
{
if (!ok()) return;
#ifdef ACGL_COMPILE_WITH_GLFW
for (int i = 0; i < mNumberOfButtons; ++i) {
debug() << (int) mGLFWButtons[i] << " ";
}
debug() << "| ";
for (int i = 0; i < mNumberOfAxes; ++i) {
debug() << mGLFWAxes[i] << " ";
}
debug() << endl;
#endif
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment