Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F133835
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
85 KB
Referenced Files
None
Subscribers
None
View Options
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
Details
Attached
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)
Attached To
Mode
R75 R-Tech1
Attached
Detach File
Event Timeline