Started adding support for multiple keyboard players (does not work at kart selection screen atm)

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/irrlicht@4223 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
auria 2009-11-14 15:09:34 +00:00
parent 1b59004a1e
commit cb91674631
7 changed files with 193 additions and 146 deletions

View File

@ -271,3 +271,14 @@ irr::core::stringw GamepadConfig::toString ()
returnString += DeviceConfig::toString();
return returnString;
}
//------------------------------------------------------------------------------
bool DeviceConfig::hasBindingFor(const int buttonID) const
{
for (int n=0; n<PA_COUNT; n++)
{
if (m_bindings[n].id == buttonID) return true;
}
return false;
}

View File

@ -10,11 +10,11 @@
struct KeyBinding
{
Input::InputType type;
int id;
Input::AxisDirection dir;
};
@ -22,57 +22,59 @@ struct KeyBinding
class DeviceConfig
{
private:
KeyBinding m_bindings[PA_COUNT];
bool m_inuse; // Is there a device connected to the system
// which uses this config?
protected:
std::string m_name;
public:
std::string getName() const { return m_name; };
irr::core::stringw getBindingAsString (const PlayerAction action) const;
irr::core::stringw toString ();
void serialize (std::ofstream& stream);
bool deserializeAction (irr::io::IrrXMLReader* xml);
void setBinding (const PlayerAction action,
const Input::InputType type,
const int id,
Input::AxisDirection direction = Input::AD_NEUTRAL);
void setInUse (bool inuse) {m_inuse = inuse;}
bool isInUse () {return m_inuse;}
// Don't call this directly unless you are KeyboardDevice or GamepadDevice
bool getAction (Input::InputType type,
const int id,
const int value,
PlayerAction* action);
KeyBinding getBinding (int i) {return m_bindings[i];}
private:
KeyBinding m_bindings[PA_COUNT];
bool m_inuse; // Is there a device connected to the system
// which uses this config?
protected:
std::string m_name;
public:
std::string getName() const { return m_name; };
irr::core::stringw getBindingAsString (const PlayerAction action) const;
irr::core::stringw toString ();
void serialize (std::ofstream& stream);
bool deserializeAction (irr::io::IrrXMLReader* xml);
void setBinding (const PlayerAction action,
const Input::InputType type,
const int id,
Input::AxisDirection direction = Input::AD_NEUTRAL);
void setInUse (bool inuse) {m_inuse = inuse;}
bool isInUse () {return m_inuse;}
// Don't call this directly unless you are KeyboardDevice or GamepadDevice
bool getAction (Input::InputType type,
const int id,
const int value,
PlayerAction* action);
KeyBinding getBinding (int i) {return m_bindings[i];}
bool hasBindingFor(const int buttonID) const;
};
//==== K E Y B O A R D C O N F I G =============================================
class KeyboardConfig : public DeviceConfig
{
private:
protected:
public:
void setDefaultBinds ();
void serialize (std::ofstream& stream);
// KeyboardConfig (irr::io::IrrXMLReader* xml);
KeyboardConfig ();
private:
protected:
public:
void setDefaultBinds ();
void serialize (std::ofstream& stream);
// KeyboardConfig (irr::io::IrrXMLReader* xml);
KeyboardConfig ();
};
@ -80,25 +82,25 @@ class KeyboardConfig : public DeviceConfig
class GamepadConfig : public DeviceConfig
{
private:
int m_axis_count;
int m_button_count;
public:
irr::core::stringw toString ();
int getAxisCount() const { return m_axis_count; };
int getButtonCount() const { return m_button_count; };
void serialize (std::ofstream& stream);
void setDefaultBinds ();
GamepadConfig (irr::io::IrrXMLReader* xml);
GamepadConfig (const std::string name,
const int axis_count,
const int btnCount);
// ~GamepadConfig();
private:
int m_axis_count;
int m_button_count;
public:
irr::core::stringw toString ();
int getAxisCount() const { return m_axis_count; };
int getButtonCount() const { return m_button_count; };
void serialize (std::ofstream& stream);
void setDefaultBinds ();
GamepadConfig (irr::io::IrrXMLReader* xml);
GamepadConfig (const std::string name,
const int axis_count,
const int btnCount);
// ~GamepadConfig();
};
#endif

View File

@ -13,7 +13,6 @@
DeviceManager::DeviceManager()
{
m_latest_used_device = NULL;
m_keyboard = NULL;
m_assign_mode = NO_ASSIGN;
}
@ -42,7 +41,7 @@ bool DeviceManager::initialize()
m_keyboard_configs.push_back(new KeyboardConfig());
created = true;
}
m_keyboard = new KeyboardDevice(m_keyboard_configs.get(0));
m_keyboards.push_back(new KeyboardDevice(m_keyboard_configs.get(0)));
// TODO: Detect keyboard presence, if there is no keyboard, this should be false
m_keyboard_configs.get(0)->setInUse(true);
@ -86,13 +85,16 @@ void DeviceManager::setAssignMode(const PlayerAssignMode assignMode)
m_assign_mode = assignMode;
// when going back to no-assign mode, do some cleanup
if(assignMode == NO_ASSIGN)
if (assignMode == NO_ASSIGN)
{
for(int i=0; i < m_gamepads.size(); i++)
for (int i=0; i < m_gamepads.size(); i++)
{
m_gamepads[i].setPlayer(NULL);
}
m_keyboard->setPlayer(NULL);
for (int i=0; i < m_keyboards.size(); i++)
{
m_keyboards[i].setPlayer(NULL);
}
}
}
// -----------------------------------------------------------------------------
@ -148,7 +150,7 @@ bool DeviceManager::getConfigForGamepad(const int irr_id, GamepadConfig **config
// -----------------------------------------------------------------------------
void DeviceManager::addKeyboard(KeyboardDevice* d)
{
m_keyboard = d;
m_keyboards.push_back(d);
}
// -----------------------------------------------------------------------------
void DeviceManager::addGamepad(GamePadDevice* d)
@ -157,24 +159,28 @@ void DeviceManager::addGamepad(GamePadDevice* d)
}
// -----------------------------------------------------------------------------
InputDevice *DeviceManager::mapKeyboardInput( int deviceID,
InputDevice* DeviceManager::mapKeyboardInput( int deviceID,
int btnID,
ActivePlayer **player,
PlayerAction *action )
{
KeyboardDevice *keyboard = m_keyboard;
if (keyboard->hasBinding(btnID, action))
const int keyboard_amount = m_keyboards.size();
for (int n=0; n<keyboard_amount; n++)
{
if (m_assign_mode == NO_ASSIGN) // Don't set the player in NO_ASSIGN mode
{
*player = NULL;
}
else *player = keyboard->m_player;
}
else keyboard = NULL; // If no appropriate bind was found, return NULL
KeyboardDevice *keyboard = m_keyboards.get(n);
return keyboard;
if (keyboard->hasBinding(btnID, action))
{
if (m_assign_mode == NO_ASSIGN) // Don't set the player in NO_ASSIGN mode
{
*player = NULL;
}
else *player = keyboard->m_player;
return keyboard;
}
}
return NULL; // no appropriate binding found
}
//-----------------------------------------------------------------------------
@ -245,7 +251,7 @@ InputDevice* DeviceManager::getLatestUsedDevice()
if (m_latest_used_device == NULL )
{
return m_keyboard;
return m_keyboards.get(0); // FIXME: is this right?
}
return m_latest_used_device;
@ -380,20 +386,27 @@ void DeviceManager::serialize()
configfile.close();
printf("Serialization complete.\n\n");
}
// -----------------------------------------------------------------------------
KeyboardDevice* DeviceManager::getKeyboardFromBtnID(const int btnID)
{
const int keyboard_amount = m_keyboards.size();
for (int n=0; n<keyboard_amount; n++)
{
if (m_keyboards[n].getConfiguration()->hasBindingFor(btnID)) return m_keyboards.get(n);
}
return NULL;
}
// -----------------------------------------------------------------------------
void DeviceManager::shutdown()
{
m_gamepads.clearAndDeleteAll();
m_keyboards.clearAndDeleteAll();
m_gamepad_configs.clearAndDeleteAll();
m_keyboard_configs.clearAndDeleteAll();
m_latest_used_device = NULL;
if (m_keyboard != NULL)
{
delete m_keyboard;
m_keyboard = NULL;
}
}

View File

@ -16,7 +16,7 @@ class DeviceManager
{
private:
KeyboardDevice *m_keyboard;
ptr_vector<KeyboardDevice, HOLD> m_keyboards;
ptr_vector<GamePadDevice, HOLD> m_gamepads;
ptr_vector<KeyboardConfig, HOLD> m_keyboard_configs;
ptr_vector<GamepadConfig, HOLD> m_gamepad_configs;
@ -52,18 +52,27 @@ public:
DeviceManager();
void clearGamepads() { m_gamepads.clearAndDeleteAll(); }
void clearKeyboard() {delete m_keyboard;}
void addKeyboard(KeyboardDevice* d);
// ---- Gamepads ----
void addGamepad(GamePadDevice* d);
int getGamePadAmount() const { return m_gamepads.size(); }
int getGamePadConfigAmount() const { return m_gamepad_configs.size(); }
GamePadDevice* getGamePad(const int i) { return m_gamepads.get(i); }
GamepadConfig* getGamepadConfig(const int i) { return m_gamepad_configs.get(i); }
void clearGamepads() { m_gamepads.clearAndDeleteAll(); }
// ---- Keyboard(s) ----
void addKeyboard(KeyboardDevice* d);
int getKeyboardConfigAmount() const { return m_keyboard_configs.size(); }
KeyboardDevice* getKeyboard(const int i) { return m_keyboards.get(i); }
KeyboardConfig* getKeyboardConfig(const int i) { return m_keyboard_configs.get(i); }
void clearKeyboard() { m_keyboards.clearAndDeleteAll(); }
PlayerAssignMode playerAssignMode() const { return m_assign_mode; }
KeyboardDevice* getKeyboard() { return m_keyboard; }
/** Returns the keyboard that has a binding for this button, or NULL if none */
KeyboardDevice* getKeyboardFromBtnID(const int btnID);
PlayerAssignMode getAssignMode() { return m_assign_mode; }
GamePadDevice* getGamePadFromIrrID(const int i);
InputDevice* getLatestUsedDevice();

View File

@ -228,11 +228,12 @@ int InputManager::getPlayerKeyboardID() const
if (m_device_manager->playerAssignMode() == NO_ASSIGN) return GUI_PLAYER_ID;
// Otherwise, after devices are assigned, we can check the ID
if (m_device_manager->getKeyboard() != NULL)
// FIXME: don't hardcode keyboard 0, there may be multiple keyboard configs
if (m_device_manager->getKeyboard(0) != NULL)
{
if (m_device_manager->getKeyboard()->getPlayer() != NULL)
if (m_device_manager->getKeyboard(0)->getPlayer() != NULL)
{
return m_device_manager->getKeyboard()->getPlayer()->m_id;
return m_device_manager->getKeyboard(0)->getPlayer()->m_id;
}
}
return -1;
@ -318,7 +319,7 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID, int btnID,
InputDevice *device = NULL;
if (type == Input::IT_KEYBOARD)
{
device = m_device_manager->getKeyboard();
device = m_device_manager->getKeyboardFromBtnID(btnID);
}
else if (type == Input::IT_STICKBUTTON || type == Input::IT_STICKMOTION)
{

View File

@ -632,8 +632,8 @@ int main(int argc, char *argv[] )
{
InputDevice *device;
// Use keyboard by default in --no-start-screen
device = input_manager->getDeviceList()->getKeyboard();
// Use keyboard 0 by default in --no-start-screen
device = input_manager->getDeviceList()->getKeyboard(0);
// Create player and associate player with keyboard
StateManager::get()->createActivePlayer( UserConfigParams::m_all_players.get(0), device );

View File

@ -26,7 +26,8 @@
#include "io/file_manager.hpp"
#include "states_screens/dialogs/press_a_key_dialog.hpp"
#include "states_screens/state_manager.hpp"
#include "utils/string_utils.hpp"
#include "utils/translation.hpp"
#include <iostream>
#include <sstream>
@ -96,13 +97,26 @@ void OptionsScreenInput::init()
DynamicRibbonWidget* devices = this->getWidget<DynamicRibbonWidget>("devices");
assert( devices != NULL );
if(!this->m_inited)
{
devices->addItem("Keyboard","keyboard", file_manager->getDataDir() + "/gui/keyboard.png");
if (!this->m_inited)
{
const int keyboard_config_count = input_manager->getDeviceList()->getKeyboardConfigAmount();
for (int i=0; i<keyboard_config_count; i++)
{
KeyboardConfig *config = input_manager->getDeviceList()->getKeyboardConfig(i);
std::ostringstream kbname;
kbname << "keyboard" << i;
const std::string internal_name = kbname.str();
devices->addItem(StringUtils::insertValues(_("Keyboard %i"), i), internal_name,
file_manager->getDataDir() + "/gui/keyboard.png");
}
const int gpad_config_count = input_manager->getDeviceList()->getGamePadConfigAmount();
for(int i = 0; i < gpad_config_count; i++)
for (int i = 0; i < gpad_config_count; i++)
{
GamepadConfig *config = input_manager->getDeviceList()->getGamepadConfig(i);
// Don't display the configuration if a matching device is not available
@ -142,17 +156,19 @@ void OptionsScreenInput::gotSensedInput(Input* sensedInput)
std::string deviceID = devices->getSelectionIDString(GUI_PLAYER_ID);
const bool keyboard = sensedInput->type == Input::IT_KEYBOARD && deviceID== "keyboard";
const bool keyboard = sensedInput->type == Input::IT_KEYBOARD && deviceID.find("keyboard") != std::string::npos;
const bool gamepad = (sensedInput->type == Input::IT_STICKMOTION ||
sensedInput->type == Input::IT_STICKBUTTON) &&
deviceID.find("gamepad") != std::string::npos;
deviceID.find("gamepad") != std::string::npos;
if(!keyboard && !gamepad) return;
if(gamepad)
if (!keyboard && !gamepad) return;
if (gamepad)
{
if(sensedInput->type != Input::IT_STICKMOTION &&
sensedInput->type != Input::IT_STICKBUTTON)
if (sensedInput->type != Input::IT_STICKMOTION &&
sensedInput->type != Input::IT_STICKBUTTON)
{
return; // that kind of input does not interest us
}
}
@ -160,8 +176,12 @@ void OptionsScreenInput::gotSensedInput(Input* sensedInput)
{
std::cout << "% Binding " << KartActionStrings[binding_to_set] << " : setting to keyboard key " << sensedInput->btnID << " \n\n";
KeyboardDevice* keyboard = input_manager->getDeviceList()->getKeyboard();
keyboard->getConfiguration()->setBinding(binding_to_set, Input::IT_KEYBOARD, sensedInput->btnID, Input::AD_NEUTRAL);
// extract keyboard ID from name
int configID = -1;
sscanf( devices->getSelectionIDString(GUI_PLAYER_ID).c_str(), "keyboard%i", &configID );
KeyboardConfig* keyboard = input_manager->getDeviceList()->getKeyboardConfig(configID);
keyboard->setBinding(binding_to_set, Input::IT_KEYBOARD, sensedInput->btnID, Input::AD_NEUTRAL);
// refresh display
init();
@ -169,42 +189,24 @@ void OptionsScreenInput::gotSensedInput(Input* sensedInput)
else if (gamepad)
{
std::cout << "% Binding " << KartActionStrings[binding_to_set] << " : setting to gamepad #" << sensedInput->deviceID << " : ";
if(sensedInput->type == Input::IT_STICKMOTION)
if (sensedInput->type == Input::IT_STICKMOTION)
{
std::cout << "axis " << sensedInput->btnID << " direction " <<
(sensedInput->axisDirection == Input::AD_NEGATIVE ? "-" : "+") << "\n\n";
}
else if(sensedInput->type == Input::IT_STICKBUTTON)
else if (sensedInput->type == Input::IT_STICKBUTTON)
{
std::cout << "button " << sensedInput->btnID << "\n\n";
}
else
{
std::cout << "Sensed unknown gamepad event type??\n";
}
// extract gamepad ID from name
int configID = -1;
sscanf( devices->getSelectionIDString(GUI_PLAYER_ID).c_str(), "gamepad%i", &configID );
/*
if(sscanf( devices->getSelectionIDString().c_str(), "gamepad%i", &gamepadID ) != 1 ||
gamepadID >= input_manager->getDeviceList()->getGamePadAmount())
{
if(gamepadID >= input_manager->getDeviceList()->getGamePadAmount() || gamepadID == -1 )
{
std::cerr << "gamepad ID does not exist (or failed to read it) : " << gamepadID << "\n";
gamepadID = sensedInput->deviceID;
}
if(input_manager->getDeviceList()->getGamepadConfig(gamepadID)->m_index != sensedInput->deviceID)
{
// should not happen, but let's try to be bulletproof...
std::cerr << "The key that was pressed is not on the gamepad we're trying to configure! ID in list=" << gamepadID <<
" which has irrID " << input_manager->getDeviceList()->getGamePad(gamepadID)->m_index <<
" and we got input from " << sensedInput->deviceID << "\n";
}
}
*/
GamepadConfig* config = input_manager->getDeviceList()->getGamepadConfig(configID);
config->setBinding(binding_to_set, sensedInput->type, sensedInput->btnID,
(Input::AxisDirection)sensedInput->axisDirection);
@ -256,22 +258,31 @@ void OptionsScreenInput::eventCallback(Widget* widget, const std::string& name,
assert(devices != NULL);
const std::string& selection = devices->getSelectionIDString(GUI_PLAYER_ID);
if( selection.find("gamepad") != std::string::npos )
if (selection.find("gamepad") != std::string::npos)
{
int i = -1, read = 0;
read = sscanf( selection.c_str(), "gamepad%i", &i );
if(read == 1 && i != -1)
if (read == 1 && i != -1)
{
updateInputButtons( input_manager->getDeviceList()->getGamepadConfig(i) );
}
else
{
std::cerr << "Cannot read internal input device ID : " << selection.c_str() << std::endl;
std::cerr << "Cannot read internal gamepad input device ID : " << selection.c_str() << std::endl;
}
}
else if(selection == "keyboard")
else if (selection.find("keyboard") != std::string::npos)
{
updateInputButtons( input_manager->getDeviceList()->getKeyboard()->getConfiguration() );
int i = -1, read = 0;
read = sscanf( selection.c_str(), "keyboard%i", &i );
if (read == 1 && i != -1)
{
updateInputButtons( input_manager->getDeviceList()->getKeyboardConfig(i) );
}
else
{
std::cerr << "Cannot read internal keyboard input device ID : " << selection.c_str() << std::endl;
}
}
else
{
@ -331,7 +342,7 @@ void OptionsScreenInput::eventCallback(Widget* widget, const std::string& name,
new PressAKeyDialog(0.4f, 0.4f);
std::string selection = devices->getSelectionIDString(GUI_PLAYER_ID);
if (selection == "keyboard")
if (selection.find("keyboard") != std::string::npos)
{
input_manager->setMode(InputManager::INPUT_SENSE_KEYBOARD);
}