Yay for another mammoth commit! Totally refactored focus handling code; ditched irrlicht code, completely switched to my own. Things are now much clearer. A few known glitches were introduced and should be corrected soon

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/irrlicht@4180 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
auria 2009-10-31 19:09:45 +00:00
parent 4f7187467b
commit 8a3bcdaa03
20 changed files with 282 additions and 248 deletions

View File

@ -35,8 +35,7 @@ using namespace irr::video;
namespace GUIEngine
{
Widget* g_focus_for_player[MAX_PLAYER_COUNT]; // unused for player 0, player 0's focus is tracked by irrlicht
namespace Private
{
IGUIEnvironment* g_env;
@ -46,9 +45,10 @@ 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
}
using namespace Private;
ptr_vector<Widget, REF> needsUpdate;
ptr_vector<Screen, REF> g_loaded_screens;
@ -58,6 +58,34 @@ namespace GUIEngine
{
return dt;
}
Widget* getFocusForPlayer(const int playerID)
{
assert(playerID >= 0);
assert(playerID < MAX_PLAYER_COUNT);
return g_focus_for_player[playerID];
}
void focusNothingForPlayer(const int playerID)
{
Widget* focus = getFocusForPlayer(playerID);
if (focus != NULL) focus->unsetFocusForPlayer(playerID);
g_focus_for_player[playerID] = NULL;
}
bool isFocusedForPlayer(const Widget* w, const int playerID)
{
assert(w != NULL);
assert(playerID >= 0);
assert(playerID < MAX_PLAYER_COUNT);
// If no focus
if (g_focus_for_player[playerID] == NULL) return false;
// otherwise check if the focus is the given widget
return g_focus_for_player[playerID]->isSameIrrlichtWidgetAs(w);
}
// -----------------------------------------------------------------------------
void clear()
{

View File

@ -205,14 +205,31 @@ being left, allowing for setup/clean-up.
#include "utils/ptr_vector.hpp"
namespace GUIEngine
{
extern Widget* g_focus_for_player[MAX_PLAYER_COUNT]; // unused for player 0, player 0's focus is tracked by irrlicht;
{
class Screen;
class CutScene;
class Widget;
/** Returns the widget currently focused by given player, or NULL if none.
Do NOT use irrLicht's GUI focus facilities; it's too limited for our
needs, so we use ours. (i.e. always call these functions are never those
in IGUIEnvironment) */
Widget* getFocusForPlayer(const int playerID);
/** Focuses nothing for given player (removes any selection for this player).
Do NOT use irrLicht's GUI focus facilities; it's too limited for our
needs, so we use ours. (i.e. always call these functions are never those
in IGUIEnvironment) */
void focusNothingForPlayer(const int playerID);
/** Returns whether given the widget is currently focused by given player.
Do NOT use irrLicht's GUI focus facilities; it's too limited for our
needs, so we use ours. (i.e. always call these functions are never those
in IGUIEnvironment) */
bool isFocusedForPlayer(const Widget*w, const int playerID);
// In an attempt to make getters as fast as possible by possibly allowing inlining
// These fields should never be accessed outside of the GUI engine.
namespace Private
{
extern irr::gui::IGUIEnvironment* g_env;
@ -222,6 +239,7 @@ namespace GUIEngine
extern irr::video::IVideoDriver* g_driver;
extern Screen* g_current_screen;
extern AbstractStateManager* g_state_manager;
extern Widget* g_focus_for_player[MAX_PLAYER_COUNT];
}
inline IrrlichtDevice* getDevice() { return Private::g_device; }

View File

@ -97,12 +97,13 @@ EventPropagation EventHandler::onGUIEvent(const SEvent& event)
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);
getGUIEnv()->setFocus(ribbon->m_element);
ribbon->setFocusForPlayer(playerID);
}
else
{
// focus on hover for other widgets
getGUIEnv()->setFocus(w->m_element);
const int playerID = 0; // FIXME: don't hardcode player 0 ?
w->setFocusForPlayer(playerID);
}
break;
@ -116,11 +117,13 @@ EventPropagation EventHandler::onGUIEvent(const SEvent& event)
break;
}
*/
case EGET_ELEMENT_FOCUSED:
case EGET_ELEMENT_FOCUSED: // FIXME: is this still used with the new focus implementation?
{
Widget* w = GUIEngine::getWidget(id);
if (w == NULL) break;
std::cout << "==== irrlicht widget focused : " << w->m_properties[PROP_ID] << std::endl;
// FIXME: don't hardcode player 0
return w->focused(0);
@ -210,21 +213,7 @@ void EventHandler::processAction(const int action, const unsigned int value, Inp
{
case PA_LEFT:
{
Widget* w = NULL;
// TODO : unify player 0 and players > 0 focus navigation to eliminate this kind of branching
if (playerID == 0)
{
IGUIElement *el = GUIEngine::getGUIEnv()->getFocus();
if (el == NULL) break;
w = GUIEngine::getWidget( el->getID() );
}
else
{
w = GUIEngine::g_focus_for_player[playerID];
}
Widget* w = GUIEngine::getFocusForPlayer(playerID);
if (w == NULL) break;
Widget* widget_to_call = w;
@ -235,34 +224,24 @@ void EventHandler::processAction(const int action, const unsigned int value, Inp
On the way, also notify everyone in the chain of the left press. */
while (widget_to_call->m_event_handler != NULL && widget_to_call->m_event_handler != widget_to_call)
{
widget_to_call->leftPressed(playerID);
if (widget_to_call->leftPressed(playerID) == EVENT_LET)
{
transmitEvent(w, w->m_properties[PROP_ID], playerID);
}
widget_to_call = widget_to_call->m_event_handler;
}
if (widget_to_call->leftPressed(playerID) == EVENT_LET)
{
transmitEvent(w, w->m_properties[PROP_ID], playerID);
transmitEvent(widget_to_call, widget_to_call->m_properties[PROP_ID], playerID);
}
}
break;
case PA_RIGHT:
{
Widget* w = NULL;
// TODO : unify player 0 and players > 0 focus navigation to eliminate this kind of branching
if (playerID == 0)
{
IGUIElement *el = GUIEngine::getGUIEnv()->getFocus();
if(el == NULL) break;
w = GUIEngine::getWidget( el->getID() );
}
else
{
w = GUIEngine::g_focus_for_player[playerID];
}
Widget* w = GUIEngine::getFocusForPlayer(playerID);
if (w == NULL) break;
Widget* widget_to_call = w;
@ -272,13 +251,16 @@ void EventHandler::processAction(const int action, const unsigned int value, Inp
On the way, also notify everyone in the chain of the right press */
while (widget_to_call->m_event_handler != NULL && widget_to_call->m_event_handler != widget_to_call)
{
widget_to_call->rightPressed(playerID);
if (widget_to_call->rightPressed(playerID) == EVENT_LET)
{
transmitEvent(widget_to_call, w->m_properties[PROP_ID], playerID);
}
widget_to_call = widget_to_call->m_event_handler;
}
if (widget_to_call->rightPressed(playerID) == EVENT_LET)
{
transmitEvent(widget_to_call, w->m_properties[PROP_ID], playerID);
transmitEvent(widget_to_call, widget_to_call->m_properties[PROP_ID], playerID);
}
}
break;
@ -298,19 +280,7 @@ void EventHandler::processAction(const int action, const unsigned int value, Inp
case PA_FIRE:
if (pressedDown)
{
Widget* w = NULL;
// FIXME: remove special case for player 0
if (playerID == 0)
{
IGUIElement* element = GUIEngine::getGUIEnv()->getFocus();
if (element == NULL) break;
w = GUIEngine::getWidget( element->getID() );
}
else
{
w = GUIEngine::g_focus_for_player[playerID];
}
Widget* w = GUIEngine::getFocusForPlayer(playerID);
if (w == NULL) break;
// FIXME : consider returned value?
onWidgetActivated( w, playerID );
@ -338,23 +308,11 @@ void EventHandler::processAction(const int action, const unsigned int value, Inp
void EventHandler::navigateUp(const int playerID, Input::InputType type, const bool pressedDown)
{
std::cout << "Naviagte up!\n";
IGUIElement *el = NULL, *first=NULL, *closest=NULL;
// TODO : unify player 0 and players > 0 focus navigation to eliminate this kind of branching
if (playerID == 0)
{
el = GUIEngine::getGUIEnv()->getFocus();
}
else
{
Widget* widget = g_focus_for_player[playerID];
if (widget != NULL)
{
el = widget->m_element;
}
}
Widget* w = (el == NULL) ? NULL : GUIEngine::getWidget( el->getID() );
Widget* w = GUIEngine::getFocusForPlayer(playerID);
if (w != NULL) el = w->getIrrlichtElement();
// list widgets are a bit special, because up/down keys are also used
// to navigate between various list items, not only to navigate between
@ -365,7 +323,7 @@ void EventHandler::navigateUp(const int playerID, Input::InputType type, const b
assert(list != NULL);
const bool stay_within_list = list->getSelected() > 0;
/*
if (type == Input::IT_STICKMOTION)
{
// simulate a key press
@ -376,33 +334,40 @@ void EventHandler::navigateUp(const int playerID, Input::InputType type, const b
wrapper.KeyInput = evt;
wrapper.EventType = EET_KEY_INPUT_EVENT;
GUIEngine::getDevice()->postEventFromUser(wrapper);
}
}*/
if (stay_within_list) return;
else list->setSelected(-1);
if (stay_within_list)
{
list->setSelected(list->getSelected()-1);
return;
}
else
{
list->setSelected(-1);
}
}
if (w != NULL && w->m_tab_up_root != -1) el = GUIEngine::getWidget( w->m_tab_up_root )->getIrrlichtElement();
if (el == NULL)
if (w != NULL && w->m_tab_up_root != -1)
{
std::cerr << "WARNING : m_tab_down_root is set to an ID for which I can't find the widget\n";
return;
Widget* up = GUIEngine::getWidget( w->m_tab_up_root );
assert( up != NULL );
el = up->getIrrlichtElement();
if (el == NULL)
{
std::cerr << "WARNING : m_tab_down_root is set to an ID for which I can't find the widget\n";
return;
}
}
// find closest widget
if (el != NULL && el->getTabGroup() != NULL &&
el->getTabGroup()->getNextElement(el->getTabOrder(), true /* reverse */, false /* group */, first, closest))
{
std::cout << "Navigating up to " << closest->getID() << std::endl;
Widget* w = GUIEngine::getWidget( closest->getID() );
if (playerID == 0)
{
GUIEngine::getGUIEnv()->setFocus(closest);
}
else if (w != NULL)
{
w->setFocusForPlayer(playerID);
}
w->setFocusForPlayer(playerID);
// when focusing a list by going up, select the last item of the list
if (w != NULL && w->m_type == WTYPE_LIST)
@ -418,6 +383,10 @@ void EventHandler::navigateUp(const int playerID, Input::InputType type, const b
else
{
std::cout << "EventHandler::navigateUp : warp around, selecting the last widget\n";
//if (el == NULL) std::cout << " because el is null\n";
//else if (el->getTabGroup() == NULL) std::cout << " because el's tab group is null\n";
//else if (!el->getTabGroup()->getNextElement(el->getTabOrder(), true, false, first, closest))std::cout << " because el (" << core::stringc(el->getText()).c_str() << ", tab order " << el->getTabOrder() << ") has no known previous\n";
// select the last widget
Widget* w = NULL;
@ -432,13 +401,7 @@ void EventHandler::navigateUp(const int playerID, Input::InputType type, const b
w = screen->getLastWidget();
}
if (w != NULL)
{
if (playerID == 0)
GUIEngine::getGUIEnv()->setFocus( w->m_element );
else
w->setFocusForPlayer(playerID);
}
if (w != NULL) w->setFocusForPlayer(playerID);
}
}
@ -446,21 +409,12 @@ void EventHandler::navigateUp(const int playerID, Input::InputType type, const b
void EventHandler::navigateDown(const int playerID, Input::InputType type, const bool pressedDown)
{
std::cout << "Naviagte down!\n";
IGUIElement *el = NULL, *first = NULL, *closest = NULL;
// TODO : unify player 0 and players > 0 focus navigation to eliminate this kind of branching
if (playerID == 0)
{
el = GUIEngine::getGUIEnv()->getFocus();
}
else
{
Widget* widget = GUIEngine::g_focus_for_player[playerID];
if (widget != NULL) el = widget->m_element;
}
Widget* w = (el == NULL) ? NULL : GUIEngine::getWidget( el->getID() );
Widget* w = GUIEngine::getFocusForPlayer(playerID);
if (w != NULL) el = w->getIrrlichtElement();
//std::cout << "!!! Player " << playerID << " navigating down of " << w->m_element->getID() << std::endl;
// list widgets are a bit special, because up/down keys are also used
@ -473,6 +427,7 @@ void EventHandler::navigateDown(const int playerID, Input::InputType type, const
const bool stay_within_list = list->getSelected() < (int)list->getItemCount()-1;
/*
if (type == Input::IT_STICKMOTION)
{
// simulate a key press
@ -483,39 +438,51 @@ void EventHandler::navigateDown(const int playerID, Input::InputType type, const
wrapper.KeyInput = evt;
wrapper.EventType = EET_KEY_INPUT_EVENT;
GUIEngine::getDevice()->postEventFromUser(wrapper);
}*/
if (stay_within_list)
{
list->setSelected(list->getSelected()+1);
return;
}
else
{
list->setSelected(-1);
}
if (stay_within_list) return;
else list->setSelected(-1);
}
if (w != NULL && w->m_tab_down_root != -1)
{
//std::cout << " w->m_tab_down_root=" << w->m_tab_down_root << std::endl;
Widget* down = GUIEngine::getWidget( w->m_tab_down_root );
//std::cout << "navigateDown : setting root to " << w->m_tab_down_root << std::endl;
assert(down != NULL);
el = down->getIrrlichtElement();
if (el == NULL)
{
std::cerr << "WARNING : m_tab_down_root is set to an ID for which I can't find the widget\n";
return;
}
}
if (el == NULL)
{
std::cerr << "WARNING : m_tab_down_root is set to an ID for which I can't find the widget\n";
return;
}
if (el != NULL && el->getTabGroup() != NULL &&
el->getTabGroup()->getNextElement(el->getTabOrder(), false, false, first, closest))
{
//std::cout << "!!! Player " << playerID << " navigating down to " << closest->getID() << std::endl;
//std::cout << "Navigating down to " << closest->getID() << std::endl;
// FIXME : remove the special case for player 0
if (playerID == 0)
Widget* w = GUIEngine::getWidget( closest->getID() );
assert( w != NULL );
w->setFocusForPlayer(playerID);
// another list exception : when entering a list, select the first item
if (w->m_type == WTYPE_LIST)
{
GUIEngine::getGUIEnv()->setFocus(closest);
}
else
{
Widget* w = GUIEngine::getWidget( closest->getID() );
w->setFocusForPlayer(playerID);
IGUIListBox* list = (IGUIListBox*)(w->m_element);
assert(list != NULL);
list->setSelected(0);
}
}
else
@ -542,13 +509,7 @@ void EventHandler::navigateDown(const int playerID, Input::InputType type, const
w = screen->getFirstWidget();
}
if(w != NULL)
{
if (playerID == 0)
GUIEngine::getGUIEnv()->setFocus( w->m_element );
else
w->setFocusForPlayer(playerID);
}
if (w != NULL) w->setFocusForPlayer(playerID);
}
}

View File

@ -70,7 +70,7 @@ ModalDialog::~ModalDialog()
m_irrlicht_window->remove();
if(modalWindow == this) modalWindow = NULL;
if (modalWindow == this) modalWindow = NULL;
}
void ModalDialog::clearWindow()

View File

@ -264,9 +264,13 @@ void Screen::addWidgets()
addWidgetsRecursively( m_widgets );
//std::cout << "*****ScreenAddWidgets " << m_filename.c_str() << " : focusing the first widget*****\n";
// select the first widget
Widget* w = getFirstWidget();
if(w != NULL) GUIEngine::getGUIEnv()->setFocus( w->m_element );
//std::cout << "First widget is " << (w == NULL ? "null" : w->m_properties[PROP_ID].c_str()) << std::endl;
if (w != NULL) w->setFocusForPlayer( 0 ); // FIXME: don't hardcode player ID 0
else std::cerr << "Couldn't select first widget, NULL was returned\n";
}
// -----------------------------------------------------------------------------
void Screen::addWidgetsRecursively(ptr_vector<Widget>& widgets, Widget* parent)

View File

@ -600,7 +600,15 @@ void Skin::drawRibbonChild(const core::rect< s32 > &rect, Widget* widget, const
bool mark_selected = widget->isSelected();
bool always_show_selection = false;
const bool parent_focused = GUIEngine::getGUIEnv()->getFocus() == widget->m_event_handler->m_element;
const int playerID = 0; // FIXME : don't hardcode player 0 ?
IGUIElement* focusedElem = NULL;
if (GUIEngine::getFocusForPlayer(playerID) != NULL)
{
focusedElem = GUIEngine::getFocusForPlayer(playerID)->getIrrlichtElement();
}
const bool parent_focused = (focusedElem == widget->m_event_handler->m_element);
RibbonWidget* parentRibbon = (RibbonWidget*)widget->m_event_handler;
RibbonType type = parentRibbon->getRibbonType();
@ -658,7 +666,7 @@ void Skin::drawRibbonChild(const core::rect< s32 > &rect, Widget* widget, const
if(w->getRibbonType() == RIBBON_COMBO) always_show_selection = true;
}
const bool mark_focused = focused || (parent_focused && w != NULL && w->m_focus == widget) ||
const bool mark_focused = focused || (parent_focused && w != NULL && w->m_mouse_focus == widget) ||
(mark_selected && !always_show_selection && parent_focused);
@ -780,8 +788,13 @@ void Skin::drawSpinnerBody(const core::rect< s32 > &rect, Widget* widget, const
{
if (!focused)
{
IGUIElement* focused_widget = GUIEngine::getGUIEnv()->getFocus();
IGUIElement* focused_widget = NULL;
const int playerID = 0;
if (GUIEngine::getFocusForPlayer(playerID) != NULL)
{
focused_widget = GUIEngine::getFocusForPlayer(playerID)->getIrrlichtElement();
}
if (focused_widget != NULL && widget->m_children.size()>2)
{
if (widget->m_children[0].id == focused_widget->getID() ||
@ -957,13 +970,13 @@ void Skin::draw2DRectangle (IGUIElement *element, const video::SColor &color, co
{
if (GUIEngine::getStateManager()->getGameState() == GUIEngine::GAME) return; // ignore in game mode
//const bool focused = GUIEngine::getGUIEnv()->hasFocus(element);
const int id = element->getID();
Widget* widget = GUIEngine::getWidget(id);
if(widget == NULL) return;
if (widget == NULL) return;
const bool focused = GUIEngine::getGUIEnv()->hasFocus(element);
const int playerID = 0; // FIXME: don't hardcode player 0?
const bool focused = GUIEngine::isFocusedForPlayer(widget, playerID);
const WidgetType type = widget->m_type;
if(type == WTYPE_LIST)
@ -973,14 +986,17 @@ void Skin::draw2DRectangle (IGUIElement *element, const video::SColor &color, co
}
}
void Skin::process3DPane(IGUIElement *element, const core::rect< s32 > &rect, const bool pressed)
{
const bool focused = GUIEngine::getGUIEnv()->hasFocus(element);
{
const int id = element->getID();
Widget* widget = NULL;
if (id != -1) widget = GUIEngine::getWidget(id);
if (widget == NULL) return;
const int playerID = 0; // FIXME: don't hardcode player 0?
const bool focused = GUIEngine::isFocusedForPlayer(widget, playerID);
/*
std::cout << "Skin (3D Pane) : " << (widget == NULL ? "NULL!!" : widget->m_properties[PROP_ID].c_str()) << std::endl;
if (widget == NULL) std::cout << "Null widget: ID=" << id << " type=" << element->getTypeName() <<
@ -1091,7 +1107,15 @@ void Skin::draw3DSunkenPane (IGUIElement *element, video::SColor bgcolor, bool f
const WidgetType type = widget->m_type;
const bool focused = GUIEngine::getGUIEnv()->getFocus() == element;
const int playerID = 0; // FIXME : don't hardcode player 0 ?
IGUIElement* focusedElem = NULL;
if (GUIEngine::getFocusForPlayer(playerID) != NULL)
{
focusedElem = GUIEngine::getFocusForPlayer(playerID)->getIrrlichtElement();
}
const bool focused = (focusedElem == element);
if (type == WTYPE_LIST)
{

View File

@ -85,7 +85,6 @@ Widget::Widget(bool reserve_id)
for (int n=0; n<MAX_PLAYER_COUNT; n++)
{
m_player_focus[n] = false;
GUIEngine::g_focus_for_player[n] = false;
}
m_reserved_id = -1;
@ -99,7 +98,7 @@ void Widget::add()
m_reserved_id = getNewID();
}
}
// -----------------------------------------------------------------------------
/**
* \param playerID ID of the player you want to set/unset focus for, starting from 0
@ -109,23 +108,16 @@ void Widget::add()
void Widget::setFocusForPlayer(const int playerID)
{
// Unset focus flag on previous widget that had focus
if (GUIEngine::g_focus_for_player[playerID] != NULL)
if (GUIEngine::getFocusForPlayer(playerID) != NULL)
{
GUIEngine::g_focus_for_player[playerID]->m_player_focus[playerID] = false;
GUIEngine::getFocusForPlayer(playerID)->m_player_focus[playerID] = false;
}
m_player_focus[playerID] = true;
GUIEngine::g_focus_for_player[playerID] = this;
// Player 0 uses irrLicht focus - FIXME : unify focus handling to remove this branching
if (playerID == 0)
{
requestFocus();
}
else
{
this->focused(playerID);
}
GUIEngine::Private::g_focus_for_player[playerID] = this;
// Callback
this->focused(playerID);
}
void Widget::unsetFocusForPlayer(const int playerID)
@ -142,11 +134,6 @@ bool Widget::isFocusedForPlayer(const int playerID)
}
void Widget::requestFocus()
{
GUIEngine::getGUIEnv()->setFocus(m_element);
}
/**
* Receives as string the raw property value retrieved from XML file.
* Will try to make sense of it, as an absolute value or a percentage.

View File

@ -108,8 +108,9 @@ namespace GUIEngine
/**
* called when left/right keys pressed and focus is on widget.
* Returns 'true' if main event handler should be notified of a change.
* Override in children to be notified of left/right events.
* Returns 'EVENT_LET' if user's event handler should be notified of a change.
* Override in children to be notified of left/right events and/or make
* the event propagate to the user's event handler.
*/
virtual EventPropagation rightPressed(const int playerID) { return EVENT_BLOCK; }
virtual EventPropagation leftPressed(const int playerID) { return EVENT_BLOCK; }
@ -164,6 +165,8 @@ namespace GUIEngine
bool m_reserve_id;
friend void GUIEngine::focusNothingForPlayer(const int playerID);
public:
/**
* This is set to NULL by default; set to something else in a widget to mean
@ -256,6 +259,7 @@ namespace GUIEngine
*/
bool isFocusedForPlayer(const int playerID);
/** Internal method, do not call it. Call the functions in GUIEngine instead to unset focus. */
void unsetFocusForPlayer(const int playerID);
/**
@ -266,8 +270,8 @@ namespace GUIEngine
bool isSelected() const { return m_selected; }
void requestFocus();
bool isSameIrrlichtWidgetAs(const Widget* ref) const { return m_element == ref->m_element; }
/**
* These methods provide new unique IDs each time you call them.
* Since IDs are used to determine tabbing order, "non-tabbable"

View File

@ -298,33 +298,18 @@ RibbonWidget* DynamicRibbonWidget::getRowContaining(Widget* w) const
// -----------------------------------------------------------------------------
RibbonWidget* DynamicRibbonWidget::getSelectedRibbon(const int playerID) const
{
if (playerID == 0)
const int row_amount = m_rows.size();
for(int n=0; n<row_amount; n++)
{
const int row_amount = m_rows.size();
for(int n=0; n<row_amount; n++)
const RibbonWidget* row = &m_rows[n];
if (GUIEngine::isFocusedForPlayer(row, playerID))
{
const RibbonWidget* row = &m_rows[n];
if(row != NULL)
{
if( GUIEngine::getGUIEnv()->hasFocus(row->m_element) ||
m_element->isMyChild( GUIEngine::getGUIEnv()->getFocus() ) ) return (RibbonWidget*)row;
}
return (RibbonWidget*)row;
}
}
else
{
const int row_amount = m_rows.size();
for(int n=0; n<row_amount; n++)
{
const RibbonWidget* row = &m_rows[n];
if (row == GUIEngine::g_focus_for_player[playerID])
{
return (RibbonWidget*)row;
}
}
}
return NULL;
}
@ -354,9 +339,12 @@ EventPropagation DynamicRibbonWidget::rightPressed(const int playerID)
getSelectedRibbon(playerID)->getSelectionText(playerID), playerID);
}
}
std::cout << "rightpressed (dynamic ribbon)\n";
if (m_rows[0].m_ribbon_type == RIBBON_TOOLBAR) return EVENT_BLOCK;
std::cout << " rightpressed returning EVENT_LET\n";
return EVENT_LET;
}
// -----------------------------------------------------------------------------
@ -604,7 +592,7 @@ void DynamicRibbonWidget::updateItemDisplay()
} // next row
}
// -----------------------------------------------------------------------------
bool DynamicRibbonWidget::setSelection(int item_id, const int playerID)
bool DynamicRibbonWidget::setSelection(int item_id, const int playerID, const bool focusIt)
{
//printf("****DynamicRibbonWidget::setSelection()****\n");
@ -635,20 +623,20 @@ bool DynamicRibbonWidget::setSelection(int item_id, const int playerID)
//std::cout << "Player " << playerID << " has item " << item_id << " (" << name.c_str() << ") in row " << row << std::endl;
m_rows[row].setSelection(id, playerID);
m_rows[row].setFocusForPlayer(playerID);
if (focusIt) m_rows[row].setFocusForPlayer(playerID);
propagateSelection();
return true;
}
// -----------------------------------------------------------------------------
bool DynamicRibbonWidget::setSelection(const std::string item_codename, const int playerID)
bool DynamicRibbonWidget::setSelection(const std::string item_codename, const int playerID, const bool focusIt)
{
const int item_count = m_items.size();
for (int n=0; n<item_count; n++)
{
if (m_items[n].m_code_name == item_codename)
{
return setSelection(n, playerID);
return setSelection(n, playerID, focusIt);
}
}
return false;

View File

@ -179,11 +179,11 @@ namespace GUIEngine
/** Select an item from its numerical ID. Only for [1-row] combo ribbons.
ID ranges from {0} to {number of items added through 'addItem' - 1}
\return Whether setting the selection was successful (whether the item exists) */
bool setSelection(int item_id, const int playerID);
bool setSelection(int item_id, const int playerID, const bool focusIt);
/** Select an item from its codename.
\return Whether setting the selection was successful (whether the item exists) */
bool setSelection(const std::string item_codename, const int playerID);
bool setSelection(const std::string item_codename, const int playerID, const bool focusIt);
/**
* Called when irrLicht widgets cleared. Forget all references to them, they're no more valid.

View File

@ -37,7 +37,7 @@ RibbonWidget::RibbonWidget(const RibbonType type)
m_selection[0] = 0; // only player 0 has a selection by default
m_ribbon_type = type;
m_focus = NULL;
m_mouse_focus = NULL;
updateSelection();
m_type = WTYPE_RIBBON;
}
@ -235,10 +235,19 @@ EventPropagation RibbonWidget::rightPressed(const int playerID)
else m_selection[playerID] = 0;
}
updateSelection();
if (playerID == 0) m_focus = m_children.get(m_selection[playerID]);
if (m_ribbon_type != RIBBON_TOOLBAR) return EVENT_LET;
else return EVENT_BLOCK;
// FIXME: don't hardcode player ID 0
if (playerID == 0) m_mouse_focus = m_children.get(m_selection[playerID]);
if (m_ribbon_type != RIBBON_TOOLBAR)
{
//GUIEngine::transmitEvent( this, m_properties[PROP_ID], playerID );
return EVENT_LET;
}
else
{
return EVENT_BLOCK;
}
}
// -----------------------------------------------------------------------------
EventPropagation RibbonWidget::leftPressed(const int playerID)
@ -255,10 +264,18 @@ EventPropagation RibbonWidget::leftPressed(const int playerID)
}
updateSelection();
if (playerID == 0) m_focus = m_children.get(m_selection[playerID]);
// FIXME: don't hardcode player ID
if (playerID == 0) m_mouse_focus = m_children.get(m_selection[playerID]);
if (m_ribbon_type != RIBBON_TOOLBAR) return EVENT_LET;
else return EVENT_BLOCK;
if (m_ribbon_type != RIBBON_TOOLBAR)
{
//GUIEngine::transmitEvent( this, m_properties[PROP_ID], playerID );
return EVENT_LET;
}
else
{
return EVENT_BLOCK;
}
}
// -----------------------------------------------------------------------------
EventPropagation RibbonWidget::focused(const int playerID)
@ -267,14 +284,15 @@ EventPropagation RibbonWidget::focused(const int playerID)
if (m_children.size() < 1) return EVENT_LET; // empty ribbon
if (m_focus == NULL && m_selection[playerID] != -1)
// FIXME: don't hardcode player ID 0
if (m_mouse_focus == NULL && m_selection[playerID] != -1 && playerID == 0)
{
m_focus = m_children.get(m_selection[playerID]);
m_mouse_focus = m_children.get(m_selection[playerID]);
}
if (m_event_handler != NULL)
{
if (playerID == 0) GUIEngine::getGUIEnv()->setFocus(m_focus->m_element);
//m_focus->setFocusForPlayer( playerID );
// FIXME : unclean, children ribbons shouldn't need to know about their parent
((DynamicRibbonWidget*)m_event_handler)->onRowChange( this, playerID );
@ -287,7 +305,7 @@ EventPropagation RibbonWidget::mouseHovered(Widget* child)
{
const int subbuttons_amount = m_children.size();
m_focus = child;
m_mouse_focus = child;
for (int i=0; i<subbuttons_amount; i++)
{
@ -323,7 +341,7 @@ void RibbonWidget::updateSelection()
}
// FIXME: don't hardcode player 0
if (subbuttons_amount > 0 && m_ribbon_type == RIBBON_TOOLBAR) m_focus = m_children.get(m_selection[0]);
if (subbuttons_amount > 0 && m_ribbon_type == RIBBON_TOOLBAR) m_mouse_focus = m_children.get(m_selection[0]);
}
// -----------------------------------------------------------------------------
EventPropagation RibbonWidget::transmitEvent(Widget* w, std::string& originator, const int playerID)
@ -342,7 +360,7 @@ EventPropagation RibbonWidget::transmitEvent(Widget* w, std::string& originator,
updateSelection();
// bring focus back to enclosing ribbon widget
GUIEngine::getGUIEnv()->setFocus(m_element);
this->setFocusForPlayer( playerID );
return EVENT_LET;
}

View File

@ -65,7 +65,7 @@ namespace GUIEngine
/** Contains which element within the ribbon is currently focused (used by the skin to
show mouse hovers over items that are not selected) */
Widget* m_focus;
Widget* m_mouse_focus;
RibbonWidget(const RibbonType type=RIBBON_COMBO);
virtual ~RibbonWidget() {}

View File

@ -185,7 +185,7 @@ EventPropagation SpinnerWidget::rightPressed(const int playerID)
//std::cout << "Right pressed\n";
if (m_value+1 <= m_max) setValue(m_value+1);
GUIEngine::transmitEvent( this, m_properties[PROP_ID], playerID );
//GUIEngine::transmitEvent( this, m_properties[PROP_ID], playerID );
return EVENT_LET;
}
@ -195,7 +195,7 @@ EventPropagation SpinnerWidget::leftPressed(const int playerID)
//std::cout << "Left pressed\n";
if (m_value-1 >= m_min) setValue(m_value-1);
GUIEngine::transmitEvent( this, m_properties[PROP_ID], playerID );
//GUIEngine::transmitEvent( this, m_properties[PROP_ID], playerID );
return EVENT_LET;
}
@ -205,7 +205,7 @@ EventPropagation SpinnerWidget::transmitEvent(Widget* w, std::string& originator
if (originator == "left") leftPressed(playerID);
else if (originator == "right") rightPressed(playerID);
GUIEngine::getGUIEnv()->setFocus(m_element);
this->setFocusForPlayer( playerID );
return EVENT_LET;
}
// -----------------------------------------------------------------------------

View File

@ -60,7 +60,7 @@ EnterPlayerNameDialog::EnterPlayerNameDialog(const float w, const float h) :
textCtrl->setParent(m_irrlicht_window);
m_children.push_back(textCtrl);
textCtrl->add();
GUIEngine::getGUIEnv()->setFocus( textCtrl->getIrrlichtElement() );
textCtrl->setFocusForPlayer(0); // FIXME : don't hardcode player 0 ?
// TODO : add Ok button
@ -93,7 +93,8 @@ GUIEngine::EventPropagation EnterPlayerNameDialog::processEvent(std::string& eve
void EnterPlayerNameDialog::onEnterPressedInternal()
{
// ---- Cancel button pressed
if( GUIEngine::getGUIEnv()->hasFocus(cancelButton->getIrrlichtElement()) )
const int playerID = 0; // FIXME: don't ahrdcode player 0?
if (GUIEngine::isFocusedForPlayer(cancelButton, playerID))
{
std::string fakeEvent = "cancel";
processEvent(fakeEvent);

View File

@ -59,7 +59,9 @@ void PlayerInfoDialog::showRegularDialog()
textCtrl->setParent(m_irrlicht_window);
m_children.push_back(textCtrl);
textCtrl->add();
GUIEngine::getGUIEnv()->setFocus( textCtrl->getIrrlichtElement() );
const int playerID = 0; // FIXME: don't hardcode player ID
textCtrl->setFocusForPlayer( playerID );
}
{
@ -172,8 +174,9 @@ void PlayerInfoDialog::showConfirmDialog()
widget->setParent(m_irrlicht_window);
m_children.push_back(widget);
widget->add();
GUIEngine::getGUIEnv()->setFocus( widget->getIrrlichtElement() );
const int playerID = 0; // FIXME: don't hardcode player ID
widget->setFocusForPlayer( playerID );
}
}

View File

@ -66,7 +66,9 @@ RacePausedDialog::RacePausedDialog(const float percentWidth, const float percent
back_btn->setParent(m_irrlicht_window);
m_children.push_back(back_btn);
back_btn->add();
GUIEngine::getGUIEnv()->setFocus( back_btn->getIrrlichtElement() );
const int playerID = 0; // FIXME: don't hardcode player ID
back_btn->setFocusForPlayer( playerID );
// ---- Choice ribbon
m_choice_ribbon = new RibbonWidget(RIBBON_TOOLBAR);

View File

@ -82,7 +82,8 @@ TrackInfoDialog::TrackInfoDialog(const std::string& trackIdent, const irr::core:
okBtn->getIrrlichtElement()->setTabStop(true);
okBtn->getIrrlichtElement()->setTabGroup(false);
GUIEngine::getGUIEnv()->setFocus( okBtn->getIrrlichtElement() );
const int playerID = 0; // FIXME: don't hardcode
okBtn->setFocusForPlayer( playerID );
// ---- Track title
core::rect< s32 > area_top(0, 0, m_area.getWidth(), y1);

View File

@ -303,10 +303,9 @@ FocusDispatcher* g_dispatcher = NULL;
~PlayerKartWidget()
{
if (GUIEngine::g_focus_for_player[m_playerID] == this)
if (GUIEngine::getFocusForPlayer(m_playerID) == this)
{
unsetFocusForPlayer(m_playerID);
GUIEngine::g_focus_for_player[m_playerID] = NULL;
GUIEngine::focusNothingForPlayer(m_playerID);
}
if (playerIDLabel->getIrrlichtElement() != NULL)
@ -334,12 +333,14 @@ FocusDispatcher* g_dispatcher = NULL;
assert(false);
}
Widget* focus = GUIEngine::g_focus_for_player[m_playerID];
if (focus != NULL) focus->unsetFocusForPlayer(m_playerID);
GUIEngine::g_focus_for_player[m_playerID] = NULL;
// Remove current focus, but rembmer it
Widget* focus = GUIEngine::getFocusForPlayer(m_playerID);
GUIEngine::focusNothingForPlayer(m_playerID);
// Change the player ID
m_playerID = newPlayerID;
// restore previous focus, but with new player ID
if (focus != NULL) focus->setFocusForPlayer(m_playerID);
//I18N: In kart selection screen (Will read like 'Player 1 (foobartech gamepad)')
@ -626,7 +627,7 @@ public:
DynamicRibbonWidget* w = m_parent->getWidget<DynamicRibbonWidget>("karts");
assert(w != NULL);
w->setSelection(m_parent->m_kart_widgets[playerID].m_kartInternalName, playerID);
w->setSelection(m_parent->m_kart_widgets[playerID].m_kartInternalName, playerID, true);
return;
}
@ -746,8 +747,10 @@ bool KartSelectionScreen::playerJoin(InputDevice* device, bool firstPlayer)
// ---- Focus a kart for this player
const int playerID = amount-1;
w->setSelection(playerID, playerID);
if (!firstPlayer)
{
w->setSelection(playerID, playerID, true);
}
return true;
}
@ -790,11 +793,7 @@ bool KartSelectionScreen::playerQuit(ActivePlayer* player)
assert( m_kart_widgets.size() == StateManager::get()->activePlayerCount() );
// unset selection of this player
if (GUIEngine::g_focus_for_player[playerID] != NULL)
{
GUIEngine::g_focus_for_player[playerID]->unsetFocusForPlayer(playerID);
}
GUIEngine::g_focus_for_player[playerID] = NULL;
GUIEngine::focusNothingForPlayer(playerID);
// keep the removed kart a while, for the 'disappear' animation to take place
removedWidget = m_kart_widgets.remove(playerID);
@ -926,8 +925,7 @@ void KartSelectionScreen::init()
}
// Player 0 select first kart (Tux)
w->setSelection(0, 0);
w->m_rows[0].requestFocus();
w->setSelection(0, 0, true);
}
// -----------------------------------------------------------------------------
@ -1077,14 +1075,10 @@ void KartSelectionScreen::eventCallback(Widget* widget, const std::string& name,
const int num_players = m_kart_widgets.size();
for (int n=0; n<num_players; n++)
{
if (GUIEngine::g_focus_for_player[n] != NULL)
{
GUIEngine::g_focus_for_player[n]->unsetFocusForPlayer(n);
}
GUIEngine::g_focus_for_player[n] = NULL;
GUIEngine::focusNothingForPlayer(n);
const std::string& selection = m_kart_widgets[n].getKartInternalName();
if (!w->setSelection( selection, n ))
if (!w->setSelection( selection, n, true ))
{
std::cout << "Player " << n << " lost their selection when switching tabs!!!\n";
// For now, select a random kart in this case (TODO : maybe do something better? )
@ -1093,7 +1087,7 @@ void KartSelectionScreen::eventCallback(Widget* widget, const std::string& name,
if (count > 0)
{
const int randomID = random.get( count );
w->setSelection( randomID, n );
w->setSelection( randomID, n, true );
}
else
{
@ -1201,12 +1195,12 @@ EventPropagation FocusDispatcher::focused(const int playerID)
std::cout << "--> Redirecting focus for player " << playerID << " from FocusDispatcher " <<
" (ID " << m_element->getID() <<
") to spinner " << n << " (ID " << m_parent->m_kart_widgets[n].playerName->getIrrlichtElement()->getID() << ")" << std::endl;
int IDbefore = GUIEngine::getGUIEnv()->getFocus()->getID();
//int IDbefore = GUIEngine::getGUIEnv()->getFocus()->getID();
m_parent->m_kart_widgets[n].playerName->setFocusForPlayer(playerID);
int IDafter = GUIEngine::getGUIEnv()->getFocus()->getID();
std::cout << "--> ID before : " << IDbefore << "; ID after : " << IDafter << std::endl;
//int IDafter = GUIEngine::getGUIEnv()->getFocus()->getID();
//std::cout << "--> ID before : " << IDbefore << "; ID after : " << IDafter << std::endl;
return GUIEngine::EVENT_BLOCK;
}

View File

@ -111,7 +111,7 @@ void OptionsScreenAV::init()
res->updateItemDisplay();
// ---- select curernt resolution every time
// ---- select current resolution every time
const std::vector<VideoMode>& modes = irr_driver->getVideoModes();
const int amount = modes.size();
for(int n=0; n<amount; n++)
@ -127,7 +127,7 @@ void OptionsScreenAV::init()
//std::cout << "************* Detected right resolution!!! " << n << "\n";
// that's the current one
const int playerID = 0; // FIXME: don't hardcode player 0 ?
res->setSelection(n, playerID);
res->setSelection(n, playerID, false);
break;
}
} // end for

View File

@ -223,7 +223,8 @@ void OptionsScreenInput::gotSensedInput(Input* sensedInput)
// re-select the previous button
ButtonWidget* btn = this->getWidget<ButtonWidget>(binding_to_set_button.c_str());
if(btn != NULL) GUIEngine::getGUIEnv()->setFocus( btn->getIrrlichtElement() );
const int playerID = 0; // FIXME: don't hardcode player ID
if(btn != NULL) btn->setFocusForPlayer(playerID);
// save new binding to file
input_manager->getDeviceList()->serialize();