Much cleanup and documentation in input code, which was done on the way of fixing a bug that dealt with multiple and/or custom keyboard configs and menu navigation
git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@4355 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
2caccb8c6e
commit
df422703ac
@ -51,7 +51,7 @@ void DeviceConfig::setBinding ( const PlayerAction action,
|
||||
bool DeviceConfig::getAction ( Input::InputType type,
|
||||
const int id,
|
||||
const int value,
|
||||
PlayerAction* action )
|
||||
PlayerAction* action /* out */ )
|
||||
{
|
||||
bool success = false;
|
||||
int n;
|
||||
|
@ -53,7 +53,7 @@ public:
|
||||
bool getAction (Input::InputType type,
|
||||
const int id,
|
||||
const int value,
|
||||
PlayerAction* action);
|
||||
PlayerAction* action /* out */);
|
||||
KeyBinding getBinding (int i) {return m_bindings[i];}
|
||||
|
||||
bool hasBindingFor(const int buttonID) const;
|
||||
|
@ -172,23 +172,29 @@ void DeviceManager::addGamepad(GamePadDevice* d)
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
InputDevice* DeviceManager::mapKeyboardInput( int deviceID,
|
||||
int btnID,
|
||||
ActivePlayer **player,
|
||||
PlayerAction *action )
|
||||
InputDevice* DeviceManager::mapKeyboardInput( int btnID,
|
||||
ActivePlayer **player /* out */,
|
||||
PlayerAction *action /* out */ )
|
||||
{
|
||||
const int keyboard_amount = m_keyboards.size();
|
||||
|
||||
//std::cout << "mapKeyboardInput " << btnID << " to " << keyboard_amount << " keyboards\n";
|
||||
|
||||
for (int n=0; n<keyboard_amount; n++)
|
||||
{
|
||||
KeyboardDevice *keyboard = m_keyboards.get(n);
|
||||
|
||||
if (keyboard->hasBinding(btnID, action))
|
||||
{
|
||||
//std::cout << " binding found in keyboard #" << (n+1) << "; action is " << KartActionStrings[*action] << "\n";
|
||||
if (m_assign_mode == NO_ASSIGN) // Don't set the player in NO_ASSIGN mode
|
||||
{
|
||||
*player = NULL;
|
||||
}
|
||||
else *player = keyboard->m_player;
|
||||
else
|
||||
{
|
||||
*player = keyboard->m_player;
|
||||
}
|
||||
return keyboard;
|
||||
}
|
||||
}
|
||||
@ -202,8 +208,8 @@ InputDevice *DeviceManager::mapGamepadInput( Input::InputType type,
|
||||
int btnID,
|
||||
int axisDir,
|
||||
int value,
|
||||
ActivePlayer **player,
|
||||
PlayerAction *action )
|
||||
ActivePlayer **player /* out */,
|
||||
PlayerAction *action /* out */)
|
||||
{
|
||||
GamePadDevice *gPad = getGamePadFromIrrID(deviceID);
|
||||
|
||||
@ -227,8 +233,6 @@ InputDevice *DeviceManager::mapGamepadInput( Input::InputType type,
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Formerly mapInputToPlayerAndAction(), broken down to be more readable
|
||||
|
||||
bool DeviceManager::translateInput( Input::InputType type,
|
||||
int deviceID,
|
||||
int btnID,
|
||||
@ -243,7 +247,7 @@ bool DeviceManager::translateInput( Input::InputType type,
|
||||
switch (type)
|
||||
{
|
||||
case Input::IT_KEYBOARD:
|
||||
device = mapKeyboardInput(deviceID, btnID, player, action);
|
||||
device = mapKeyboardInput(btnID, player, action);
|
||||
break;
|
||||
case Input::IT_STICKBUTTON:
|
||||
case Input::IT_STICKMOTION:
|
||||
@ -253,6 +257,12 @@ bool DeviceManager::translateInput( Input::InputType type,
|
||||
break;
|
||||
};
|
||||
|
||||
/*
|
||||
if (device != NULL)
|
||||
{
|
||||
std::cout << " binding found; action is " << KartActionStrings[*action] << "\n";
|
||||
}*/
|
||||
|
||||
// Return true if input was successfully translated to an action and player
|
||||
if (device != NULL && abs(value) > Input::MAX_VALUE/2)
|
||||
{
|
||||
|
@ -7,11 +7,23 @@
|
||||
|
||||
enum PlayerAssignMode
|
||||
{
|
||||
NO_ASSIGN, // react to all devices
|
||||
DETECT_NEW, // notify the manager when an inactive device is being asked to activate with fire
|
||||
ASSIGN // only react to assigned devices
|
||||
NO_ASSIGN, //!< react to all devices
|
||||
DETECT_NEW, //!< notify the manager when an inactive device is being asked to activate with fire
|
||||
ASSIGN //!< only react to assigned devices
|
||||
};
|
||||
|
||||
/**
|
||||
* This class holds the list of all known devices (ands their configurations), as well as the list
|
||||
* of currently plugged (used) devices. It thus takes care of finding to which device any given
|
||||
* input belongs, and what action each keypress is bound to, if any (and, since each device is associated
|
||||
* to a player, it also finds which player triggered this action)
|
||||
* These input mapping capabilities should *only* be used through the InputManager, not directly.
|
||||
*
|
||||
* The device manager starts in "no-assign" mode, which means no input configuration is associated
|
||||
* to any player. So all devices will react. This is used in menus before player set-up is done.
|
||||
* Switching back to no-assign mode will also clear anything in devices that was associated with
|
||||
* players in assign mode.
|
||||
*/
|
||||
class DeviceManager
|
||||
{
|
||||
private:
|
||||
@ -24,67 +36,71 @@ private:
|
||||
InputDevice* m_latest_used_device;
|
||||
PlayerAssignMode m_assign_mode;
|
||||
|
||||
// Helper functions, only used internally
|
||||
/**
|
||||
* Helper method, only used internally. Takes care of analyzing gamepad input.
|
||||
*
|
||||
* \param[out] player Which player this input belongs to (only set in ASSIGN mode)
|
||||
* \param[out] action Which action is related to this input trigger
|
||||
* \return The device to which this input belongs
|
||||
*/
|
||||
InputDevice *mapGamepadInput ( Input::InputType type,
|
||||
int deviceID,
|
||||
int btnID,
|
||||
int axisDir,
|
||||
int value,
|
||||
ActivePlayer **player,
|
||||
PlayerAction *action );
|
||||
ActivePlayer **player /* out */,
|
||||
PlayerAction *action /* out */);
|
||||
|
||||
InputDevice *mapKeyboardInput ( int deviceID,
|
||||
int btnID,
|
||||
ActivePlayer **player,
|
||||
PlayerAction *action );
|
||||
/**
|
||||
* Helper method, only used internally. Takes care of analyzing keyboard input.
|
||||
*
|
||||
* \param[out] player Which player this input belongs to (only set in ASSIGN mode)
|
||||
* \param[out] action Which action is related to this input trigger
|
||||
* \return The device to which this input belongs
|
||||
*/
|
||||
InputDevice *mapKeyboardInput ( int btnID,
|
||||
ActivePlayer **player /* out */,
|
||||
PlayerAction *action /* out */);
|
||||
|
||||
bool deserialize();
|
||||
void shutdown();
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* The device manager starts in "no-assign" mode, which means no input configuration is associated
|
||||
* to any player. So all devices will react. This is used in menus before player set-up is done.
|
||||
* Switching back to no-assign mode will also clear anything in devices that was associated with
|
||||
* players in assign mode.
|
||||
*/
|
||||
|
||||
|
||||
DeviceManager();
|
||||
|
||||
// ---- Assign mode ----
|
||||
PlayerAssignMode getAssignMode() const { return m_assign_mode; }
|
||||
void setAssignMode(const PlayerAssignMode assignMode);
|
||||
|
||||
// ---- 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(); }
|
||||
|
||||
GamePadDevice* getGamePadFromIrrID(const int i);
|
||||
void clearGamepads() { m_gamepads.clearAndDeleteAll(); }
|
||||
/** Returns the keyboard that has a binding for this button, or NULL if none */
|
||||
bool getConfigForGamepad(const int sdl_id, GamepadConfig **config);
|
||||
|
||||
// ---- 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; }
|
||||
|
||||
|
||||
/** Returns the keyboard that has a binding for this button, or NULL if none */
|
||||
void clearKeyboard() { m_keyboards.clearAndDeleteAll(); }
|
||||
KeyboardDevice* getKeyboardFromBtnID(const int btnID);
|
||||
PlayerAssignMode getAssignMode() { return m_assign_mode; }
|
||||
GamePadDevice* getGamePadFromIrrID(const int i);
|
||||
InputDevice* getLatestUsedDevice();
|
||||
void setAssignMode(const PlayerAssignMode assignMode);
|
||||
bool getConfigForGamepad(const int sdl_id, GamepadConfig **config);
|
||||
|
||||
|
||||
|
||||
|
||||
/** Given some input, finds to which device it belongs and, using the corresponding device object,
|
||||
* maps this input to the corresponding player and game action. returns false if player/action could not be set.
|
||||
* Special case : can return true but set action to PA_FIRST if the input was used but is not associated to an
|
||||
* action and a player
|
||||
*/
|
||||
|
||||
bool translateInput( Input::InputType type,
|
||||
int deviceID,
|
||||
int btnID,
|
||||
@ -93,7 +109,7 @@ public:
|
||||
ActivePlayer** player /* out */,
|
||||
PlayerAction* action /* out */ );
|
||||
|
||||
/* returns whether a new gamepad was detected */
|
||||
InputDevice* getLatestUsedDevice();
|
||||
bool initialize();
|
||||
void serialize();
|
||||
};
|
||||
|
@ -44,7 +44,7 @@ KeyboardDevice::KeyboardDevice()
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
bool KeyboardDevice::hasBinding(const int id, PlayerAction* action)
|
||||
bool KeyboardDevice::hasBinding(const int id, PlayerAction* action /* out */)
|
||||
{
|
||||
return m_configuration->getAction(Input::IT_KEYBOARD, id, 0, action);
|
||||
}
|
||||
|
@ -44,11 +44,19 @@ public:
|
||||
class KeyboardDevice : public InputDevice
|
||||
{
|
||||
public:
|
||||
bool hasBinding(const int id, PlayerAction* action);
|
||||
|
||||
|
||||
KeyboardDevice();
|
||||
KeyboardDevice(KeyboardConfig *configuration);
|
||||
|
||||
/** checks if this key belongs to this belongs. if yes, sets action and returns true; otherwise returns false */
|
||||
/**
|
||||
* Checks if this key belongs to this device. if yes, sets action and returns true; otherwise returns false
|
||||
*
|
||||
* \param id ID of the key that was pressed
|
||||
* \param[out] action The action associated to this input (only check this value if method returned true)
|
||||
*/
|
||||
bool hasBinding(const int id, PlayerAction* action);
|
||||
|
||||
};
|
||||
|
||||
class GamePadDevice : public InputDevice
|
||||
@ -63,17 +71,22 @@ public:
|
||||
int m_axis_count;
|
||||
int m_button_count;
|
||||
|
||||
|
||||
/** checks if this key belongs to this belongs. if yes, sets action and returns true; otherwise returns false.
|
||||
The 'player' id passed is simply to know where to send 'axis reset's when necessary*/
|
||||
bool hasBinding(Input::InputType type, const int id, const int value, ActivePlayer* player, PlayerAction* action);
|
||||
|
||||
GamePadDevice(const int irrIndex, const std::string name, const int axis_number, const int btnAmount, GamepadConfig *configuration);
|
||||
~GamePadDevice();
|
||||
|
||||
bool isButtonPressed(const int i);
|
||||
void setButtonPressed(const int i, bool isButtonPressed);
|
||||
|
||||
~GamePadDevice();
|
||||
/**
|
||||
* Checks if this key belongs to this device. if yes, sets action and returns true; otherwise returns false.
|
||||
*
|
||||
* \param player Only passed to know where to send 'axis reset's when necessary
|
||||
* \param id ID of the key that was pressed or of the axis that was triggered (depending on
|
||||
* the value of the 'type' parameter)
|
||||
* \param[out] action The action associated to this input (only check this value if method returned true)
|
||||
*/
|
||||
bool hasBinding(Input::InputType type, const int id, const int value, ActivePlayer* player, PlayerAction* action);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -228,7 +228,7 @@ void InputManager::inputSensing(Input::InputType type, int deviceID, int btnID,
|
||||
int InputManager::getPlayerKeyboardID() const
|
||||
{
|
||||
// In no-assign mode, just return the GUI player ID (devices not assigned yet)
|
||||
if (m_device_manager->playerAssignMode() == NO_ASSIGN) return GUI_PLAYER_ID;
|
||||
if (m_device_manager->getAssignMode() == NO_ASSIGN) return GUI_PLAYER_ID;
|
||||
|
||||
// Otherwise, after devices are assigned, we can check the ID
|
||||
// FIXME: don't hardcode keyboard 0, there may be multiple keyboard configs
|
||||
@ -262,8 +262,8 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID, int btnID,
|
||||
|
||||
// in menus, some keyboard keys are standard (before each player selected his device)
|
||||
// FIXME: should enter always work to accept for a player using keyboard?
|
||||
if (StateManager::get()->getGameState() != GUIEngine::GAME && type == Input::IT_KEYBOARD && m_mode == MENU &&
|
||||
m_device_manager->playerAssignMode() == NO_ASSIGN)
|
||||
if (!action_found && StateManager::get()->getGameState() != GUIEngine::GAME && type == Input::IT_KEYBOARD &&
|
||||
m_mode == MENU && m_device_manager->getAssignMode() == NO_ASSIGN)
|
||||
{
|
||||
action = PA_FIRST;
|
||||
|
||||
@ -273,7 +273,10 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID, int btnID,
|
||||
else if (btnID == KEY_RIGHT) action = PA_RIGHT;
|
||||
else if (btnID == KEY_SPACE) action = PA_FIRE;
|
||||
|
||||
if(btnID == KEY_RETURN && GUIEngine::ModalDialog::isADialogActive()) GUIEngine::ModalDialog::onEnterPressed();
|
||||
if (btnID == KEY_RETURN && GUIEngine::ModalDialog::isADialogActive())
|
||||
{
|
||||
GUIEngine::ModalDialog::onEnterPressed();
|
||||
}
|
||||
|
||||
if (action != PA_FIRST)
|
||||
{
|
||||
@ -364,6 +367,7 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID, int btnID,
|
||||
// ... when in menus
|
||||
else
|
||||
{
|
||||
|
||||
// reset timer when released
|
||||
if (abs(value) == 0 && (/*type == Input::IT_KEYBOARD ||*/ type == Input::IT_STICKBUTTON))
|
||||
{
|
||||
@ -390,7 +394,7 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID, int btnID,
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(type == Input::IT_KEYBOARD)
|
||||
else if (type == Input::IT_KEYBOARD)
|
||||
{
|
||||
// keyboard press not handled by device manager / bindings. Check static bindings...
|
||||
handleStaticAction( btnID, value );
|
||||
@ -557,7 +561,7 @@ EventPropagation InputManager::input(const SEvent& event)
|
||||
#endif
|
||||
|
||||
// block events in all modes but initial menus (except in text boxes to allow typing, and except in modal dialogs in-game)
|
||||
if (getDeviceList()->playerAssignMode() != NO_ASSIGN && !GUIEngine::isWithinATextBox() &&
|
||||
if (getDeviceList()->getAssignMode() != NO_ASSIGN && !GUIEngine::isWithinATextBox() &&
|
||||
(!GUIEngine::ModalDialog::isADialogActive() && StateManager::get()->getGameState() == GUIEngine::GAME))
|
||||
{
|
||||
return EVENT_BLOCK;
|
||||
|
Loading…
Reference in New Issue
Block a user