Improved assignment of mouse to which player (a few known glitches when game master uses a gamepad, but getting better overall)

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/irrlicht@4193 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
auria
2009-11-02 01:04:05 +00:00
parent 12ec1f52df
commit bc9f8ebf6c
17 changed files with 142 additions and 64 deletions

View File

@@ -30,11 +30,13 @@ InputDevice* ActivePlayer::getDevice() const
void ActivePlayer::setDevice(InputDevice* device)
{
// unset player from previous device he was assigned to, if any
if (m_device != NULL) m_device->setPlayer(NULL);
m_device = device;
if(device != NULL) device->setPlayer(this);
// inform the devce of its new owner
if (device != NULL) device->setPlayer(this);
}
PlayerKart* ActivePlayer::getKart()

View File

@@ -69,7 +69,7 @@ class ActivePlayer
PlayerProfile* m_player;
InputDevice* m_device;
public:
// ID of this player within the lsit of active players
/** ID of this player within the list of active players */
int m_id;
ActivePlayer(PlayerProfile* player, InputDevice* device);

View File

@@ -45,7 +45,7 @@ namespace GUIEngine
IVideoDriver* g_driver;
Screen* g_current_screen = NULL;
AbstractStateManager* g_state_manager = NULL;
Widget* g_focus_for_player[MAX_PLAYER_COUNT]; // unused for player 0, player 0's focus is tracked by irrlicht
Widget* g_focus_for_player[MAX_PLAYER_COUNT];
}
using namespace Private;

View File

@@ -97,16 +97,20 @@ EventPropagation EventHandler::onGUIEvent(const SEvent& event)
{
RibbonWidget* ribbon = dynamic_cast<RibbonWidget*>(w->m_event_handler);
if (ribbon == NULL) break;
const int playerID = 0; // FIXME : don't hardcode player 0
if (ribbon->mouseHovered(w) == EVENT_LET) transmitEvent(ribbon, ribbon->m_properties[PROP_ID], playerID);
if (ribbon->m_event_handler != NULL) ribbon->m_event_handler->mouseHovered(w);
const int playerID = input_manager->getPlayerKeyboardID();
if (playerID == -1) break;
if (ribbon->mouseHovered(w, playerID) == EVENT_LET) transmitEvent(ribbon, ribbon->m_properties[PROP_ID], playerID);
if (ribbon->m_event_handler != NULL) ribbon->m_event_handler->mouseHovered(w, playerID);
ribbon->setFocusForPlayer(playerID);
}
else
{
// focus on hover for other widgets
const int playerID = 0; // FIXME: don't hardcode player 0 ?
w->setFocusForPlayer(playerID);
const int playerID = input_manager->getPlayerKeyboardID();
if (playerID != -1)
{
w->setFocusForPlayer(playerID);
}
}
break;

View File

@@ -597,11 +597,11 @@ void Skin::drawRibbon(const core::rect< s32 > &rect, Widget* widget, const bool
void Skin::drawRibbonChild(const core::rect< s32 > &rect, Widget* widget, const bool pressed, bool focused)
{
bool mark_selected = widget->isSelected();
bool always_show_selection = false;
const int playerID = 0; // FIXME : don't hardcode player 0 ?
bool mark_selected = widget->isSelected(playerID);
bool always_show_selection = false;
IGUIElement* focusedElem = NULL;
if (GUIEngine::getFocusForPlayer(playerID) != NULL)
{

View File

@@ -63,7 +63,7 @@ Widget::Widget(bool reserve_id)
id = -1;
m_element = NULL;
m_type = WTYPE_NONE;
m_selected = false;
m_event_handler = NULL;
m_show_bounding_box = false;
m_parent = NULL;
@@ -75,6 +75,7 @@ Widget::Widget(bool reserve_id)
for (int n=0; n<MAX_PLAYER_COUNT; n++)
{
m_player_focus[n] = false;
m_selected[n] = false;
}
m_reserved_id = -1;

View File

@@ -105,7 +105,7 @@ namespace GUIEngine
* - in widgets where it makes sense (e.g. ribbon children) and where the
* irrLicht widget can not directly contain this state
*/
bool m_selected;
bool m_selected[MAX_PLAYER_COUNT];
/**
* called when left/right keys pressed and focus is on widget.
@@ -119,7 +119,7 @@ namespace GUIEngine
/** used when you set eventSupervisors - see m_event_handler explainations below
called when one of a widget's children is hovered.
Returns 'true' if main event handler should be notified of a change. */
virtual EventPropagation mouseHovered(Widget* child) { return EVENT_BLOCK; }
virtual EventPropagation mouseHovered(Widget* child, const int playerID) { return EVENT_BLOCK; }
/** override in children if you need to know when the widget is focused. return whether to block event */
virtual EventPropagation focused(const int playerID) { setWithinATextBox(false); return EVENT_LET; }
@@ -272,7 +272,7 @@ namespace GUIEngine
virtual void move(const int x, const int y, const int w, const int h);
bool isSelected() const { return m_selected; }
bool isSelected(const int playerID) const { return m_selected[playerID]; }
bool isSameIrrlichtWidgetAs(const Widget* ref) const { return m_element == ref->m_element; }

View File

@@ -397,14 +397,13 @@ EventPropagation DynamicRibbonWidget::transmitEvent(Widget* w, std::string& orig
return EVENT_LET;
}
// -----------------------------------------------------------------------------
EventPropagation DynamicRibbonWidget::mouseHovered(Widget* child)
EventPropagation DynamicRibbonWidget::mouseHovered(Widget* child, const int playerID)
{
std::cout << "DynamicRibbonWidget::mouseHovered " << playerID << std::endl;
updateLabel();
propagateSelection();
// FIXME: don't hardcode player 0
const int playerID = 0;
if (getSelectedRibbon(playerID) != NULL)
{
const int listenerAmount = m_hover_listeners.size();

View File

@@ -133,10 +133,10 @@ namespace GUIEngine
int m_selected_item[MAX_PLAYER_COUNT];
/** Callbacks */
void onRowChange(RibbonWidget* row, const int playerID);
void add();
EventPropagation mouseHovered(Widget* child);
EventPropagation transmitEvent(Widget* w, std::string& originator, const int playerID);
virtual void onRowChange(RibbonWidget* row, const int playerID);
virtual void add();
virtual EventPropagation mouseHovered(Widget* child, const int playerID);
virtual EventPropagation transmitEvent(Widget* w, std::string& originator, const int playerID);
public:

View File

@@ -18,6 +18,7 @@
#include "guiengine/widgets/ribbon_widget.hpp"
#include "guiengine/engine.hpp"
#include "input/input_manager.hpp"
#include "io/file_manager.hpp"
using namespace GUIEngine;
using namespace irr::core;
@@ -206,7 +207,7 @@ void RibbonWidget::add()
}
// -----------------------------------------------------------------------------
void RibbonWidget::select(std::string item, const int playerID)
void RibbonWidget::select(std::string item, const int mousePlayerID)
{
const int subbuttons_amount = m_children.size();
@@ -214,7 +215,7 @@ void RibbonWidget::select(std::string item, const int playerID)
{
if (m_children[i].m_properties[PROP_ID] == item)
{
m_selection[playerID] = i;
m_selection[mousePlayerID] = i;
updateSelection();
return;
}
@@ -236,8 +237,14 @@ EventPropagation RibbonWidget::rightPressed(const int playerID)
}
updateSelection();
// FIXME: don't hardcode player ID 0
if (playerID == 0) m_mouse_focus = m_children.get(m_selection[playerID]);
if (m_ribbon_type == RIBBON_COMBO)
{
const int mousePlayerID = input_manager->getPlayerKeyboardID();
if (playerID == mousePlayerID)
{
m_mouse_focus = m_children.get(m_selection[mousePlayerID]);
}
}
if (m_ribbon_type != RIBBON_TOOLBAR)
{
@@ -264,8 +271,14 @@ EventPropagation RibbonWidget::leftPressed(const int playerID)
}
updateSelection();
// FIXME: don't hardcode player ID
if (playerID == 0) m_mouse_focus = m_children.get(m_selection[playerID]);
if (m_ribbon_type == RIBBON_COMBO)
{
const int mousePlayerID = input_manager->getPlayerKeyboardID();
if (playerID == mousePlayerID)
{
m_mouse_focus = m_children.get(m_selection[mousePlayerID]);
}
}
if (m_ribbon_type != RIBBON_TOOLBAR)
{
@@ -284,10 +297,13 @@ EventPropagation RibbonWidget::focused(const int playerID)
if (m_children.size() < 1) return EVENT_LET; // empty ribbon
// FIXME: don't hardcode player ID 0
if (m_mouse_focus == NULL && m_selection[playerID] != -1 && playerID == 0)
if (m_ribbon_type == RIBBON_COMBO)
{
m_mouse_focus = m_children.get(m_selection[playerID]);
const int mousePlayerID = input_manager->getPlayerKeyboardID();
if (m_mouse_focus == NULL && m_selection[playerID] != -1 && playerID == mousePlayerID)
{
m_mouse_focus = m_children.get(m_selection[playerID]);
}
}
if (m_event_handler != NULL)
@@ -301,22 +317,31 @@ EventPropagation RibbonWidget::focused(const int playerID)
return EVENT_LET;
}
// -----------------------------------------------------------------------------
EventPropagation RibbonWidget::mouseHovered(Widget* child)
EventPropagation RibbonWidget::mouseHovered(Widget* child, const int mousePlayerID)
{
std::cout << "RibbonWidget::mouseHovered " << mousePlayerID << std::endl;
const int subbuttons_amount = m_children.size();
m_mouse_focus = child;
for (int i=0; i<subbuttons_amount; i++)
if (m_ribbon_type == RIBBON_COMBO)
{
if (m_children.get(i) == child)
std::cout << "SETTING m_mouse_focus\n";
m_mouse_focus = child;
}
// In toolbar ribbons, hovering selects
if (m_ribbon_type == RIBBON_TOOLBAR)
{
for (int i=0; i<subbuttons_amount; i++)
{
// FIXME: don't hardcode player 0 there?
if (m_selection[0] == i) return EVENT_BLOCK; // was already selected, don't send another event
if (m_ribbon_type == RIBBON_TOOLBAR) m_selection[0] = i; // don't change selection on hover for others
break;
if (m_children.get(i) == child)
{
if (m_selection[mousePlayerID] == i) return EVENT_BLOCK; // was already selected, don't send another event
m_selection[mousePlayerID] = i; // don't change selection on hover for others
break;
}
}
}
updateSelection();
return EVENT_BLOCK;
}
@@ -334,14 +359,37 @@ void RibbonWidget::updateSelection()
{
const int subbuttons_amount = m_children.size();
for (int i=0; i<subbuttons_amount; i++)
// FIXME: m_selection, m_selected, m_mouse_focus... what a mess...
//std::cout << "----\n";
// Update selection flags for mouse player
for (int p=0; p<MAX_PLAYER_COUNT; p++)
{
// Player 0 selection
m_children[i].m_selected = (i == m_selection[0]);
for (int i=0; i<subbuttons_amount; i++)
{
m_children[i].m_selected[p] = (i == m_selection[p]);
/*
if (m_children[i].m_selected[p])
std::cout << "m_children[" << i << "].m_selected[" << p << "] = " << m_children[i].m_selected[p] << std::endl;
if (p == 0 && m_children.get(i) == m_mouse_focus)
std::cout << "m_children[" << i << "] is mouse focus" << std::endl;
*/
}
}
// FIXME: don't hardcode player 0
if (subbuttons_amount > 0 && m_ribbon_type == RIBBON_TOOLBAR) m_mouse_focus = m_children.get(m_selection[0]);
// Update the 'mouse focus' if necessary
/*
if (subbuttons_amount > 0 && m_ribbon_type == RIBBON_COMBO)
{
const int mousePlayerID = input_manager->getPlayerKeyboardID();
if (mousePlayerID != -1 && m_selection[mousePlayerID] != -1)
{
m_mouse_focus = m_children.get(m_selection[mousePlayerID]);
std::cout << "RESET mouse focus\n";
}
}
*/
}
// -----------------------------------------------------------------------------
EventPropagation RibbonWidget::transmitEvent(Widget* w, std::string& originator, const int playerID)

View File

@@ -53,18 +53,18 @@ namespace GUIEngine
void updateSelection();
/** Callbacks */
EventPropagation rightPressed(const int playerID=0);
EventPropagation leftPressed(const int playerID=0);
EventPropagation mouseHovered(Widget* child);
EventPropagation transmitEvent(Widget* w, std::string& originator, const int playerID=0);
EventPropagation focused(const int playerID);
virtual EventPropagation rightPressed(const int playerID=0);
virtual EventPropagation leftPressed(const int playerID=0);
virtual EventPropagation mouseHovered(Widget* child, const int playerID);
virtual EventPropagation transmitEvent(Widget* w, std::string& originator, const int playerID=0);
virtual EventPropagation focused(const int playerID);
ptr_vector<irr::gui::IGUIStaticText, REF> m_labels;
public:
/** Contains which element within the ribbon is currently focused (used by the skin to
show mouse hovers over items that are not selected) */
/** Contains which element within the ribbon is currently focused by player 0 (used by the skin to
show mouse hovers over items that are not selected). Only used for COMBO ribbons. */
Widget* m_mouse_focus;
RibbonWidget(const RibbonType type=RIBBON_COMBO);

View File

@@ -63,7 +63,7 @@ public:
GamePadDevice* getGamePad(const int i) { return m_gamepads.get(i); }
GamepadConfig* getGamepadConfig(const int i) { return m_gamepad_configs.get(i); }
PlayerAssignMode playerAssignMode() const { return m_assign_mode; }
KeyboardDevice* getKeyboard(const int i) { return m_keyboard; }
KeyboardDevice* getKeyboard() { return m_keyboard; }
PlayerAssignMode getAssignMode() { return m_assign_mode; }
GamePadDevice* getGamePadFromIrrID(const int i);
InputDevice* getLatestUsedDevice();

View File

@@ -22,6 +22,11 @@ void InputDevice::setPlayer(ActivePlayer* owner)
m_player = owner;
}
#if 0
#pragma mark -
#pragma mark Keyboard
#endif
// -----------------------------------------------------------------------------
KeyboardDevice::KeyboardDevice(KeyboardConfig *configuration)
{
@@ -48,7 +53,7 @@ bool KeyboardDevice::hasBinding(const int id, PlayerAction* action)
#if 0
#pragma mark -
#pragma mark gamepad
#pragma mark Gamepad
#endif

View File

@@ -221,7 +221,22 @@ void InputManager::inputSensing(Input::InputType type, int deviceID, int btnID,
OptionsScreenInput::getInstance()->gotSensedInput(m_sensed_input);
}
}
//-----------------------------------------------------------------------------
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;
// Otherwise, after devices are assigned, we can check the ID
if (m_device_manager->getKeyboard() != NULL)
{
if (m_device_manager->getKeyboard()->getPlayer() != NULL)
{
return m_device_manager->getKeyboard()->getPlayer()->m_id;
}
}
return -1;
}
//-----------------------------------------------------------------------------
/** Handles the conversion from some input to a GameAction and its distribution
* to the currently active menu.
@@ -302,9 +317,13 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID, int btnID,
{
InputDevice *device = NULL;
if (type == Input::IT_KEYBOARD)
device = m_device_manager->getKeyboard(0);
{
device = m_device_manager->getKeyboard();
}
else if (type == Input::IT_STICKBUTTON || type == Input::IT_STICKMOTION)
{
device = m_device_manager->getGamePadFromIrrID(deviceID);
}
if (device != NULL)
{

View File

@@ -60,8 +60,7 @@ private:
* axis which was pushed the furthest when sensing input. */
int m_max_sensed_input;
Input::InputType m_max_sensed_type;
//ActionMap *m_action_map;
//GamePadDevice **m_stick_infos;
InputDriverMode m_mode;
/* Helper values to store and track the relative mouse movements. If these
@@ -89,7 +88,8 @@ public:
void update(float dt);
//Input &getSensedInput();
/** Returns the ID of the player that plays with the keyboard, or -1 if none */
int getPlayerKeyboardID() const;
};
extern InputManager *input_manager;

View File

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

View File

@@ -161,7 +161,7 @@ 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(0);
KeyboardDevice* keyboard = input_manager->getDeviceList()->getKeyboard();
keyboard->getConfiguration()->setBinding(binding_to_set, Input::IT_KEYBOARD, sensedInput->btnID, Input::AD_NEUTRAL);
// refresh display
@@ -273,7 +273,7 @@ void OptionsScreenInput::eventCallback(Widget* widget, const std::string& name,
}
else if(selection == "keyboard")
{
updateInputButtons( input_manager->getDeviceList()->getKeyboard(0)->getConfiguration() );
updateInputButtons( input_manager->getDeviceList()->getKeyboard()->getConfiguration() );
}
else
{