Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
85 KB
Referenced Files
None
Subscribers
None
diff --git a/util/configuration.cpp b/util/configuration.cpp
index 1d3e93f0..c020de8f 100644
--- a/util/configuration.cpp
+++ b/util/configuration.cpp
@@ -1,984 +1,1007 @@
#include "configuration.h"
#include "input/keyboard.h"
#include "exceptions/load_exception.h"
#include "tokenreader.h"
#include "token.h"
#include "file-system.h"
#include "input/input.h"
#include "debug.h"
#include <sstream>
#include <fstream>
#include <stdlib.h>
#include <string>
#include <map>
#ifdef USE_SDL
#if SDL_VERSION_ATLEAST(1, 3, 0)
static const std::string INPUT_TYPE = "SDL1.3";
#else
static const std::string INPUT_TYPE = "SDL";
#endif
#endif
#ifdef USE_ALLEGRO
static const std::string INPUT_TYPE = "Allegro";
#endif
#ifdef USE_ALLEGRO5
static const std::string INPUT_TYPE = "Allegro5";
#endif
bool Configuration::save = true;
Util::ReferenceCount<Token> Configuration::data;
/* text that appears in the config file */
#define define_config(n,str) static const char * config_##n = str
define_config(attack1, "attack1");
define_config(attack2, "attack2");
define_config(attack3, "attack3");
define_config(attack4, "attack4");
define_config(attack5, "attack5");
define_config(attack6, "attack6");
define_config(configuration, "configuration");
define_config(cooperative, "cooperative");
// define_config(current_game, "current-game");
define_config(down, "down");
define_config(free_for_all, "free-for-all");
define_config(fullscreen, "fullscreen");
define_config(game_speed, "game-speed");
define_config(invincible, "invincible");
define_config(jump, "jump");
define_config(quit, "quit");
define_config(keyboard_configuration, "keyboard-configuration");
define_config(input, "input");
define_config(joystick_configuration, "joystick-configuration");
define_config(left, "left");
define_config(lives, "lives");
define_config(menu_font, "menu-font");
define_config(menu_font_width, "menu-font-width");
define_config(menu_font_height, "menu-font-height");
define_config(npc_buddies, "npc-buddies");
define_config(number, "number");
define_config(play_mode, "play-mode");
define_config(right, "right");
define_config(screen_size, "screen-size");
define_config(sound, "sound");
define_config(music, "music");
define_config(up, "up");
define_config(quality_filter, "quality-filter");
define_config(fps, "frames-per-second");
define_config(language, "language");
define_config(mugen_motif, "mugen-motif");
/* version of the game: 3.3, 3.4, 4.24 */
define_config(version, "version");
#undef def_config
using namespace std;
static const int InvalidKey = 0;
static const Joystick::Key InvalidJoystick = Joystick::Invalid;
/* don't save the configuration while loading it */
class Disable{
public:
Disable(){
last = Configuration::getSave();
Configuration::disableSave();
}
~Disable(){
Configuration::setSave(last);
}
bool last;
};
/* FIXME: move this to some utils module */
static std::vector<std::string> split(std::string str, char splitter){
std::vector<std::string> strings;
size_t next = str.find(splitter);
while (next != std::string::npos){
strings.push_back(str.substr(0, next));
str = str.substr(next+1);
next = str.find(splitter);
}
if (str != ""){
strings.push_back(str);
}
return strings;
}
static std::string last(const vector<string> & what){
return what.at(what.size() - 1);
}
/* Create a token that contains the entire path.
* path = "foo/bar/baz"
* out = (foo (bar (baz)))
*/
static Token * createToken(const string & path){
vector<string> paths = split(path, '/');
Token * out = new Token();
Token * current = out;
for (vector<string>::iterator it = paths.begin(); it != paths.end(); it++){
current->addToken(new Token(*it, false));
if (paths.end() - it > 1){
Token * next = new Token();
current->addToken(next);
current = next;
}
}
return out;
}
/* Create a token with the given path and give it a value */
template <class Value>
static Token * createToken(const string & path, const Value & value){
Token * out = createToken(path);
*out << value;
return out;
}
template <class Value, class Value2>
static Token * createToken(const string & path, const Value & value, const Value2 & value2){
Token * out = createToken(path);
*out << value;
*out << value2;
return out;
}
/* remove a path if it exists */
static void removeToken(Token * data, const std::string & path){
Token * found = data->findToken(path);
/* See if the token already exists. If it does then remove it from its
* parent and add a new token to the parent with the updated value.
*/
if (found != NULL){
Token * parent = found->getParent();
parent->removeToken(found);
}
}
static void updateToken(Token * data, const std::string & path, Token * add){
if (data == NULL){
delete add;
}
Token * found = data->findToken(path);
/* See if the token already exists. If it does then remove it from its
* parent and add a new token to the parent with the updated value.
*/
if (found != NULL){
Token * parent = found->getParent();
parent->removeToken(found);
parent->addToken(add);
} else {
const vector<string> paths = split(path, '/');
Token * start = data;
for (int index = 1; index < paths.size() - 1; index++){
string where = paths[index];
Token * next = start->findToken(string("_/") + where);
if (next == NULL){
ostringstream out;
bool first = true;
for (int from = index; from < paths.size(); from++){
if (!first){
out << "/";
}
out << paths[from];
first = false;
}
/* If we run out of found paths then create a token with an empty
* value for the unfound paths we have so far and call updateToken
* again. This time the entire path will be there
* so the 'found = ...' logic will work.
*/
start->addToken(createToken(out.str(), string("")));
updateToken(data, path, add);
return;
} else {
start = next;
}
}
/* It probably shouldn't be possible to get here. If the entire
* path was there then the findToken() logic above should have worked.
*/
start->addToken(add);
}
}
template <class Value>
static void updateToken(Token * data, const string & path, const Value & value){
if (data == NULL){
return;
}
updateToken(data, path, createToken(last(split(path, '/')), value));
}
void Configuration::setProperty(const string & name, const string & value){
updateToken(getRawData(), string(config_configuration) + "/" + name, value);
saveConfiguration();
}
static Token * getPropertyX(Token * data, const std::string & path){
return data->findToken(string(config_configuration) + "/" + path);
}
template <class Out>
static Out getPropertyX(Token * data, const std::string & path, const Out & defaultValue){
if (data == NULL){
return defaultValue;
}
Out out;
if (data->match(string(config_configuration) + "/" + path, out)){
return out;
}
updateToken(data, string(config_configuration) + "/" + path, defaultValue);
return defaultValue;
}
void Configuration::setDefaultKeys(int config){
/* Set the keys token to an empty value */
ostringstream path;
path << config_input << "/" << config << "/keys";
setProperty(path.str(), createToken("keys"));
/* Call the get methods to reset the defaults */
int ignore;
ignore = getRight(config);
ignore = getLeft(config);
ignore = getUp(config);
ignore = getDown(config);
ignore = getAttack1(config);
ignore = getAttack2(config);
ignore = getAttack3(config);
ignore = getAttack4(config);
ignore = getAttack5(config);
ignore = getAttack6(config);
ignore = getJump(config);
}
/* hopefully this is only used right before setting all the values
* since the key mappings are bogus in here'
*/
Configuration::Configuration(){
}
Configuration::Configuration(const Configuration & config){
menuFont = config.menuFont;
}
Configuration & Configuration::operator=(const Configuration & config){
Disable disable;
setMenuFont(config.getMenuFont());
return *this;
}
Configuration::~Configuration(){
}
Util::ReferenceCount<Menu::FontInfo> Configuration::getMenuFont(){
return menuFont;
}
bool Configuration::hasMenuFont(){
return menuFont != NULL;
}
void Configuration::setMenuFont(const Util::ReferenceCount<Menu::FontInfo> & info){
menuFont = info;
saveConfiguration();
}
void Configuration::setMenuFontWidth(int x){
setProperty(config_menu_font_width, x);
saveConfiguration();
}
int Configuration::getMenuFontWidth(){
return getProperty(config_menu_font_width, 24);
}
void Configuration::setMenuFontHeight(int x){
setProperty(config_menu_font_height, x);
saveConfiguration();
}
int Configuration::getMenuFontHeight(){
return getProperty(config_menu_font_height, 24);
}
static string joystickKeyName(Joystick::Key key){
switch (key){
case Joystick::Up: return "up";
case Joystick::Down: return "down";
case Joystick::Left: return "left";
case Joystick::Right: return "right";
case Joystick::Button1: return "button1";
case Joystick::Button2: return "button2";
case Joystick::Button3: return "button3";
case Joystick::Button4: return "button4";
case Joystick::Button5: return "button5";
case Joystick::Button6: return "button6";
case Joystick::Start: return "start";
case Joystick::Quit: return "quit";
case Joystick::Invalid: return "invalid";
}
return "?";
}
void Configuration::setCustomButton(Joystick::Key key, int config, const std::string & name, int button){
if (key != Joystick::Invalid){
ostringstream base;
base << config_configuration << "/" << config_input << "/" << INPUT_TYPE << "/";
base << "joystick" << "/" << config << "/";
base << name << "/" << joystickKeyName(key);
removeToken(getRawData(), base.str());
updateToken(getRawData(), base.str() + "/button", button);
saveConfiguration();
}
}
+bool Configuration::getCustomButton(Joystick::Key key, int config, const std::string & name, int & button){
+ /* FIXME: use a helper function for the joystick path */
+ ostringstream base;
+ base << config_configuration << "/" << config_input << "/" << INPUT_TYPE << "/";
+ base << "joystick" << "/" << config << "/";
+ base << name << "/" << joystickKeyName(key);
+
+ return getRawData()->match(base.str() + "/button", button);
+}
+
+bool Configuration::getCustomAxis(Joystick::Key key, int config, const std::string & name, int & stick, int & axis, double & low, double & high){
+ /* FIXME: use a helper function for the joystick path */
+ ostringstream base;
+ base << config_configuration << "/" << config_input << "/" << INPUT_TYPE << "/";
+ base << "joystick" << "/" << config << "/";
+ base << name << "/" << joystickKeyName(key);
+
+ return getRawData()->match(base.str() + "/stick", stick) &&
+ getRawData()->match(base.str() + "/axis", axis) &&
+ getRawData()->match(base.str() + "/low", low) &&
+ getRawData()->match(base.str() + "/high", high);
+}
+
void Configuration::setCustomAxis(Joystick::Key key, int config, const string & name, int stick, int axis, double low, double high){
if (key != Joystick::Invalid){
ostringstream base;
base << config_configuration << "/" << config_input << "/" << INPUT_TYPE << "/";
base << "joystick" << "/" << config << "/";
base << name << "/" << joystickKeyName(key);
removeToken(getRawData(), base.str());
updateToken(getRawData(), base.str() + "/stick", stick);
updateToken(getRawData(), base.str() + "/axis", axis);
updateToken(getRawData(), base.str() + "/low", low);
updateToken(getRawData(), base.str() + "/high", high);
saveConfiguration();
}
}
void Configuration::setKey(int config, const string & name, int value){
if (value != InvalidKey){
ostringstream path;
path << config_configuration << "/" << config_input << "/" << config << "/keys/" << name;
updateToken(getRawData(), path.str(), value);
saveConfiguration();
}
}
void Configuration::setRight(int config, int i){
setKey(config, "right", i);
}
void Configuration::setLeft(int config, int i){
setKey(config, "left", i);
}
void Configuration::setUp(int config, int i){
setKey(config, "up", i);
}
void Configuration::setDown(int config, int i){
setKey(config, "down", i);
}
void Configuration::setAttack1(int config, int i){
setKey(config, "attack1", i);
}
void Configuration::setAttack2(int config, int i){
setKey(config, "attack2", i);
}
void Configuration::setAttack3(int config, int i){
setKey(config, "attack3", i);
}
void Configuration::setAttack4(int config, int i){
setKey(config, "attack4", i);
}
void Configuration::setAttack5(int config, int i){
setKey(config, "attack5", i);
}
void Configuration::setAttack6(int config, int i){
setKey(config, "attack6", i);
}
void Configuration::setJump(int config, int i){
setKey(config, "jump", i);
}
int Configuration::getKey(int config, const string & name, int defaultValue){
ostringstream path;
path << config_input << "/" << INPUT_TYPE << "/" << config << "/keys/" << name;
return getProperty(path.str(), defaultValue);
}
/* this nonsense is just to convert a regular integer into an enum */
/*
static Configuration::JoystickInput intToJoystick(int a){
switch (a){
case Joystick::Up : return Joystick::Up;
case Joystick::Down : return Joystick::Down;
case Joystick::Left : return Joystick::Left;
case Joystick::Right : return Joystick::Right;
case Joystick::Button1 : return Joystick::Button1;
case Joystick::Button2 : return Joystick::Button2;
case Joystick::Button3 : return Joystick::Button3;
case Joystick::Button4 : return Joystick::Button4;
case Joystick::Button5 : return Joystick::Button5;
case Joystick::Button6 : return Joystick::Button6;
case Joystick::Start : return Joystick::Start;
case Joystick::Quit : return Joystick::Quit;
}
return Joystick::Invalid;
}
*/
/*
Configuration::JoystickInput Configuration::getJoystickKey(int config, const string & name, JoystickInput defaultValue){
ostringstream path;
path << config_input << "/" << config << "/joystick/" << name;
return intToJoystick(getProperty(path.str(), defaultValue));
}
*/
int Configuration::getRight(int config){
int normal = 0;
switch (config){
case 0: normal = Keyboard::Key_RIGHT; break;
case 1: normal = Keyboard::Key_L; break;
}
return getKey(config, "right", normal);
}
int Configuration::getLeft(int config){
int normal = 0;
switch (config){
case 0: normal = Keyboard::Key_LEFT; break;
case 1: normal = Keyboard::Key_J; break;
}
return getKey(config, "left", normal);
}
int Configuration::getUp(int config){
int normal = 0;
switch (config){
case 0: normal = Keyboard::Key_UP; break;
case 1: normal = Keyboard::Key_I; break;
}
return getKey(config, "up", normal);
}
int Configuration::getDown(int config){
int normal = 0;
switch (config){
case 0: normal = Keyboard::Key_DOWN; break;
case 1: normal = Keyboard::Key_COMMA; break;
}
return getKey(config, "down", normal);
}
int Configuration::getAttack1(int config){
int normal = 0;
switch (config){
case 0: normal = Keyboard::Key_A; break;
case 1: normal = Keyboard::Key_R; break;
}
return getKey(config, "attack1", normal);
}
int Configuration::getAttack2(int config){
int normal = 0;
switch (config){
case 0: normal = Keyboard::Key_S; break;
case 1: normal = Keyboard::Key_T; break;
}
return getKey(config, "attack2", normal);
}
int Configuration::getAttack3(int config){
int normal = 0;
switch (config){
case 0: normal = Keyboard::Key_D; break;
case 1: normal = Keyboard::Key_Y; break;
}
return getKey(config, "attack3", normal);
}
int Configuration::getAttack4(int config){
int normal = 0;
switch (config){
case 0: normal = Keyboard::Key_Z; break;
case 1: normal = Keyboard::Key_F; break;
}
return getKey(config, "attack4", normal);
}
int Configuration::getAttack5(int config){
int normal = 0;
switch (config){
case 0: normal = Keyboard::Key_X; break;
case 1: normal = Keyboard::Key_G; break;
}
return getKey(config, "attack5", normal);
}
int Configuration::getAttack6(int config){
int normal = 0;
switch (config){
case 0: normal = Keyboard::Key_C; break;
case 1: normal = Keyboard::Key_H; break;
}
return getKey(config, "attack6", normal);
}
int Configuration::getJump(int config){
int normal = 0;
switch (config){
case 0: normal = Keyboard::Key_SPACE; break;
case 1: normal = Keyboard::Key_B; break;
}
return getKey(config, "jump", normal);
}
/*
void Configuration::setJoystickKey(int config, const std::string & name, const Configuration::JoystickInput & what){
if (what != Joystick::Invalid){
ostringstream path;
path << config_configuration << "/" << config_input << "/" << config << "/joystick/" << name;
updateToken(data.raw(), path.str(), what);
saveConfiguration();
}
}
void Configuration::setJoystickRight(int config, Configuration::JoystickInput i){
setJoystickKey(config, "right", i);
}
void Configuration::setJoystickLeft(int config, Configuration::JoystickInput i){
setJoystickKey(config, "left", i);
}
void Configuration::setJoystickUp(int config, Configuration::JoystickInput i){
setJoystickKey(config, "up", i);
}
void Configuration::setJoystickDown(int config, Configuration::JoystickInput i){
setJoystickKey(config, "down", i);
}
void Configuration::setJoystickAttack1(int config, Configuration::JoystickInput i){
setJoystickKey(config, "attack1", i);
}
void Configuration::setJoystickAttack2(int config, Configuration::JoystickInput i){
setJoystickKey(config, "attack2", i);
}
void Configuration::setJoystickAttack3(int config, Configuration::JoystickInput i){
setJoystickKey(config, "attack3", i);
}
void Configuration::setJoystickAttack4(int config, Configuration::JoystickInput i){
setJoystickKey(config, "attack4", i);
}
void Configuration::setJoystickAttack5(int config, Configuration::JoystickInput i){
setJoystickKey(config, "attack5", i);
}
void Configuration::setJoystickAttack6(int config, Configuration::JoystickInput i){
setJoystickKey(config, "attack6", i);
}
void Configuration::setJoystickJump(int config, Configuration::JoystickInput i){
setJoystickKey(config, "jump", i);
}
void Configuration::setJoystickQuit(int config, Configuration::JoystickInput i){
setJoystickKey(config, "quit", i);
}
void Configuration::setJoystickStart(int config, Configuration::JoystickInput i){
setJoystickKey(config, "start", i);
}
Configuration::JoystickInput Configuration::getJoystickRight(int config){
return getJoystickKey(config, "right", Joystick::Right);
}
Configuration::JoystickInput Configuration::getJoystickLeft(int config){
return getJoystickKey(config, "left", Joystick::Left);
}
Configuration::JoystickInput Configuration::getJoystickUp(int config){
return getJoystickKey(config, "up", Joystick::Up);
}
Configuration::JoystickInput Configuration::getJoystickDown(int config){
return getJoystickKey(config, "down", Joystick::Down);
}
Configuration::JoystickInput Configuration::getJoystickAttack1(int config){
return getJoystickKey(config, "attack1", Joystick::Button1);
}
Configuration::JoystickInput Configuration::getJoystickAttack2(int config){
return getJoystickKey(config, "attack2", Joystick::Button2);
}
Configuration::JoystickInput Configuration::getJoystickAttack3(int config){
return getJoystickKey(config, "attack3", Joystick::Button3);
}
Configuration::JoystickInput Configuration::getJoystickAttack4(int config){
return getJoystickKey(config, "attack4", Joystick::Button4);
}
Configuration::JoystickInput Configuration::getJoystickAttack5(int config){
return getJoystickKey(config, "attack5", Joystick::Button5);
}
Configuration::JoystickInput Configuration::getJoystickAttack6(int config){
return getJoystickKey(config, "attack6", Joystick::Button6);
}
Configuration::JoystickInput Configuration::getJoystickJump(int config){
return getJoystickKey(config, "jump", Joystick::Button4);
}
Configuration::JoystickInput Configuration::getJoystickQuit(int config){
return getJoystickKey(config, "quit", Joystick::Quit);
}
Configuration::JoystickInput Configuration::getJoystickStart(int config){
return getJoystickKey(config, "start", Joystick::Start);
}
*/
/*
string Configuration::getCurrentGame(){
return getProperty(config_current_game, string(""));
}
/ * assumes the directory is readable and has a dir/dir.txt in it * /
void Configuration::setCurrentGame(const std::string & str){
setProperty(config_current_game, str);
saveConfiguration();
}
*/
void Configuration::disableSave(){
save = false;
}
void Configuration::setSave(bool what){
save = what;
}
bool Configuration::getSave(){
return save;
}
static Token * removeDuplicates(Token * token){
/* TODO */
return token;
}
Token * Configuration::getRawData(){
if (data == NULL){
data = new Token();
}
return data.raw();
}
void Configuration::loadConfigurations(){
data = new Token();
*data << config_configuration;
try{
Filesystem::AbsolutePath file = Storage::instance().configFile();
TokenReader tr;
Token * head = tr.readTokenFromFile(file.path());
if (*head != config_configuration){
throw LoadException(__FILE__, __LINE__, string("Config file ") + Storage::instance().configFile().path() + " does not use the configuration format" );
}
/* Store the entire configuration tree */
data = removeDuplicates(head->copy());
} catch ( const LoadException & le ){
Global::debug( 0 ) << "Notice: Could not load configuration file " << Storage::instance().configFile().path() << ": " << le.getTrace() << endl;
} catch ( const TokenException & t ){
Global::debug( 0 ) << "Notice: could not open configuration file '" << Storage::instance().configFile().path() << "': " << t.getTrace() << endl;
}
}
void Configuration::saveConfiguration(){
if (!save){
return;
}
if (data != NULL){
ofstream out(Storage::instance().configFile().path().c_str(), ios::trunc | ios::out);
if (! out.bad()){
data->toString(out, string(""));
out << endl;
out.close();
}
}
}
Util::ReferenceCount<Menu::FontInfo> Configuration::menuFont;
bool Configuration::joystickEnabled = true;
int Configuration::getProperty(const std::string & path, int defaultValue){
return getPropertyX(getRawData(), path, defaultValue);
}
void Configuration::setProperty(const std::string & path, int value){
updateToken(getRawData(), string(config_configuration) + "/" + path, value);
saveConfiguration();
}
void Configuration::setProperty(const std::string & path, Token * value){
updateToken(getRawData(), string(config_configuration) + "/" + path, value);
saveConfiguration();
}
Token * Configuration::getProperty(const std::string & path){
return getPropertyX(getRawData(),path);
}
double Configuration::getProperty(const std::string & path, double defaultValue){
return getPropertyX(getRawData(), path, defaultValue);
}
void Configuration::setProperty(const std::string & path, double value){
updateToken(getRawData(), string(config_configuration) + "/" + path, value);
saveConfiguration();
}
bool Configuration::getProperty(const std::string & path, bool defaultValue){
return getPropertyX(getRawData(), path, defaultValue);
}
void Configuration::setProperty(const std::string & path, bool value){
updateToken(getRawData(), string(config_configuration) + "/" + path, value);
saveConfiguration();
}
std::string Configuration::getProperty(const std::string & path, const std::string & defaultValue){
return getPropertyX(getRawData(), path, defaultValue);
}
double Configuration::getGameSpeed(){
return getProperty(config_game_speed, 1.0);
}
void Configuration::setGameSpeed(double s){
setProperty(config_game_speed, s);
saveConfiguration();
}
bool Configuration::getInvincible(){
return getProperty(config_invincible, false);
}
void Configuration::setInvincible(bool i){
setProperty(config_invincible, i);
saveConfiguration();
}
bool Configuration::getFullscreen(){
/* Defaults for all configuration options */
#if defined(PS3) || defined(ANDROID) || defined(IPHONE)
return getProperty(config_fullscreen, true);
#else
return getProperty(config_fullscreen, false);
#endif
}
void Configuration::setFullscreen(bool f){
setProperty(config_fullscreen, f);
saveConfiguration();
}
int Configuration::getLives(){
return getProperty(config_lives, 4);
}
void Configuration::setLives(int l){
setProperty(config_lives, l);
saveConfiguration();
}
int Configuration::getNpcBuddies(){
return getProperty(config_npc_buddies, 1);
}
void Configuration::setNpcBuddies(int i){
setProperty(config_npc_buddies,i);
saveConfiguration();
}
Configuration::PlayMode Configuration::getPlayMode(){
string mode = getProperty("play-mode", string(config_cooperative));
if (mode == config_cooperative){
return Cooperative;
}
if (mode == config_free_for_all){
return FreeForAll;
}
return Cooperative;
}
void Configuration::setPlayMode(Configuration::PlayMode mode){
if (mode == Configuration::Cooperative){
setProperty("play-mode", string(config_cooperative));
} else if (mode == Configuration::FreeForAll){
setProperty("play-mode", string(config_free_for_all));
}
}
std::string Configuration::getLanguage(){
return getProperty("language", string());
}
void Configuration::setLanguage(const std::string & str){
setProperty("language", str);
saveConfiguration();
}
/* In case this is ever useful again */
/*
#ifdef MINPSPW
// default resolution for the psp is 480x272
int Configuration::screen_width = 480;
int Configuration::screen_height = 272;
#else
int Configuration::screen_width = 640;
int Configuration::screen_height = 480;
#endif
*/
#ifdef GCW0
static int DefaultWidth = 320;
static int DefaultHeight = 240;
#else
static int DefaultWidth = 640;
static int DefaultHeight = 480;
#endif
/* TODO: All the screen width/height stuff shares a lot of code. Refactor */
void Configuration::setScreenWidth(int i){
int width = DefaultWidth;
int height = DefaultHeight;
Token * screen = getPropertyX(getRawData(), config_screen_size);
if (screen != NULL){
try{
screen->view() >> width >> height;
} catch (const TokenException & fail){
}
}
width = i;
setProperty(config_screen_size, createToken(config_screen_size, width, height));
saveConfiguration();
}
int Configuration::getScreenWidth(){
int width = DefaultWidth;
int height = DefaultHeight;
Token * screen = getPropertyX(getRawData(), config_screen_size);
if (screen != NULL){
try{
screen->view() >> width >> height;
} catch (const TokenException & fail){
}
} else {
setProperty(config_screen_size, createToken(config_screen_size, width, height));
}
return width;
}
void Configuration::setScreenHeight(int i){
int width = DefaultWidth;
int height = DefaultHeight;
Token * screen = getPropertyX(getRawData(), config_screen_size);
if (screen != NULL){
try{
screen->view() >> width >> height;
} catch (const TokenException & fail){
}
}
height = i;
setProperty(config_screen_size, createToken(config_screen_size, width, height));
saveConfiguration();
}
int Configuration::getScreenHeight(){
int width = DefaultWidth;
int height = DefaultHeight;
Token * screen = getPropertyX(getRawData(), config_screen_size);
if (screen != NULL){
try{
screen->view() >> width >> height;
} catch (const TokenException & fail){
}
} else {
setProperty(config_screen_size, createToken(config_screen_size, width, height));
}
return height;
}
int Configuration::getSoundVolume(){
return getProperty(config_sound, 70);
}
void Configuration::setSoundVolume(int volume){
setProperty(config_sound, volume);
saveConfiguration();
}
int Configuration::getMusicVolume(){
return getProperty(config_music, 70);
}
void Configuration::setMusicVolume(int volume){
setProperty(config_music, volume);
saveConfiguration();
}
bool Configuration::isJoystickEnabled(){
return joystickEnabled;
}
void Configuration::setJoystickEnabled(bool enabled){
joystickEnabled = enabled;
saveConfiguration();
}
std::string Configuration::getQualityFilter(){
return getProperty(config_quality_filter, string("none"));
}
void Configuration::setQualityFilter(const std::string & filter){
setProperty(config_quality_filter, filter);
saveConfiguration();
}
int Configuration::getFps(){
return getProperty(config_fps, 50);
}
void Configuration::setFps(int what){
setProperty(config_fps, what);
saveConfiguration();
}
diff --git a/util/configuration.h b/util/configuration.h
index adfb59ac..912a9358 100644
--- a/util/configuration.h
+++ b/util/configuration.h
@@ -1,182 +1,186 @@
#ifndef _paintown_configuration_h
#define _paintown_configuration_h
#include <string>
#include <map>
#include "input/input.h"
#include "pointer.h"
#include "menu/font-info.h"
namespace Menu{
class FontInfo;
}
class Token;
class Configuration{
public:
virtual ~Configuration();
static void setDefaultKeys(int x);
static void loadConfigurations();
static void saveConfiguration();
enum PlayMode{
Cooperative = 1,
FreeForAll = 2,
};
static void setRight(int config, int i);
static void setLeft(int config, int i);
static void setUp(int config, int i);
static void setDown(int config, int i);
static void setAttack1(int config, int i);
static void setAttack2(int config, int i);
static void setAttack3(int config, int i);
static void setAttack4(int config, int i);
static void setAttack5(int config, int i);
static void setAttack6(int config, int i);
static void setJump(int config, int i);
/* Config is the associated player */
static int getRight(int config);
static int getLeft(int config);
static int getUp(int config);
static int getDown(int config);
static int getAttack1(int config);
static int getAttack2(int config);
static int getAttack3(int config);
static int getAttack4(int config);
static int getAttack5(int config);
static int getAttack6(int config);
static int getJump(int config);
+ /* Returns true if there was a custom axis set, and modifies the output parameters */
+ static bool getCustomAxis(Joystick::Key key, int config, const std::string & name, int & stick, int & axis, double & low, double & high);
static void setCustomAxis(Joystick::Key key, int config, const std::string & name, int stick, int axis, double low, double high);
+ /* Returns true if there was a custom button set, and modifies the output parameters */
+ static bool getCustomButton(Joystick::Key key, int config, const std::string & name, int & button);
static void setCustomButton(Joystick::Key key, int config, const std::string & name, int button);
/*
static void setJoystickRight(int config, JoystickInput i);
static void setJoystickLeft(int config, JoystickInput i);
static void setJoystickUp(int config, JoystickInput i);
static void setJoystickDown(int config, JoystickInput i);
static void setJoystickAttack1(int config, JoystickInput i);
static void setJoystickAttack2(int config, JoystickInput i);
static void setJoystickAttack3(int config, JoystickInput i);
static void setJoystickAttack4(int config, JoystickInput i);
static void setJoystickAttack5(int config, JoystickInput i);
static void setJoystickAttack6(int config, JoystickInput i);
static void setJoystickJump(int config, JoystickInput i);
static void setJoystickStart(int config, JoystickInput i);
static void setJoystickQuit(int config, JoystickInput i);
static JoystickInput getJoystickRight(int config);
static JoystickInput getJoystickLeft(int config);
static JoystickInput getJoystickUp(int config);
static JoystickInput getJoystickDown(int config);
static JoystickInput getJoystickAttack1(int config);
static JoystickInput getJoystickAttack2(int config);
static JoystickInput getJoystickAttack3(int config);
static JoystickInput getJoystickAttack4(int config);
static JoystickInput getJoystickAttack5(int config);
static JoystickInput getJoystickAttack6(int config);
static JoystickInput getJoystickJump(int config);
static JoystickInput getJoystickStart(int config);
static JoystickInput getJoystickQuit(int config);
*/
public:
static double getGameSpeed();
static void setGameSpeed(double s);
static bool getInvincible();
static void setInvincible(bool i);
static bool getFullscreen();
static void setFullscreen(bool f);
static int getLives();
static void setLives(int l);
static int getSoundVolume();
static void setSoundVolume(int volume);
static int getMusicVolume();
static void setMusicVolume(int volume);
static int getNpcBuddies();
static void setNpcBuddies(int i);
static PlayMode getPlayMode();
static void setPlayMode(PlayMode mode);
static void setScreenWidth(int i);
static int getScreenWidth();
static void setScreenHeight(int i);
static int getScreenHeight();
static std::string getQualityFilter();
static void setQualityFilter(const std::string & filter);
static int getFps();
static void setFps(int fps);
static Util::ReferenceCount<Menu::FontInfo> getMenuFont();
static void setMenuFont(const Util::ReferenceCount<Menu::FontInfo> & str);
static bool hasMenuFont();
static int getMenuFontWidth();
static int getMenuFontHeight();
static void setMenuFontWidth(int x);
static void setMenuFontHeight(int x);
/* directory of current game/mod */
/*
static std::string getCurrentGame();
static void setCurrentGame(const std::string & str);
*/
static std::string getLanguage();
static void setLanguage(const std::string & str);
static bool isJoystickEnabled();
static void setJoystickEnabled(bool enabled);
static void setProperty(const std::string & path, const std::string & value);
static std::string getProperty(const std::string & path, const std::string & defaultValue);
static void setProperty(const std::string & path, int value);
static int getProperty(const std::string & path, int value);
static void setProperty(const std::string & path, double value);
static double getProperty(const std::string & path, double value);
static void setProperty(const std::string & path, bool value);
static bool getProperty(const std::string & path, bool value);
static void setProperty(const std::string & path, Token * value);
/* Might return NULL */
static Token * getProperty(const std::string & path);
static void disableSave();
static void setSave(bool what);
static bool getSave();
protected:
Configuration();
Configuration(const Configuration & config);
Configuration & operator=(const Configuration & config);
static Token * getRawData();
static int getKey(int config, const std::string & name, int defaultValue);
static Joystick::Key getJoystickKey(int config, const std::string & name, Joystick::Key defaultValue);
static void setKey(int config, const std::string & name, int value);
static void setJoystickKey(int config, const std::string & name, const Joystick::Key & what);
private:
/* whether to save the configuration or not */
static bool save;
static Util::ReferenceCount<Menu::FontInfo> menuFont;
static bool joystickEnabled;
static Util::ReferenceCount<Token> data;
};
#endif
diff --git a/util/input/allegro5/joystick.cpp b/util/input/allegro5/joystick.cpp
index 5a5d8d01..3bd22c3c 100644
--- a/util/input/allegro5/joystick.cpp
+++ b/util/input/allegro5/joystick.cpp
@@ -1,386 +1,389 @@
#ifdef USE_ALLEGRO5
#include "../joystick.h"
#include "joystick.h"
#include "util/debug.h"
#include <allegro5/allegro.h>
using std::vector;
using std::string;
using std::map;
class ButtonMapping{
public:
ButtonMapping(){
}
virtual ~ButtonMapping(){
}
virtual int toNative(Joystick::Key key) = 0;
virtual Joystick::Key toKey(int button) = 0;
virtual void axisMotionEvents(int stick, int axis, float position, vector<Joystick::Event> & events) = 0;
virtual void hatMotionEvents(int motion, vector<Joystick::Event> & events) = 0;
};
class DefaultMapping: public ButtonMapping {
public:
DefaultMapping(){
}
virtual int toNative(Joystick::Key key){
switch (key){
case Joystick::Button1: return 0;
case Joystick::Button2: return 1;
case Joystick::Button3: return 2;
case Joystick::Button4: return 3;
case Joystick::Button5: return 4;
case Joystick::Button6: return 5;
case Joystick::Start: return 6;
case Joystick::Quit: return 7;
case Joystick::Up: return 8;
case Joystick::Down: return 9;
case Joystick::Left: return 10;
case Joystick::Right: return 11;
case Joystick::Invalid: return -1;
}
return -1;
}
virtual Joystick::Key toKey(int button){
switch (button){
case 0: return Joystick::Button1;
case 1: return Joystick::Button2;
case 2: return Joystick::Button3;
case 3: return Joystick::Button4;
case 4: return Joystick::Button5;
case 5: return Joystick::Button6;
case 6: return Joystick::Start;
case 7: return Joystick::Quit;
case 8: return Joystick::Up;
case 9: return Joystick::Down;
case 10: return Joystick::Left;
case 11: return Joystick::Right;
}
return Joystick::Invalid;
}
virtual void axisMotionEvents(int stick, int axis, float position, vector<Joystick::Event> & events){
}
virtual void hatMotionEvents(int motion, vector<Joystick::Event> & events){
}
virtual ~DefaultMapping(){
}
};
class LogitechPrecision: public ButtonMapping {
public:
enum Buttons{
Button1 = 0,
Button2 = 1,
Button3 = 2,
Button4 = 3,
Start = 8,
Select = 9,
R2 = 7,
R1 = 5,
L2 = 6,
L1 = 4
};
int toNative(Joystick::Key key){
switch (key){
case Joystick::Button1: return Button1;
case Joystick::Button2: return Button2;
case Joystick::Button3: return Button3;
case Joystick::Button4: return Button4;
case Joystick::Button5: return L1;
case Joystick::Button6: return R1;
case Joystick::Start: return Start;
case Joystick::Quit: return Select;
case Joystick::Invalid: return -1;
case Joystick::Left:
case Joystick::Right:
case Joystick::Up:
case Joystick::Down: return -1;
}
return -1;
}
Joystick::Key toKey(int button){
switch (button){
case Button1: return Joystick::Button1;
case Button2: return Joystick::Button2;
case Button3: return Joystick::Button3;
case Button4: return Joystick::Button4;
case L1: return Joystick::Button5;
case R1: return Joystick::Button6;
case Start: return Joystick::Start;
case Select: return Joystick::Quit;
}
return Joystick::Invalid;
}
/* axis 1. negative up, positive down
* axis 0, negative left, positive right
*/
void axisMotionEvents(int stick, int axis, float position, vector<Joystick::Event> & events){
int tolerance = 10;
const int LeftRightAxis = 0;
const int UpDownAxis = 1;
switch (stick){
case 0: {
switch (axis){
case UpDownAxis: {
if (position == -1){
events.push_back(Joystick::Event(Joystick::Up, true));
events.push_back(Joystick::Event(Joystick::Down, false));
} else if (position == 1){
events.push_back(Joystick::Event(Joystick::Up, false));
events.push_back(Joystick::Event(Joystick::Down, true));
} else if (position == 0){
events.push_back(Joystick::Event(Joystick::Up, false));
events.push_back(Joystick::Event(Joystick::Down, false));
}
break;
}
case LeftRightAxis: {
if (position == -1){
events.push_back(Joystick::Event(Joystick::Left, true));
events.push_back(Joystick::Event(Joystick::Right, false));
} else if (position == 1){
events.push_back(Joystick::Event(Joystick::Left, false));
events.push_back(Joystick::Event(Joystick::Right, true));
} else if (position == 0){
events.push_back(Joystick::Event(Joystick::Left, false));
events.push_back(Joystick::Event(Joystick::Right, false));
}
break;
}
default: {
}
}
}
default: {
break;
}
}
#if 0
if (axis == 0){
if (position == 0){
events.push_back(Joystick::Event(Joystick::Left, false));
events.push_back(Joystick::Event(Joystick::Right, false));
} else if (motion == -32768){
events.push_back(Joystick::Event(Joystick::Left, true));
} else if (motion == 32767){
events.push_back(Joystick::Event(Joystick::Right, true));
} else if (motion == 128){
events.push_back(Joystick::Event(Joystick::Up, false));
events.push_back(Joystick::Event(Joystick::Down, false));
} else if (motion == 1){
events.push_back(Joystick::Event(Joystick::Up, true));
} else if (motion == 255){
events.push_back(Joystick::Event(Joystick::Down, true));
}
/*
if (motion < -tolerance){
events.push_back(Joystick::Event(Joystick::Left, true));
} else if (motion > tolerance){
events.push_back(Joystick::Event(Joystick::Right, true));
} else {
/ * fake a release for left and right * /
events.push_back(Joystick::Event(Joystick::Left, false));
events.push_back(Joystick::Event(Joystick::Right, false));
}
*/
} else if (axis == 1){
if (motion < -tolerance){
events.push_back(Joystick::Event(Joystick::Up, true));
} else if (motion > tolerance){
events.push_back(Joystick::Event(Joystick::Down, true));
} else {
events.push_back(Joystick::Event(Joystick::Up, false));
events.push_back(Joystick::Event(Joystick::Down, false));
}
}
#endif
}
virtual void hatMotionEvents(int motion, vector<Joystick::Event> & events){
}
};
static Util::ReferenceCount<ButtonMapping> createMapping(ALLEGRO_JOYSTICK * joystick){
string name = al_get_joystick_name(joystick);
if (name.find("Logitech(R) Precision(TM) Gamepad") != string::npos){
return Util::ReferenceCount<ButtonMapping>(new LogitechPrecision());
}
return Util::ReferenceCount<ButtonMapping>(new DefaultMapping());
}
Allegro5Joystick::Allegro5Joystick(int id):
id(id){
queue = al_create_event_queue();
if (al_is_joystick_installed()){
al_register_event_source(queue, al_get_joystick_event_source());
}
buttons = createMapping(al_get_joystick(id));
+
+ readCustomButtons();
+ readCustomAxes();
}
void Allegro5Joystick::axis(int stick, int axis, float position){
/*
if (stick == 9){
Global::debug(0) << "stick " << stick << " axis " << axis << " position " << position << std::endl;
}
*/
std::set<JoystickListener*> listeners = getListeners();
for (std::set<JoystickListener*>::iterator it = listeners.begin(); it != listeners.end(); it++){
(*it)->axisMotion(this, stick, axis, position);
}
bool handled = false;
for (std::map<Key, Axis>::iterator it = customAxis.begin(); it != customAxis.end(); it++){
Key key = it->first;
Axis & use = it->second;
if (use.stick == stick && use.axis == axis){
handled = true;
bool output = false;
/* Only output an event if the new axis position is different from the last one */
if (position >= use.low && position <= use.high){
if (use.on == false){
use.on = true;
output = true;
}
} else {
/* Not in range, so if we output an event before then output a false event */
if (use.on == true){
use.on = false;
output = true;
}
}
if (output){
events.push_back(Joystick::Event(key, use.on));
}
}
}
/* If no custom axis then use the default joystick handler */
if (!handled){
buttons->axisMotionEvents(stick, axis, position, events);
}
}
Joystick::Key Allegro5Joystick::getKey(int button){
if (customButton.find(button) != customButton.end()){
return customButton[button];
}
return buttons->toKey(button);
}
int Allegro5Joystick::getButton(Key key){
for (std::map<int, Key>::iterator it = customButton.begin(); it != customButton.end(); it++){
if (it->second == key){
return it->first;
}
}
return buttons->toNative(key);
}
void Allegro5Joystick::buttonDown(int button){
// Global::debug(0) << "Button down " << button << std::endl;
std::set<JoystickListener*> listeners = getListeners();
for (std::set<JoystickListener*>::iterator it = listeners.begin(); it != listeners.end(); it++){
(*it)->pressButton(this, button);
}
Key event = getKey(button);
if (event != Invalid){
events.push_back(Event(event, true));
}
}
void Allegro5Joystick::buttonUp(int button){
// Global::debug(0) << "Button up " << button << std::endl;
for (std::set<JoystickListener*>::iterator it = listeners.begin(); it != listeners.end(); it++){
(*it)->releaseButton(this, button);
}
Key event = getKey(button);
if (event != Invalid){
events.push_back(Event(event, false));
}
}
void Allegro5Joystick::poll(){
events.clear();
ALLEGRO_EVENT event;
while (al_get_next_event(queue, &event)){
switch (event.type){
case ALLEGRO_EVENT_JOYSTICK_AXIS: {
if (event.joystick.id == al_get_joystick(id)){
axis(event.joystick.stick, event.joystick.axis, event.joystick.pos);
}
break;
}
case ALLEGRO_EVENT_JOYSTICK_BUTTON_DOWN: {
if (event.joystick.id == al_get_joystick(id)){
buttonDown(event.joystick.button);
}
break;
}
case ALLEGRO_EVENT_JOYSTICK_BUTTON_UP: {
if (event.joystick.id == al_get_joystick(id)){
buttonUp(event.joystick.button);
}
break;
}
}
}
}
std::map<int, std::map<int, double> > Allegro5Joystick::getCurrentAxisValues() const {
ALLEGRO_JOYSTICK_STATE state;
ALLEGRO_JOYSTICK * joystick = al_get_joystick(id);
al_get_joystick_state(joystick, &state);
map<int, map<int, double> > out;
int sticks = al_get_joystick_num_sticks(joystick);
for (int stick = 0; stick < sticks; stick++){
int axis = al_get_joystick_num_axes(joystick, stick);
for (int i = 0; i < axis; i++){
out[stick][i] = state.stick[stick].axis[i];
}
}
return out;
}
int Allegro5Joystick::getDeviceId() const {
return id;
}
std::string Allegro5Joystick::getName() const {
return al_get_joystick_name(al_get_joystick(id));
}
Allegro5Joystick::~Allegro5Joystick(){
al_destroy_event_queue(queue);
queue = NULL;
}
int Joystick::numberOfJoysticks(){
return al_get_num_joysticks();
}
#endif
diff --git a/util/input/joystick.cpp b/util/input/joystick.cpp
index add79f9f..c4c73f83 100644
--- a/util/input/joystick.cpp
+++ b/util/input/joystick.cpp
@@ -1,155 +1,222 @@
#include <stdlib.h>
#include "util/configuration.h"
#include "joystick.h"
/*
#ifdef LINUX
#include "linux_joystick.h"
#endif
*/
#ifdef USE_ALLEGRO
#include "allegro/allegro-joystick.h"
#endif
#ifdef USE_ALLEGRO5
#include "allegro5/joystick.h"
#endif
#ifdef USE_SDL
#ifdef WII
#include "wii/joystick.h"
#include "sdl/joystick.h"
#elif MINPSPW
#include "psp/joystick.h"
#else
#include "sdl/joystick.h"
#endif
#endif
JoystickListener::JoystickListener(){
}
JoystickListener::~JoystickListener(){
}
Joystick * Joystick::create(int i){
#ifdef USE_ALLEGRO
return new AllegroJoystick();
#endif
#ifdef USE_SDL
#ifdef WII
return new SDLJoystick(i);
// return new WiiJoystick();
#elif MINPSPW
return new PSPJoystick();
#else
return new SDLJoystick(i);
#endif
#endif
#ifdef USE_ALLEGRO5
return new Allegro5Joystick(i);
#endif
/* TODO: support allegro5 joystick */
/*
#ifdef LINUX
return new LinuxJoystick();
#endif
return NULL;
*/
return NULL;
}
Joystick::Joystick(){
}
Joystick::~Joystick(){
}
+
+void Joystick::readCustomButton(Key key){
+ int button;
+ if (Configuration::getCustomButton(key, getDeviceId(), getName(), button)){
+ customButton[button] = key;
+ if (customAxis.find(key) != customAxis.end()){
+ customAxis.erase(key);
+ }
+ }
+}
+
+void Joystick::readCustomButtons(){
+ readCustomButton(Up);
+ readCustomButton(Down);
+ readCustomButton(Left);
+ readCustomButton(Right);
+ readCustomButton(Button1);
+ readCustomButton(Button2);
+ readCustomButton(Button3);
+ readCustomButton(Button4);
+ readCustomButton(Button5);
+ readCustomButton(Button6);
+ readCustomButton(Quit);
+ readCustomButton(Start);
+}
+
+void Joystick::readCustomAxis(Key key){
+ int stick, axis;
+ double low, high;
+ if (Configuration::getCustomAxis(key, getDeviceId(), getName(), stick, axis, low, high)){
+ Axis & use = customAxis[key];
+ use.stick = stick;
+ use.axis = axis;
+ use.low = low;
+ use.high = high;
+ use.on = false;
+
+ eraseCustomButton(key);
+ }
+}
+
+void Joystick::readCustomAxes(){
+ readCustomAxis(Up);
+ readCustomAxis(Down);
+ readCustomAxis(Left);
+ readCustomAxis(Right);
+ readCustomAxis(Button1);
+ readCustomAxis(Button2);
+ readCustomAxis(Button3);
+ readCustomAxis(Button4);
+ readCustomAxis(Button5);
+ readCustomAxis(Button6);
+ readCustomAxis(Quit);
+ readCustomAxis(Start);
+
+}
const char * Joystick::keyToName(Key key){
switch (key){
case Invalid: return "Invalid";
case Up: return "Up";
case Down: return "Down";
case Left: return "Left";
case Right: return "Right";
case Button1: return "Button1";
case Button2: return "Button2";
case Button3: return "Button3";
case Button4: return "Button4";
case Button5: return "Button5";
case Button6: return "Button6";
case Start: return "Start";
case Quit: return "Quit";
}
return "Unknown";
}
bool Joystick::pressed() const {
return events.size() > 0;
}
void Joystick::pressButton(int button){
}
void Joystick::releaseButton(int button){
}
void Joystick::axisMotion(int axis, int motion){
}
void Joystick::hatMotion(int motion){
}
void Joystick::setCustomButton(int button, Key key){
Configuration::setCustomButton(key, getDeviceId(), getName(), button);
customButton[button] = key;
/* Can only have one unique button/axis */
if (customAxis.find(key) != customAxis.end()){
customAxis.erase(key);
}
}
+void Joystick::eraseCustomButton(Key key){
+ std::vector<int> keys;
+ for (std::map<int, Key>::iterator it = customButton.begin(); it != customButton.end(); it++){
+ if (it->second == key){
+ keys.push_back(it->first);
+ }
+ }
+
+ for (std::vector<int>::iterator it = keys.begin(); it != keys.end(); it++){
+ customButton.erase(*it);
+ }
+}
+
void Joystick::setCustomAxis(Key key, int stick, int axis, double low, double high){
Configuration::setCustomAxis(key, getDeviceId(), getName(), stick, axis, low, high);
Axis & use = customAxis[key];
use.stick = stick;
use.axis = axis;
use.low = low;
use.high = high;
use.on = false;
/* Can only have one unique button/axis */
- if (customButton.find(key) != customButton.end()){
- customButton.erase(key);
- }
+ eraseCustomButton(key);
}
bool Joystick::getAxis(Key key, int & stick, int & axis, double & low, double & high) const {
std::map<Key, Axis>::const_iterator find = customAxis.find(key);
if (find != customAxis.end()){
const Axis & use = find->second;
stick = use.stick;
axis = use.axis;
low = use.low;
high = use.high;
return true;
} else {
return false;
}
}
void Joystick::addListener(JoystickListener * listener){
listeners.insert(listener);
}
void Joystick::removeListener(JoystickListener * listener){
listeners.erase(listener);
}
std::set<JoystickListener*> Joystick::listeners;
std::set<JoystickListener*> Joystick::getListeners(){
return listeners;
}
diff --git a/util/input/joystick.h b/util/input/joystick.h
index d3a74316..75d7a225 100644
--- a/util/input/joystick.h
+++ b/util/input/joystick.h
@@ -1,161 +1,167 @@
#ifndef _paintown_joystick_h
#define _paintown_joystick_h
#include <vector>
#include <set>
#include <string>
#include <map>
struct JoystickInput{
JoystickInput():
left(false),
right(false),
up(false),
down(false),
button1(false),
button2(false),
button3(false),
button4(false),
button5(false),
button6(false),
quit(false),
start(false){
}
JoystickInput(const JoystickInput & copy):
left(copy.left),
right(copy.right),
up(copy.up),
down(copy.down),
button1(copy.button1),
button2(copy.button2),
button3(copy.button3),
button4(copy.button4),
button5(copy.button5),
button6(copy.button6),
quit(copy.quit),
start(copy.start){
}
/* true if something is pressed */
bool pressed(){
return left || right || up || down ||
button1 || button2 || button3 || button4 ||
button5 || button6 ||
quit || start;
}
bool left;
bool right;
bool up;
bool down;
bool button1;
bool button2;
bool button3;
bool button4;
bool button5;
bool button6;
bool quit;
bool start;
};
/* Callback for joystick actions like button presses, axis motions, etc.
*/
class Joystick;
class JoystickListener{
public:
JoystickListener();
virtual ~JoystickListener();
virtual void pressButton(Joystick * from, int button) = 0;
virtual void releaseButton(Joystick * from, int button) = 0;
virtual void axisMotion(Joystick * from, int stick, int axis, double motion) = 0;
virtual void hatMotion(Joystick * from, int motion) = 0;
};
class Joystick{
public:
virtual void poll() = 0;
// virtual JoystickInput readAll() = 0;
virtual bool pressed() const;
virtual ~Joystick();
virtual int getDeviceId() const = 0;
virtual void pressButton(int button);
virtual void releaseButton(int button);
virtual void axisMotion(int axis, int motion);
virtual void hatMotion(int motion);
virtual std::string getName() const = 0;
/* create the ith joystick */
static Joystick * create(int i);
static int numberOfJoysticks();
enum Key{
Invalid = -1,
Up = 0,
Down,
Left,
Right,
Button1,
Button2,
Button3,
Button4,
Button5,
Button6,
Quit,
Start
};
struct Event{
Event(Key key, bool enabled):
key(key), enabled(enabled){
}
Key key;
bool enabled;
};
virtual inline const std::vector<Event> & getEvents() const {
return events;
}
virtual void setCustomButton(int button, Key key);
virtual void setCustomAxis(Key key, int stick, int axis, double low, double high);
virtual Key getKey(int button) = 0;
virtual int getButton(Key key) = 0;
/* returns true if there is an axis motion for the requested key */
virtual bool getAxis(Key key, int & stick, int & axis, double & low, double & high) const;
virtual std::map<int, std::map<int, double> > getCurrentAxisValues() const = 0;
static const char * keyToName(Key key);
static void addListener(JoystickListener * listener);
static void removeListener(JoystickListener * listener);
protected:
+ void readCustomButtons();
+ void readCustomButton(Key key);
+ void readCustomAxis(Key key);
+ void readCustomAxes();
+ void eraseCustomButton(Key key);
+
static std::set<JoystickListener*> getListeners();
static std::set<JoystickListener*> listeners;
std::vector<Event> events;
std::map<int, Key> customButton;
struct Axis{
int stick;
int axis;
double low;
double high;
/* true if this axis was in range and should not output an event */
bool on;
};
std::map<Key, Axis> customAxis;
Joystick();
};
#endif
diff --git a/util/input/sdl/joystick.cpp b/util/input/sdl/joystick.cpp
index 5cc9f536..1ae908a9 100644
--- a/util/input/sdl/joystick.cpp
+++ b/util/input/sdl/joystick.cpp
@@ -1,771 +1,774 @@
#ifdef USE_SDL
#include <SDL.h>
#include "joystick.h"
#include "util/debug.h"
#include <string>
#include <vector>
#include <exception>
using std::string;
using std::vector;
using std::map;
class ButtonMapping{
public:
ButtonMapping(){
}
virtual ~ButtonMapping(){
}
virtual int toNative(Joystick::Key key) = 0;
virtual Joystick::Key toKey(int button) = 0;
virtual void axisMotionEvents(int axis, int motion, vector<Joystick::Event> & events) = 0;
virtual void hatMotionEvents(int motion, vector<Joystick::Event> & events) = 0;
};
class DefaultButtonMapping: public ButtonMapping {
public:
int toNative(Joystick::Key key){
switch (key){
case Joystick::Button1: return 0;
case Joystick::Button2: return 1;
case Joystick::Button3: return 2;
case Joystick::Button4: return 3;
case Joystick::Quit: return 4;
case Joystick::Button5: return 5;
case Joystick::Button6: return 6;
default: return -1;
}
return -1;
}
Joystick::Key toKey(int button){
switch (button){
case 0: return Joystick::Button1;
case 1: return Joystick::Button2;
case 2: return Joystick::Button3;
case 3: return Joystick::Button4;
case 4: return Joystick::Quit;
case 5: return Joystick::Button5;
case 6: return Joystick::Button6;
default: return Joystick::Invalid;
}
}
virtual void hatMotionEvents(int motion, vector<Joystick::Event> & events){
bool up = false;
bool down = false;
bool left = false;
bool right = false;
switch (motion){
case SDL_HAT_CENTERED: break;
case SDL_HAT_UP: up = true; break;
case SDL_HAT_RIGHT: right = true; break;
case SDL_HAT_DOWN: down = true; break;
case SDL_HAT_LEFT: left = true; break;
case SDL_HAT_RIGHTUP: right = true; up = true; break;
case SDL_HAT_RIGHTDOWN: right = true; down = true; break;
case SDL_HAT_LEFTUP: left = true; up = true; break;
case SDL_HAT_LEFTDOWN: left = true; down = true; break;
}
events.push_back(Joystick::Event(Joystick::Left, left));
events.push_back(Joystick::Event(Joystick::Right, right));
events.push_back(Joystick::Event(Joystick::Down, down));
events.push_back(Joystick::Event(Joystick::Up, up));
}
void axisMotionEvents(int axis, int motion, vector<Joystick::Event> & events){
bool up = false;
bool down = false;
bool left = false;
bool right = false;
if (axis == 0){
if (motion < 0){
left = true;
} else if (motion > 0){
right = true;
}
} else if (axis == 1){
if (motion < 0){
up = true;
} else if (motion > 0){
down = true;
}
}
events.push_back(Joystick::Event(Joystick::Left, left));
events.push_back(Joystick::Event(Joystick::Right, right));
events.push_back(Joystick::Event(Joystick::Down, down));
events.push_back(Joystick::Event(Joystick::Up, up));
}
};
/* used when a ps3 controller is plugged into a usb port of a normal pc */
class Playstation3Controller: public ButtonMapping {
public:
enum Buttons{
Cross = 14,
Circle = 13,
Triangle = 12,
Square = 15,
Start = 3,
Select = 0,
Up = 4,
Left = 7,
Down = 6,
Right = 5,
Stick1 = 1,
Stick2 = 2,
L2 = 8,
L1 = 10,
R2 = 9,
R1 = 11,
/* the middle ps3 button */
Ps3 = 16
};
int toNative(Joystick::Key key){
switch (key){
case Joystick::Button1: return Square;
case Joystick::Button2: return Cross;
case Joystick::Button3: return Circle;
case Joystick::Button4: return Triangle;
case Joystick::Start: return Start;
default: return -1;
}
return -1;
}
Joystick::Key toKey(int button){
switch (button){
case Square: return Joystick::Button1;
case Cross: return Joystick::Button2;
case Circle: return Joystick::Button3;
case Triangle: return Joystick::Button4;
case L1: return Joystick::Button5;
case R1: return Joystick::Button6;
case Start: return Joystick::Start;
case Select: return Joystick::Quit;
case Up: return Joystick::Up;
case Down: return Joystick::Down;
case Left: return Joystick::Left;
case Right: return Joystick::Right;
default: return Joystick::Invalid;
}
}
/* TODO */
void axisMotionEvents(int axis, int motion, vector<Joystick::Event> & events){
}
virtual void hatMotionEvents(int motion, vector<Joystick::Event> & events){
}
};
class LogitechPrecision: public ButtonMapping {
public:
enum Buttons{
Button1 = 0,
Button2 = 1,
Button3 = 2,
Button4 = 3,
Start = 8,
Select = 9,
R2 = 7,
R1 = 5,
L2 = 6,
L1 = 4
};
int toNative(Joystick::Key key){
return -1;
}
Joystick::Key toKey(int button){
switch (button){
case Button1: return Joystick::Button1;
case Button2: return Joystick::Button2;
case Button3: return Joystick::Button3;
case Button4: return Joystick::Button4;
case L1: return Joystick::Button5;
case R1: return Joystick::Button6;
case Start: return Joystick::Start;
case Select: return Joystick::Quit;
}
return Joystick::Invalid;
}
/* axis 1. negative up, positive down
* axis 0, negative left, positive right
*/
void axisMotionEvents(int axis, int motion, vector<Joystick::Event> & events){
int tolerance = 10;
if (axis == 0){
if (motion == 0){
events.push_back(Joystick::Event(Joystick::Left, false));
events.push_back(Joystick::Event(Joystick::Right, false));
} else if (motion == -32768){
events.push_back(Joystick::Event(Joystick::Left, true));
} else if (motion == 32767){
events.push_back(Joystick::Event(Joystick::Right, true));
} else if (motion == 128){
events.push_back(Joystick::Event(Joystick::Up, false));
events.push_back(Joystick::Event(Joystick::Down, false));
} else if (motion == 1){
events.push_back(Joystick::Event(Joystick::Up, true));
} else if (motion == 255){
events.push_back(Joystick::Event(Joystick::Down, true));
}
/*
if (motion < -tolerance){
events.push_back(Joystick::Event(Joystick::Left, true));
} else if (motion > tolerance){
events.push_back(Joystick::Event(Joystick::Right, true));
} else {
/ * fake a release for left and right * /
events.push_back(Joystick::Event(Joystick::Left, false));
events.push_back(Joystick::Event(Joystick::Right, false));
}
*/
} else if (axis == 1){
if (motion < -tolerance){
events.push_back(Joystick::Event(Joystick::Up, true));
} else if (motion > tolerance){
events.push_back(Joystick::Event(Joystick::Down, true));
} else {
events.push_back(Joystick::Event(Joystick::Up, false));
events.push_back(Joystick::Event(Joystick::Down, false));
}
}
}
virtual void hatMotionEvents(int motion, vector<Joystick::Event> & events){
}
};
/* used for the ps3 controller with psl1ght's SDL version */
class Ps3Controller: public ButtonMapping {
public:
enum Buttons{
Left = 0,
Down = 1,
Right = 2,
Up = 3,
Select = 7,
Start = 4,
Square = 8,
Cross = 9,
Circle = 10,
Triangle = 11,
L1 = 13,
R1 = 12,
L2 = 15,
R2 = 14,
L3 = 6,
R3 = 5
};
int toNative(Joystick::Key key){
switch (key){
case Joystick::Button1: return Square;
case Joystick::Button2: return Cross;
case Joystick::Button3: return Circle;
case Joystick::Button4: return Triangle;
case Joystick::Start: return Start;
default: return -1;
}
return -1;
}
Joystick::Key toKey(int button){
switch (button){
case Square: return Joystick::Button1;
case Cross: return Joystick::Button2;
case Circle: return Joystick::Button3;
case Triangle: return Joystick::Button4;
case L1: return Joystick::Button5;
case R1: return Joystick::Button6;
case Start: return Joystick::Start;
case Select: return Joystick::Quit;
case Up: return Joystick::Up;
case Down: return Joystick::Down;
case Left: return Joystick::Left;
case Right: return Joystick::Right;
default: return Joystick::Invalid;
}
}
/* TODO */
void axisMotionEvents(int axis, int motion, vector<Joystick::Event> & events){
}
virtual void hatMotionEvents(int motion, vector<Joystick::Event> & events){
}
};
class XBox360Controller: public ButtonMapping {
public:
enum Buttons{
A = 0,
B = 1,
X = 2,
Y = 3,
L1 = 4,
R1 = 5,
Start = 6,
Xbox = 7,
L3 = 8,
R3 = 9,
Select = 10
};
int toNative(Joystick::Key key){
return -1;
}
Joystick::Key toKey(int button){
switch (button){
case A: return Joystick::Button1;
case B: return Joystick::Button2;
case X: return Joystick::Button3;
case Y: return Joystick::Button4;
case L1: return Joystick::Button5;
case R1: return Joystick::Button6;
case Start: return Joystick::Start;
case Select: return Joystick::Quit;
}
return Joystick::Invalid;
}
void axisMotionEvents(int axis, int motion, vector<Joystick::Event> & events){
/* axis 6 and 7 are the hats. sdl passes them as hat events */
#if 0
if (axis == 6){
if (motion < 0){
events.push_back(Joystick::Event(Joystick::Left, true));
} else if (motion > 0){
events.push_back(Joystick::Event(Joystick::Right, true));
} else if (motion == 0){
/* fake a release for left and right */
events.push_back(Joystick::Event(Joystick::Left, false));
events.push_back(Joystick::Event(Joystick::Right, false));
}
} else if (axis == 7){
if (motion < 0){
events.push_back(Joystick::Event(Joystick::Up, true));
} else if (motion > 0){
events.push_back(Joystick::Event(Joystick::Down, true));
} else if (motion == 0){
events.push_back(Joystick::Event(Joystick::Up, false));
events.push_back(Joystick::Event(Joystick::Down, false));
}
}
#endif
}
virtual void hatMotionEvents(int motion, vector<Joystick::Event> & events){
bool up = false;
bool down = false;
bool left = false;
bool right = false;
switch (motion){
case SDL_HAT_CENTERED: break;
case SDL_HAT_UP: up = true; break;
case SDL_HAT_RIGHT: right = true; break;
case SDL_HAT_DOWN: down = true; break;
case SDL_HAT_LEFT: left = true; break;
case SDL_HAT_RIGHTUP: right = true; up = true; break;
case SDL_HAT_RIGHTDOWN: right = true; down = true; break;
case SDL_HAT_LEFTUP: left = true; up = true; break;
case SDL_HAT_LEFTDOWN: left = true; down = true; break;
}
events.push_back(Joystick::Event(Joystick::Left, left));
events.push_back(Joystick::Event(Joystick::Right, right));
events.push_back(Joystick::Event(Joystick::Down, down));
events.push_back(Joystick::Event(Joystick::Up, up));
}
};
class Wiimote: public ButtonMapping {
public:
enum Buttons{
A = 0,
B = 1,
Button1 = 2,
Button2 = 3,
Minus = 4,
Plus = 5,
Home = 6
};
int toNative(Joystick::Key key){
return -1;
}
/* FIXME: need a start key */
Joystick::Key toKey(int button){
switch (button){
case A: return Joystick::Button1;
case B: return Joystick::Button2;
case Button1: return Joystick::Button3;
case Button2: return Joystick::Button4;
case Minus: return Joystick::Button5;
case Plus: return Joystick::Button6;
case Home: return Joystick::Quit;
}
return Joystick::Invalid;
}
void axisMotionEvents(int axis, int motion, vector<Joystick::Event> & events){
}
virtual void hatMotionEvents(int motion, vector<Joystick::Event> & events){
/* rotate all the directions 90 degrees */
bool up = false; // right
bool down = false; // left
bool left = false; // up
bool right = false; // down
switch (motion){
case SDL_HAT_CENTERED: break;
case SDL_HAT_UP: up = true; break;
case SDL_HAT_RIGHT: right = true; break;
case SDL_HAT_DOWN: down = true; break;
case SDL_HAT_LEFT: left = true; break;
case SDL_HAT_RIGHTUP: up = true; right = true; break;
case SDL_HAT_RIGHTDOWN: down = true; right = true; break;
case SDL_HAT_LEFTUP: up = true; left = true; break;
case SDL_HAT_LEFTDOWN: down = true; left = true; break;
}
events.push_back(Joystick::Event(Joystick::Left, left));
events.push_back(Joystick::Event(Joystick::Right, right));
events.push_back(Joystick::Event(Joystick::Down, down));
events.push_back(Joystick::Event(Joystick::Up, up));
}
};
class GamecubePad: public ButtonMapping {
public:
enum Buttons{
A = 0,
B = 1,
X = 2,
Y = 3,
Z = 4,
Start = 7
};
int toNative(Joystick::Key key){
return -1;
}
Joystick::Key toKey(int button){
switch (button){
case A: return Joystick::Button1;
case B: return Joystick::Button2;
case X: return Joystick::Button3;
case Y: return Joystick::Button4;
case Z: return Joystick::Button5;
case Start: return Joystick::Start;
}
return Joystick::Invalid;
}
void axisMotionEvents(int axis, int motion, vector<Joystick::Event> & events){
// printf("axis %d motion %d\n", axis, motion);
}
virtual void hatMotionEvents(int motion, vector<Joystick::Event> & events){
bool up = false;
bool down = false;
bool left = false;
bool right = false;
switch (motion){
case SDL_HAT_CENTERED: break;
case SDL_HAT_UP: up = true; break;
case SDL_HAT_RIGHT: right = true; break;
case SDL_HAT_DOWN: down = true; break;
case SDL_HAT_LEFT: left = true; break;
case SDL_HAT_RIGHTUP: right = true; up = true; break;
case SDL_HAT_RIGHTDOWN: right = true; down = true; break;
case SDL_HAT_LEFTUP: left = true; up = true; break;
case SDL_HAT_LEFTDOWN: left = true; down = true; break;
}
events.push_back(Joystick::Event(Joystick::Left, left));
events.push_back(Joystick::Event(Joystick::Right, right));
events.push_back(Joystick::Event(Joystick::Down, down));
events.push_back(Joystick::Event(Joystick::Up, up));
}
};
class IControlPad: public ButtonMapping {
public:
enum Buttons{
A = 11,
B = 13,
X = 12,
Y = 10,
Start = 9,
Select = 8,
Up = 0,
Down = 3,
Left = 2,
Right = 1,
L1 = 4,
R1 = 14
};
int toNative(Joystick::Key key){
return -1;
}
Joystick::Key toKey(int button){
switch (button){
case A: return Joystick::Button1;
case B: return Joystick::Button2;
case X: return Joystick::Button3;
case Y: return Joystick::Button4;
case L1: return Joystick::Button5;
case R1: return Joystick::Button6;
case Up: return Joystick::Up;
case Down: return Joystick::Down;
case Left: return Joystick::Left;
case Right: return Joystick::Right;
case Start: return Joystick::Start;
case Select: return Joystick::Quit;
}
return Joystick::Invalid;
}
void axisMotionEvents(int axis, int motion, vector<Joystick::Event> & events){
// printf("axis %d motion %d\n", axis, motion);
}
virtual void hatMotionEvents(int motion, vector<Joystick::Event> & events){
/*
bool up = false;
bool down = false;
bool left = false;
bool right = false;
switch (motion){
case SDL_HAT_CENTERED: break;
case SDL_HAT_UP: up = true; break;
case SDL_HAT_RIGHT: right = true; break;
case SDL_HAT_DOWN: down = true; break;
case SDL_HAT_LEFT: left = true; break;
case SDL_HAT_RIGHTUP: right = true; up = true; break;
case SDL_HAT_RIGHTDOWN: right = true; down = true; break;
case SDL_HAT_LEFTUP: left = true; up = true; break;
case SDL_HAT_LEFTDOWN: left = true; down = true; break;
}
events.push_back(Joystick::Event(Joystick::Left, left));
events.push_back(Joystick::Event(Joystick::Right, right));
events.push_back(Joystick::Event(Joystick::Down, down));
events.push_back(Joystick::Event(Joystick::Up, up));
*/
}
};
ButtonMapping * makeButtonMapping(string name){
#ifdef PS3
return new Ps3Controller();
#endif
if (name == "Sony PLAYSTATION(R)3 Controller"){
return new Playstation3Controller();
}
if (name.find("Logitech(R) Precision(TM) Gamepad") != string::npos){
return new LogitechPrecision();
}
if (name == "Microsoft X-Box 360 pad"){
return new XBox360Controller();
}
if (name.find("Wiimote") != string::npos){
return new Wiimote();
}
if (name.find("Gamecube") != string::npos){
return new GamecubePad();
}
if (name.find("iControlPad") != string::npos){
return new IControlPad();
}
Global::debug(0) << "Unknown controller '" << name << "'. Using default mapping" << std::endl;
return new DefaultButtonMapping();
}
void SDLJoystick::poll(){
events.clear();
}
static bool read_button(SDL_Joystick * joystick, int button){
return SDL_JoystickGetButton(joystick, button);
}
SDLJoystick::~SDLJoystick(){
if (joystick){
SDL_JoystickClose(joystick);
}
}
#if 0
#include <io/pad.h>
#include <fstream>
void hack(){
padInfo padinfo;
int ok = ioPadGetInfo(&padinfo);
if (ok == 0){
std::ofstream out("/dev_hdd0/tmp/p.txt");
out << "PS3 Pad Info" << std::endl;
out << " max " << padinfo.max << std::endl;
out << " connected " << padinfo.connected << std::endl;
out << " status 0 " << (int) padinfo.status[0] << std::endl;
out << " status 1 " << (int) padinfo.status[1] << std::endl;
out << " status 2 " << (int) padinfo.status[2] << std::endl;
out << " status 3 " << (int) padinfo.status[3] << std::endl;
out << " status 4 " << (int) padinfo.status[4] << std::endl;
out.close();
} else {
Global::debug(0) << "Could not get pad info" << std::endl;
}
}
#endif
SDLJoystick::SDLJoystick(int id):
joystick(NULL){
if (SDL_NumJoysticks() > id){
joystick = SDL_JoystickOpen(id);
if (joystick == NULL){
Global::debug(0) << "Could not open joystick at index " << id << std::endl;
} else {
Global::debug(1) << "Opened joystick '" << SDL_JoystickName(id) << "'" << std::endl;
}
// printf("Opened joystick '%s'\n", SDL_JoystickName(4));
buttonMapping = makeButtonMapping(SDL_JoystickName(id));
+
+ readCustomButtons();
+ readCustomAxes();
}
}
Joystick::Key SDLJoystick::getKey(int button){
if (customButton.find(button) != customButton.end()){
return customButton[button];
}
return buttonMapping->toKey(button);
}
int SDLJoystick::getButton(Key key){
for (std::map<int, Key>::iterator it = customButton.begin(); it != customButton.end(); it++){
if (it->second == key){
return it->first;
}
}
return buttonMapping->toNative(key);
}
void SDLJoystick::pressButton(int button){
std::set<JoystickListener*> listeners = getListeners();
for (std::set<JoystickListener*>::iterator it = listeners.begin(); it != listeners.end(); it++){
(*it)->pressButton(this, button);
}
// Global::debug(0) << "Pressed button " << button << std::endl;
if (joystick){
Key event = getKey(button);
if (event != Invalid){
events.push_back(Event(event, true));
}
}
}
void SDLJoystick::releaseButton(int button){
std::set<JoystickListener*> listeners = getListeners();
for (std::set<JoystickListener*>::iterator it = listeners.begin(); it != listeners.end(); it++){
(*it)->releaseButton(this, button);
}
if (joystick){
Key event = getKey(button);
if (event != Invalid){
events.push_back(Event(event, false));
}
}
}
void SDLJoystick::hatMotion(int motion){
std::set<JoystickListener*> listeners = getListeners();
for (std::set<JoystickListener*>::iterator it = listeners.begin(); it != listeners.end(); it++){
(*it)->hatMotion(this, motion);
}
// Global::debug(0) << "Hat motion " << motion << std::endl;
if (joystick){
buttonMapping->hatMotionEvents(motion, events);
}
}
void SDLJoystick::axisMotion(int axis, int motion){
std::set<JoystickListener*> listeners = getListeners();
for (std::set<JoystickListener*>::iterator it = listeners.begin(); it != listeners.end(); it++){
/* Stick is always 0.
* Motions should always fit inside a short, [-32767, 32767]
*/
(*it)->axisMotion(this, 0, axis, (double) motion / 32768.0);
}
// Global::debug(0) << "Axis motion on " << axis << " motion " << motion << std::endl;
if (joystick){
buttonMapping->axisMotionEvents(axis, motion, events);
/*
Event move = buttonMapping->axisMotionToEvent(axis, motion);
if (move.key != Invalid){
events.push_back(move);
}
*/
}
}
string SDLJoystick::getName() const {
if (joystick){
return SDL_JoystickName(getDeviceId());
}
return "";
}
int SDLJoystick::getDeviceId() const {
if (joystick){
return SDL_JoystickIndex(joystick);
}
return -1;
}
std::map<int, std::map<int, double> > SDLJoystick::getCurrentAxisValues() const {
map<int, map<int, double> > out;
if (joystick){
int axis = SDL_JoystickNumAxes(joystick);
for (int i = 0; i < axis; i++){
/* always use stick 0 */
out[0][i] = (double) SDL_JoystickGetAxis(joystick, i) / 32768.0;
}
}
return out;
}
int Joystick::numberOfJoysticks(){
return SDL_NumJoysticks();
}
#endif

File Metadata

Mime Type
text/x-diff
Expires
Wed, Jun 17, 9:07 PM (1 w, 5 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
71387
Default Alt Text
(85 KB)

Event Timeline