- added best-effort algorithm to detect a formerly used joystick
- added stick config entities to configuration which includes a deadzone value - added methods to read and save this new entities - make StickInfo a part of the SDLDriver class - some spelling fixes - save config when leaving options menu through escape key (GA_LEAVE) git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@1679 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
@@ -116,3 +116,12 @@ void Options::select()
|
||||
break;
|
||||
} // switch
|
||||
}
|
||||
|
||||
void Options::handle(GameAction action, int value)
|
||||
{
|
||||
// Save config on leave.
|
||||
if (!value && action == GA_LEAVE)
|
||||
user_config->saveConfig();
|
||||
|
||||
BaseGUI::handle(action, value);
|
||||
}
|
||||
|
||||
@@ -29,6 +29,8 @@ public:
|
||||
~Options();
|
||||
|
||||
void select();
|
||||
void handle(GameAction, int);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
138
src/sdldrv.cpp
138
src/sdldrv.cpp
@@ -45,10 +45,12 @@
|
||||
|
||||
#define DEADZONE_MOUSE 150
|
||||
#define DEADZONE_MOUSE_SENSE 200
|
||||
#define DEADZONE_JOYSTICK 1000
|
||||
#define DEADZONE_JOYSTICK (1000)
|
||||
|
||||
#define MULTIPLIER_MOUSE 750
|
||||
|
||||
using namespace std;
|
||||
|
||||
SDLDriver *inputDriver;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -105,10 +107,7 @@ SDLDriver::SDLDriver()
|
||||
|
||||
SDL_JoystickEventState(SDL_ENABLE);
|
||||
|
||||
const int numSticks = SDL_NumJoysticks();
|
||||
stickInfos = new StickInfo *[numSticks];
|
||||
for (int i = 0; i < numSticks; i++)
|
||||
stickInfos[i] = new StickInfo(i);
|
||||
initStickInfos();
|
||||
|
||||
SDL_WM_SetCaption("SuperTuxKart", NULL);
|
||||
|
||||
@@ -116,6 +115,87 @@ SDLDriver::SDLDriver()
|
||||
setMode(MENU);
|
||||
}
|
||||
|
||||
void
|
||||
SDLDriver::initStickInfos()
|
||||
{
|
||||
int nextIndex = 0;
|
||||
|
||||
// Prepare a list of connected joysticks.
|
||||
const int numSticks = SDL_NumJoysticks();
|
||||
stickInfos = new StickInfo *[numSticks];
|
||||
vector<StickInfo *> *si = new vector<StickInfo *>;
|
||||
for (int i = 0; i < numSticks; i++)
|
||||
si->push_back(stickInfos[i] = new StickInfo(i));
|
||||
|
||||
// Get the list of known configs and make a copy of it.
|
||||
vector<UserConfig::StickConfig *> *sc
|
||||
= new vector<UserConfig::StickConfig *>(*user_config->getStickConfigs());
|
||||
|
||||
bool match;
|
||||
vector<StickInfo *>::iterator si_ite = si->begin();
|
||||
while (si_ite != si->end())
|
||||
{
|
||||
match = false;
|
||||
|
||||
vector<UserConfig::StickConfig *>::iterator sc_ite = sc->begin();
|
||||
while (sc_ite != sc->end())
|
||||
{
|
||||
if (nextIndex <= (*sc_ite)->preferredIndex)
|
||||
nextIndex = (*sc_ite)->preferredIndex + 1;
|
||||
|
||||
if (!(*si_ite)->id->compare((*sc_ite)->id))
|
||||
{
|
||||
// Connected stick matches a stored one.
|
||||
|
||||
// Copy important properties.
|
||||
|
||||
// Deadzone is taken only if its not null.
|
||||
if ((*sc_ite)->deadzone)
|
||||
(*si_ite)->deadzone = (*sc_ite)->deadzone;
|
||||
|
||||
// Restore former used index and other properties.
|
||||
(*si_ite)->index = (*sc_ite)->preferredIndex;
|
||||
|
||||
// Remove matching entries from the list to prevent double
|
||||
// allocation.
|
||||
sc->erase(sc_ite);
|
||||
si->erase(si_ite);
|
||||
|
||||
match = true;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
sc_ite++;
|
||||
}
|
||||
|
||||
if (!match)
|
||||
si_ite++;
|
||||
}
|
||||
delete sc;
|
||||
|
||||
// si now contains all those stick infos which have no stick config yet
|
||||
// and nextIndex is set to the next free index.
|
||||
|
||||
// Now add all those new sticks and generate a config for them.
|
||||
si_ite = si->begin();
|
||||
while (si_ite != si->end())
|
||||
{
|
||||
(*si_ite)->index = nextIndex;
|
||||
|
||||
UserConfig::StickConfig *sc = new UserConfig::StickConfig(*(*si_ite)->id);
|
||||
sc->preferredIndex = nextIndex;
|
||||
sc->deadzone = DEADZONE_JOYSTICK;
|
||||
|
||||
user_config->addStickConfig(sc);
|
||||
|
||||
nextIndex++;
|
||||
si_ite++;
|
||||
}
|
||||
|
||||
delete si;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
SDLDriver::showPointer()
|
||||
@@ -208,9 +288,9 @@ SDLDriver::setVideoMode(bool resetTextures)
|
||||
SDLDriver::~SDLDriver()
|
||||
{
|
||||
const int NUM_STICKS = SDL_NumJoysticks();
|
||||
for (int i=0;i<NUM_STICKS;i++)
|
||||
delete stickInfos[i];
|
||||
|
||||
for (int i = 0; i < NUM_STICKS; i++)
|
||||
delete stickInfos[i];
|
||||
|
||||
delete [] stickInfos;
|
||||
|
||||
SDL_FreeSurface(mainSurface);
|
||||
@@ -271,7 +351,7 @@ SDLDriver::input(InputType type, int id0, int id1, int id2, int value)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Reads the SDL event loop, does some tricks with certain values and calls
|
||||
* input() is appropriate.
|
||||
* input() if appropriate.
|
||||
*
|
||||
* Digital inputs get the value of 32768 when pressed (key/button press,
|
||||
* digital axis) because this is what SDL provides. Relative mouse inputs
|
||||
@@ -291,6 +371,10 @@ void
|
||||
SDLDriver::input()
|
||||
{
|
||||
SDL_Event ev;
|
||||
/* Logical joystick index that is reported to the higher game APIs which
|
||||
* may not be equal to SDL's joystick index.
|
||||
*/
|
||||
int stickIndex;
|
||||
|
||||
while(SDL_PollEvent(&ev))
|
||||
{
|
||||
@@ -365,20 +449,21 @@ SDLDriver::input()
|
||||
break;
|
||||
|
||||
case SDL_JOYAXISMOTION:
|
||||
stickIndex = stickInfos[ev.jaxis.which]->index;
|
||||
// If the joystick axis exceeds the deadzone report the input.
|
||||
// In menu mode (mode = MENU = 0) the joystick number is reported
|
||||
// to be zero in all cases. This has the neat effect that all
|
||||
// joysticks can be used to control the menu.
|
||||
if(ev.jaxis.value <= -DEADZONE_JOYSTICK)
|
||||
if(ev.jaxis.value <= -stickInfos[ev.jaxis.which]->deadzone)
|
||||
{
|
||||
input(IT_STICKMOTION, !mode ? 0 : ev.jaxis.which,
|
||||
input(IT_STICKMOTION, !mode ? 0 : stickIndex,
|
||||
ev.jaxis.axis, AD_NEGATIVE, -ev.jaxis.value);
|
||||
stickInfos[ev.jaxis.which]->prevAxisDirections[ev.jaxis.axis]
|
||||
= AD_NEGATIVE;
|
||||
}
|
||||
else if(ev.jaxis.value >= DEADZONE_JOYSTICK)
|
||||
else if(ev.jaxis.value >= stickInfos[ev.jaxis.which]->deadzone)
|
||||
{
|
||||
input(IT_STICKMOTION, !mode ? 0 : ev.jaxis.which,
|
||||
input(IT_STICKMOTION, !mode ? 0 : stickIndex,
|
||||
ev.jaxis.axis, AD_POSITIVE, ev.jaxis.value);
|
||||
stickInfos[ev.jaxis.which]->prevAxisDirections[ev.jaxis.axis]
|
||||
= AD_POSITIVE;
|
||||
@@ -394,11 +479,11 @@ SDLDriver::input()
|
||||
// two buttons).
|
||||
if (stickInfos[ev.jaxis.which]
|
||||
->prevAxisDirections[ev.jaxis.axis] == AD_NEGATIVE)
|
||||
input(IT_STICKMOTION, !mode ? 0 : ev.jaxis.which,
|
||||
input(IT_STICKMOTION, !mode ? 0 : stickIndex,
|
||||
ev.jaxis.axis, AD_NEGATIVE, 0);
|
||||
else if (stickInfos[ev.jaxis.which]
|
||||
->prevAxisDirections[ev.jaxis.axis] == AD_POSITIVE)
|
||||
input(IT_STICKMOTION, !mode ? 0 : ev.jaxis.which,
|
||||
input(IT_STICKMOTION, !mode ? 0 : stickIndex,
|
||||
ev.jaxis.axis, AD_POSITIVE, 0);
|
||||
|
||||
stickInfos[ev.jaxis.which]->prevAxisDirections[ev.jaxis.axis]
|
||||
@@ -407,13 +492,17 @@ SDLDriver::input()
|
||||
|
||||
break;
|
||||
case SDL_JOYBUTTONUP:
|
||||
stickIndex = stickInfos[ev.jbutton.which]->index;
|
||||
|
||||
// See the SDL_JOYAXISMOTION case label because of !mode thingie.
|
||||
input(IT_STICKBUTTON, !mode ? 0 : ev.jbutton.which, ev.jbutton.button, 0,
|
||||
input(IT_STICKBUTTON, !mode ? 0 : stickIndex, ev.jbutton.button, 0,
|
||||
0);
|
||||
break;
|
||||
case SDL_JOYBUTTONDOWN:
|
||||
stickIndex = stickInfos[ev.jbutton.which]->index;
|
||||
|
||||
// See the SDL_JOYAXISMOTION case label because of !mode thingie.
|
||||
input(IT_STICKBUTTON, !mode ? 0 : ev.jbutton.which, ev.jbutton.button, 0,
|
||||
input(IT_STICKBUTTON, !mode ? 0 : stickIndex, ev.jbutton.button, 0,
|
||||
32768);
|
||||
break;
|
||||
case SDL_USEREVENT:
|
||||
@@ -616,18 +705,27 @@ SDLDriver::setMode(InputDriverMode newMode)
|
||||
}
|
||||
}
|
||||
|
||||
StickInfo::StickInfo(int index)
|
||||
SDLDriver::StickInfo::StickInfo(int sdlIndex)
|
||||
{
|
||||
sdlJoystick = SDL_JoystickOpen(index);
|
||||
sdlJoystick = SDL_JoystickOpen(sdlIndex);
|
||||
|
||||
id = new string(SDL_JoystickName(sdlIndex));
|
||||
|
||||
const int count = SDL_JoystickNumAxes(sdlJoystick);
|
||||
prevAxisDirections = new AxisDirection[count];
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
prevAxisDirections[i] = AD_NEUTRAL;
|
||||
|
||||
deadzone = DEADZONE_JOYSTICK;
|
||||
|
||||
index = -1;
|
||||
}
|
||||
|
||||
StickInfo::~StickInfo()
|
||||
SDLDriver::StickInfo::~StickInfo()
|
||||
{
|
||||
delete id;
|
||||
|
||||
delete prevAxisDirections;
|
||||
|
||||
SDL_JoystickClose(sdlJoystick);
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
#ifndef HEADER_SDLDRV_H
|
||||
#define HEADER_SDLDRV_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
#include "input.hpp"
|
||||
@@ -36,25 +39,33 @@ enum InputDriverMode {
|
||||
BOOTSTRAP
|
||||
};
|
||||
|
||||
struct StickInfo {
|
||||
SDL_Joystick *sdlJoystick;
|
||||
AxisDirection *prevAxisDirections;
|
||||
|
||||
StickInfo(int);
|
||||
~StickInfo();
|
||||
};
|
||||
|
||||
class SDLDriver
|
||||
{
|
||||
class StickInfo {
|
||||
public:
|
||||
SDL_Joystick *sdlJoystick;
|
||||
|
||||
std::string *id;
|
||||
|
||||
int deadzone;
|
||||
|
||||
int index;
|
||||
|
||||
AxisDirection *prevAxisDirections;
|
||||
|
||||
StickInfo(int);
|
||||
|
||||
~StickInfo();
|
||||
};
|
||||
|
||||
Input *sensedInput;
|
||||
ActionMap *actionMap;
|
||||
|
||||
SDL_Surface *mainSurface;
|
||||
long flags;
|
||||
|
||||
|
||||
StickInfo **stickInfos;
|
||||
|
||||
|
||||
InputDriverMode mode;
|
||||
|
||||
/* Helper values to store and track the relative mouse movements. If these
|
||||
@@ -73,6 +84,8 @@ class SDLDriver
|
||||
public:
|
||||
SDLDriver();
|
||||
~SDLDriver();
|
||||
|
||||
void initStickInfos();
|
||||
|
||||
void toggleFullscreen(bool resetTextures=1);
|
||||
|
||||
|
||||
@@ -68,7 +68,8 @@ UserConfig::UserConfig(const std::string& filename)
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
UserConfig::~UserConfig()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/**
|
||||
@@ -333,7 +334,7 @@ void UserConfig::loadConfig(const std::string& filename)
|
||||
{
|
||||
std::string temp;
|
||||
const lisp::Lisp* root = 0;
|
||||
int i;
|
||||
int i = 0;
|
||||
int dirExist = CheckAndCreateDir();
|
||||
// Check if the config directory exists. If not, exit without an error
|
||||
// message, an appropriate message was printed by CheckAndCreateDir
|
||||
@@ -430,6 +431,9 @@ void UserConfig::loadConfig(const std::string& filename)
|
||||
|
||||
//get whether to log errors to file
|
||||
lisp->get("log-errors", m_log_errors);
|
||||
|
||||
// Handle loading the stick config in it own method.
|
||||
readStickConfigs(lisp);
|
||||
|
||||
// Unlock information:
|
||||
const lisp::Lisp* unlock_info = lisp->getLisp("unlock-info");
|
||||
@@ -501,6 +505,43 @@ void UserConfig::loadConfig(const std::string& filename)
|
||||
|
||||
delete root;
|
||||
} // loadConfig
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
UserConfig::readStickConfigs(const lisp::Lisp *r)
|
||||
{
|
||||
string temp;
|
||||
int count = 0;
|
||||
|
||||
const lisp::Lisp *scsreader = r->getLisp("stick-configs");
|
||||
if (scsreader)
|
||||
{
|
||||
scsreader->get("count", count);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
temp = "stick-";
|
||||
temp += (i + '1');
|
||||
const lisp::Lisp *screader = scsreader->getLisp(temp);
|
||||
if (screader)
|
||||
{
|
||||
string *id = new string();
|
||||
screader->get("id", *id);
|
||||
|
||||
StickConfig *sc = new StickConfig(*id);
|
||||
|
||||
screader->get("preferredIndex", sc->preferredIndex);
|
||||
screader->get("deadzone", sc->deadzone);
|
||||
|
||||
m_stickconfigs.push_back(sc);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void
|
||||
UserConfig::readPlayerInput(const lisp::Lisp *r, const char *node,
|
||||
@@ -632,6 +673,8 @@ void UserConfig::saveConfig(const std::string& filename)
|
||||
|
||||
writer->writeComment("error logging to log (true) or stderr (false)");
|
||||
writer->write("log-errors\t", m_log_errors);
|
||||
|
||||
writeStickConfigs(writer);
|
||||
|
||||
// Write unlock information back
|
||||
writer->beginList("unlock-info");
|
||||
@@ -679,6 +722,38 @@ void UserConfig::saveConfig(const std::string& filename)
|
||||
delete writer;
|
||||
} // saveConfig
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
UserConfig::writeStickConfigs(lisp::Writer *writer)
|
||||
{
|
||||
int count = 0;
|
||||
string temp;
|
||||
|
||||
writer->beginList("stick-configs");
|
||||
|
||||
count = m_stickconfigs.size();
|
||||
writer->write("count", count);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
StickConfig *sc = m_stickconfigs[i];
|
||||
temp = "stick-";
|
||||
temp += i + '1';
|
||||
|
||||
writer->beginList(temp);
|
||||
|
||||
writer->write("id", sc->id);
|
||||
writer->write("preferredIndex", sc->preferredIndex);
|
||||
writer->writeComment("0 means that the default deadzone value is used.");
|
||||
writer->write("deadzone", sc->deadzone);
|
||||
|
||||
writer->endList(temp);
|
||||
}
|
||||
|
||||
writer->endList("stick-configs");
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void
|
||||
UserConfig::writePlayerInput(lisp::Writer *writer, const char *node,
|
||||
@@ -976,4 +1051,25 @@ UserConfig::isFixedInput(InputType type, int id0, int id1, int id2)
|
||||
return false;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
UserConfig::addStickConfig(StickConfig *sc)
|
||||
{
|
||||
m_stickconfigs.push_back(sc);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
const std::vector<UserConfig::StickConfig *> *
|
||||
UserConfig::getStickConfigs() const
|
||||
{
|
||||
return &m_stickconfigs;
|
||||
}
|
||||
|
||||
UserConfig::StickConfig::StickConfig(string &newId)
|
||||
: id(newId)
|
||||
{
|
||||
// Nothing else to do.
|
||||
}
|
||||
|
||||
/*EOF*/
|
||||
|
||||
@@ -38,8 +38,9 @@
|
||||
--> if a kart control for (say) player 2 uses the same key as
|
||||
jump for player 1, this problem is not noticed in 0.3, but will
|
||||
cause an undefined game action now
|
||||
6: Added stick configurations.
|
||||
*/
|
||||
#define CURRENT_CONFIG_VERSION 5
|
||||
#define CURRENT_CONFIG_VERSION 6
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -54,7 +55,25 @@ class ActionMap;
|
||||
/*class for managing general tuxkart configuration data*/
|
||||
class UserConfig
|
||||
{
|
||||
public:
|
||||
|
||||
class StickConfig
|
||||
{
|
||||
public:
|
||||
std::string &id;
|
||||
|
||||
int preferredIndex;
|
||||
|
||||
int deadzone;
|
||||
|
||||
StickConfig(std::string &);
|
||||
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
std::vector <StickConfig *> m_stickconfigs;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int count;
|
||||
@@ -80,11 +99,21 @@ private:
|
||||
int m_music;
|
||||
std::string m_warning;
|
||||
|
||||
void readStickConfigs(const lisp::Lisp *);
|
||||
|
||||
void writeStickConfigs(lisp::Writer *);
|
||||
|
||||
void readPlayerInput(const lisp::Lisp *,
|
||||
const char *,
|
||||
KartAction ka,
|
||||
int);
|
||||
|
||||
void writePlayerInput(lisp::Writer *,
|
||||
const char *,
|
||||
KartAction,
|
||||
int);
|
||||
|
||||
|
||||
void readInput(const lisp::Lisp *,
|
||||
const char *,
|
||||
GameAction);
|
||||
@@ -93,10 +122,6 @@ private:
|
||||
const char *,
|
||||
GameAction);
|
||||
|
||||
void writePlayerInput(lisp::Writer *,
|
||||
const char *,
|
||||
KartAction,
|
||||
int);
|
||||
|
||||
/** Iterates through the input mapping and unsets all
|
||||
* where the given input occurs.
|
||||
@@ -172,7 +197,12 @@ public:
|
||||
void loadConfig(const std::string& filename);
|
||||
void saveConfig();
|
||||
void saveConfig(const std::string& filename);
|
||||
|
||||
|
||||
void addStickConfig(UserConfig::StickConfig *);
|
||||
|
||||
const std::vector<StickConfig *> *getStickConfigs() const;
|
||||
|
||||
|
||||
/** Retrieves a human readable string of the mapping for a GameAction */
|
||||
std::string getMappingAsString(GameAction);
|
||||
/** Retrieves a human readable string of the mapping for the given
|
||||
@@ -199,6 +229,7 @@ public:
|
||||
|
||||
/** Creates ActionMap for use in ingame mode. */
|
||||
ActionMap *newIngameActionMap();
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user