From d9707351ea54fbd6372ce2507063c544e264cfb2 Mon Sep 17 00:00:00 2001 From: auria Date: Thu, 27 Aug 2009 18:41:20 +0000 Subject: [PATCH] First steps towards letting two different players choose their own kart git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/irrlicht@3932 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- data/gui/skins/glass.stkskin | 12 +- .../gui/skins/glass/glass_square_focused2.png | Bin 0 -> 2628 bytes .../gui/skins/glass/glass_square_focused3.png | Bin 0 -> 2568 bytes .../gui/skins/glass/glass_square_focused4.png | Bin 0 -> 2632 bytes src/config/player.hpp | 2 + src/guiengine/event_handler.cpp | 31 ++-- src/guiengine/event_handler.hpp | 4 +- src/guiengine/skin.cpp | 20 ++- src/guiengine/widget.cpp | 23 +++ src/guiengine/widget.hpp | 21 ++- src/guiengine/widgets/check_box_widget.cpp | 2 +- src/guiengine/widgets/check_box_widget.hpp | 2 +- src/guiengine/widgets/ribbon_grid_widget.cpp | 137 +++++++++++------- src/guiengine/widgets/ribbon_grid_widget.hpp | 25 ++-- src/guiengine/widgets/ribbon_widget.cpp | 74 ++++++---- src/guiengine/widgets/ribbon_widget.hpp | 32 ++-- src/guiengine/widgets/spinner_widget.cpp | 10 +- src/guiengine/widgets/spinner_widget.hpp | 6 +- src/input/input_manager.cpp | 5 +- src/states_screens/kart_selection.cpp | 56 ++++--- src/states_screens/state_manager.cpp | 19 ++- src/states_screens/state_manager.hpp | 2 + 22 files changed, 312 insertions(+), 171 deletions(-) create mode 100644 data/gui/skins/glass/glass_square_focused2.png create mode 100644 data/gui/skins/glass/glass_square_focused3.png create mode 100644 data/gui/skins/glass/glass_square_focused4.png diff --git a/data/gui/skins/glass.stkskin b/data/gui/skins/glass.stkskin index 6659153ed..89ad212e7 100644 --- a/data/gui/skins/glass.stkskin +++ b/data/gui/skins/glass.stkskin @@ -89,8 +89,16 @@ when the border that intersect at this corner are enabled. - - + + + + diff --git a/data/gui/skins/glass/glass_square_focused2.png b/data/gui/skins/glass/glass_square_focused2.png new file mode 100644 index 0000000000000000000000000000000000000000..80505f7deaee3dd444ee30d8a4978699db82770a GIT binary patch literal 2628 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

t;dW(7cHATs3>3#4#4lf4;qhw zsv-plF&c7?;oQDCI=ZJ-^IPOiH#F9Mj%GWa@i{g@*Y$a(3G~H_&dgLe{W($(MLc^$jc?xBIu3@ zLzjQ=rmYh2P z@Ixw!N3eE8&aJ5^z69`F-rxURFE7v1@$pJyl&v!l)b+ImBCXN@G-qhe$T0#}S1`_j z_x1pwT?4?(TYr^zoRMRM>73E1qQBC1*Y(#^=kR`CSPN|$lCm_~G*0WEf&%ah4{Su75}0e-GmvOs{O`sBPoZ)_d7BD5yQs0)PPoRd^z#E@JvU z-bp0wnP&h-%96pnXFvMr8@;@Q#<&OOoi3jZ$@}}Nx^Ii0{`4dL&2QezuU=U&XIT3k z@9%%ERrN(aJv{>u4?q80aYN+f@#8)jk~YmUfBm(Z+3X=T&EEl-X$Y3Qw_u(Cm{_eU zXJ)f88DnL+6f$Oslupyh$y)&N{_lQwV~huY2QOaq`s&H!$EqQeG#;PPcwFhlg><=t z$@^UZLzd;z842CXsVW-nSLRIoDYa#D-_WZfxhKt6i2tj1IRNmij%XbUp7yvUF!#yITqG)Sw2=A1+ zn=CvUwNvaa8+BE1B!)+Au9@OPIDhe`(hwi!$>6?|UvwvHvz{Z{s+8hu9 zv}shEHaW1ys7MJ|ueEPy`;vI;B4Dde>DVK%<}3g=ANlTt=b)#(r)U|5UNS@DC-n;<~hqo&HwP{+L?%Zih zV8>8t2m%0Bb52@SSwm2A4qDeR2M0*ogvU)j`yExLmzU6{X^;14#2NwvP?p6aXp9je zsv$tD3N#**nayze>8Etl9bg|mB=VkQxg-q%>DzCS=ksiS@B;!68LL&PAzW#UqA@~4 zuv%4xee}rQbTD-G>>2T7Vx=q#07hdZh(O-F$<1e4tWCq(;(&~lE&-HQ%JNL>`V>HI zCX+i<6bJeA^a+4(X*`CR&C2ti|2!cj&GR{QJ2&)Pea|IyB&DoY?awnC1z=hSiu6R2A0wVvKj*lng+y{v9 z0Xg@N8sifH6@WzJvGQ~Zo=$sGp?%tm#Wg$J)!gkKoSbXt0x2mu2OA^)FN9%%4Qou^ zQ$Jt<(Dw0L`H05j&Aq#^*#_NdRWSgAlo-G;pP%oWyLaE?{e6>;kKf92`Eo7tJgWW& z16MZB=ZTxz|ex>=oS&h03y;}g0$ zU?2M0_u|{5v8F|0)Bwr=IU;b*AY%wA0o~|J>$)AJi4YYY+VC5Dg)c_g5N18DG5k)Pb`JawUYO(#vK zJF-};Gz7tV4b54RlE~GSbVE|n5Jam=WVy^5f@odK>gp;lL~^Ans`~#;yz15~t${kL qmb=Vv2EgSSxEcWIle04gfd2)@cN=x+Vu5M^0000getWidget(id); if(w == NULL) break; - return onWidgetActivated(w); + // FIXME: don't hardcode player 0 + return onWidgetActivated(w, 0); } case EGET_ELEMENT_HOVERED: { @@ -139,9 +140,9 @@ bool EventHandler::onGUIEvent(const SEvent& event) return false; } -bool EventHandler::onWidgetActivated(GUIEngine::Widget* w) +bool EventHandler::onWidgetActivated(GUIEngine::Widget* w, const int playerID) { - if(ModalDialog::isADialogActive() && w->m_event_handler == NULL) + if (ModalDialog::isADialogActive() && w->m_event_handler == NULL) { ModalDialog::getCurrent()->processEvent(w->m_properties[PROP_ID]); return false; @@ -150,20 +151,20 @@ bool EventHandler::onWidgetActivated(GUIEngine::Widget* w) std::cout << "**** widget activated : " << w->m_properties[PROP_ID].c_str() << " ****" << std::endl; Widget* parent = w->m_event_handler; - if(w->m_event_handler != NULL) + if (w->m_event_handler != NULL) { /* Find all parents. Stop looping if a widget event handler's is itself, to not fall in an infinite loop (this can happen e.g. in checkboxes, where they need to be notified of clicks onto themselves so they can toggle their state. ) */ - while(parent->m_event_handler != NULL && parent->m_event_handler != parent) + while (parent->m_event_handler != NULL && parent->m_event_handler != parent) { - parent->transmitEvent(w, w->m_properties[PROP_ID]); + parent->transmitEvent(w, w->m_properties[PROP_ID], playerID); parent = parent->m_event_handler; } /* notify the found event event handler, and also notify the main callback if the parent event handler says so */ - if(parent->transmitEvent(w, w->m_properties[PROP_ID])) + if (parent->transmitEvent(w, w->m_properties[PROP_ID], playerID)) { transmitEvent(parent, parent->m_properties[PROP_ID]); } @@ -176,13 +177,13 @@ bool EventHandler::onWidgetActivated(GUIEngine::Widget* w) /** * Called by the input module */ -void EventHandler::processAction(const int action, const unsigned int value, Input::InputType type) +void EventHandler::processAction(const int action, const unsigned int value, Input::InputType type, const int playerID) { const bool pressedDown = value > Input::MAX_VALUE*2/3; - if(!pressedDown && type == Input::IT_STICKMOTION) return; + if (!pressedDown && type == Input::IT_STICKMOTION) return; - switch(action) + switch (action) { case PA_LEFT: { @@ -200,12 +201,12 @@ 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(); + widget_to_call->leftPressed(playerID); widget_to_call = widget_to_call->m_event_handler; } - if (widget_to_call->leftPressed()) + if (widget_to_call->leftPressed(playerID)) transmitEvent(w, w->m_properties[PROP_ID]); } break; @@ -224,11 +225,11 @@ 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(); + widget_to_call->rightPressed(playerID); widget_to_call = widget_to_call->m_event_handler; } - if(widget_to_call->rightPressed()) + if(widget_to_call->rightPressed(playerID)) transmitEvent(widget_to_call, w->m_properties[PROP_ID]); } @@ -357,7 +358,7 @@ void EventHandler::processAction(const int action, const unsigned int value, Inp IGUIElement* element = GUIEngine::getGUIEnv()->getFocus(); Widget* w = GUIEngine::getCurrentScreen()->getWidget( element->getID() ); if(w == NULL) break; - onWidgetActivated( w ); + onWidgetActivated( w, playerID ); } /* diff --git a/src/guiengine/event_handler.hpp b/src/guiengine/event_handler.hpp index 9e1f08501..7076f020f 100644 --- a/src/guiengine/event_handler.hpp +++ b/src/guiengine/event_handler.hpp @@ -45,7 +45,7 @@ namespace GUIEngine class EventHandler : public IEventReceiver { bool onGUIEvent(const SEvent& event); - bool onWidgetActivated(Widget* w); + bool onWidgetActivated(Widget* w, const int playerID); public: EventHandler(); ~EventHandler(); @@ -61,7 +61,7 @@ public: * and this action needs to be applied to the GUI (e.g. fire pressed, left * pressed, etc.) this method is called back by the input module. */ - void processAction(const int action, const unsigned int value, Input::InputType type); + void processAction(const int action, const unsigned int value, Input::InputType type, const int playerID); // singleton static EventHandler* get(); diff --git a/src/guiengine/skin.cpp b/src/guiengine/skin.cpp index 39c6b88ab..bdcc07a36 100644 --- a/src/guiengine/skin.cpp +++ b/src/guiengine/skin.cpp @@ -622,7 +622,7 @@ void Skin::drawRibbonChild(const core::rect< s32 > &rect, Widget* widget, const /* in combo ribbons, always show selection */ RibbonWidget* w = NULL; - if(widget->m_event_handler != NULL && widget->m_event_handler->m_type == WTYPE_RIBBON) + if (widget->m_event_handler != NULL && widget->m_event_handler->m_type == WTYPE_RIBBON) { w = dynamic_cast(widget->m_event_handler); if(w->getRibbonType() == RIBBON_COMBO) always_show_selection = true; @@ -632,7 +632,7 @@ void Skin::drawRibbonChild(const core::rect< s32 > &rect, Widget* widget, const (mark_selected && !always_show_selection && parent_focused); - if(always_show_selection && mark_selected) + if (always_show_selection && mark_selected) { core::rect< s32 > rect2 = rect; rect2.UpperLeftCorner.X -= rect.getWidth() / 5; @@ -651,7 +651,7 @@ void Skin::drawRibbonChild(const core::rect< s32 > &rect, Widget* widget, const 0 /* no clipping */, 0, true /* alpha */); } - if(mark_focused) + if (mark_focused) { if (use_glow) { @@ -689,7 +689,7 @@ void Skin::drawRibbonChild(const core::rect< s32 > &rect, Widget* widget, const { const bool show_focus = focused || parent_focused; - if(!always_show_selection && !show_focus) return; + if (!always_show_selection && !show_focus) return; //const int texture_w = m_tex_squarefocus->getSize().Width; //const int texture_h = m_tex_squarefocus->getSize().Height; @@ -699,8 +699,18 @@ void Skin::drawRibbonChild(const core::rect< s32 > &rect, Widget* widget, const } } // end if mark_focused + // ---- Draw selection for other players than player 1 + if (parent_focused) + { + if (widget->isFocusedForPlayer(1)) + drawBoxFromStretchableTexture(w, rect, SkinConfig::m_render_params["squareFocusHalo2::neutral"]); + if (widget->isFocusedForPlayer(2)) + drawBoxFromStretchableTexture(w, rect, SkinConfig::m_render_params["squareFocusHalo3::neutral"]); + if (widget->isFocusedForPlayer(3)) + drawBoxFromStretchableTexture(w, rect, SkinConfig::m_render_params["squareFocusHalo4::neutral"]); + } - } + } // end if icon ribbons } diff --git a/src/guiengine/widget.cpp b/src/guiengine/widget.cpp index b0412cdcc..5e6d05233 100644 --- a/src/guiengine/widget.cpp +++ b/src/guiengine/widget.cpp @@ -79,6 +79,11 @@ Widget::Widget(bool reserve_id) m_show_bounding_box = false; m_parent = NULL; + for (int n=0; n<32; n++) + { + m_special_focus[n] = false; + } + if (reserve_id) { m_reserved_id = getNewID(); @@ -89,6 +94,24 @@ Widget::Widget(bool reserve_id) } } // ----------------------------------------------------------------------------- +/** + * \param playerID ID of the player you want to set/unset focus for, starting from 0 + * Since the code tracks focus from main player, this will most likely be used only + * for additionnal players + */ +void Widget::setFocusForPlayer(const int playerID, const bool focused) +{ + m_special_focus[playerID] = focused; +} +/** + * \param playerID ID of the player you want to set/unset focus for, starting from 0 + */ +bool Widget::isFocusedForPlayer(const int playerID) +{ + return m_special_focus[playerID]; +} + + /** * 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. diff --git a/src/guiengine/widget.hpp b/src/guiengine/widget.hpp index 4d3229e79..a61ef7104 100644 --- a/src/guiengine/widget.hpp +++ b/src/guiengine/widget.hpp @@ -119,8 +119,8 @@ namespace GUIEngine * Returns 'true' if main event handler should be notified of a change. * Override in children to be notified of left/right events. */ - virtual bool rightPressed() { return false; } - virtual bool leftPressed() { return false; } + virtual bool rightPressed(const int playerID) { return false; } + virtual bool leftPressed(const int playerID) { return false; } /** used when you set eventSupervisors - see m_event_handler explainations below called when one of a widget's children is hovered. @@ -164,6 +164,11 @@ namespace GUIEngine * (not the same as the string identificator specified in the XML file) */ int id; + + /** Usually, only one widget at a time can be focused. There is however a special case where all + players can move through the screen. This variable will then be used as a bitmask to contain + which players beyong player 1 have this widget focused. */ + bool m_special_focus[32]; // FIXME : the 32 there is arbitrary, settle for a max number of players public: /** @@ -236,6 +241,16 @@ namespace GUIEngine static void resetIDCounters(); + /** + * \param playerID ID of the player you want to set/unset focus for, starting from 0 + */ + void setFocusForPlayer(const int playerID, const bool focused); + + /** + * \param playerID ID of the player you want to set/unset focus for, starting from 0 + */ + bool isFocusedForPlayer(const int playerID); + /** * Call to resize/move the widget. Not all widgets can resize gracefully. */ @@ -255,7 +270,7 @@ namespace GUIEngine this call. Must return whether main (GUI engine user) event callback should be notified or not. Note that in the case of a hierarchy of widgets (with m_event_handler), only the topmost widget of the chain decides whether the main handler is notified; return value is not read for others. */ - virtual bool transmitEvent(Widget* w, std::string& originator) { return true; } + virtual bool transmitEvent(Widget* w, std::string& originator, const int playerID) { return true; } /** * Create and add the irrLicht widget(s) associated with this object. diff --git a/src/guiengine/widgets/check_box_widget.cpp b/src/guiengine/widgets/check_box_widget.cpp index 163c4dc97..153bbb23e 100644 --- a/src/guiengine/widgets/check_box_widget.cpp +++ b/src/guiengine/widgets/check_box_widget.cpp @@ -38,7 +38,7 @@ void CheckBoxWidget::add() m_element->setTabGroup(false); } // ----------------------------------------------------------------------------- -bool CheckBoxWidget::transmitEvent(Widget* w, std::string& originator) +bool CheckBoxWidget::transmitEvent(Widget* w, std::string& originator, const int playerID) { /* toggle */ m_state = !m_state; diff --git a/src/guiengine/widgets/check_box_widget.hpp b/src/guiengine/widgets/check_box_widget.hpp index fb7a02f1c..742f29375 100644 --- a/src/guiengine/widgets/check_box_widget.hpp +++ b/src/guiengine/widgets/check_box_widget.hpp @@ -34,7 +34,7 @@ namespace GUIEngine class CheckBoxWidget : public Widget { bool m_state; - bool transmitEvent(Widget* w, std::string& originator); + bool transmitEvent(Widget* w, std::string& originator, const int playerID); public: CheckBoxWidget(); diff --git a/src/guiengine/widgets/ribbon_grid_widget.cpp b/src/guiengine/widgets/ribbon_grid_widget.cpp index 1ad3b5503..8f92422f6 100644 --- a/src/guiengine/widgets/ribbon_grid_widget.cpp +++ b/src/guiengine/widgets/ribbon_grid_widget.cpp @@ -38,7 +38,12 @@ RibbonGridWidget::RibbonGridWidget(const bool combo, const int max_rows) m_left_widget = NULL; m_right_widget = NULL; m_type = WTYPE_RIBBON_GRID; - m_selected_item = 0; + + for (int n=0; n<32; n++) + { + m_selected_item[n] = -1; + } + m_selected_item[0] = 0; // only player 0 has a selection by default } // ----------------------------------------------------------------------------- void RibbonGridWidget::add() @@ -231,11 +236,11 @@ void RibbonGridWidget::addItem( std::string user_name, std::string code_name, st #pragma mark Getters #endif -const std::string& RibbonGridWidget::getSelectionIDString() +const std::string& RibbonGridWidget::getSelectionIDString(const int playerID) { RibbonWidget* row = (RibbonWidget*)(m_rows.size() == 1 ? m_rows.get(0) : getSelectedRibbon()); - if(row != NULL) return row->getSelectionIDString(); + if(row != NULL) return row->getSelectionIDString(playerID); static const std::string nothing = ""; return nothing; @@ -292,7 +297,28 @@ void RibbonGridWidget::registerHoverListener(RibbonGridHoverListener* listener) m_hover_listeners.push_back(listener); } // ----------------------------------------------------------------------------- -bool RibbonGridWidget::rightPressed() +bool RibbonGridWidget::rightPressed(const int playerID) +{ + RibbonWidget* w = getSelectedRibbon(); + if (w != NULL) + { + updateLabel(); + + propagateSelection(); + + const int listenerAmount = m_hover_listeners.size(); + for (int n=0; ngetSelectionIDString(playerID), playerID); + } + } + + if (m_rows[0].m_ribbon_type == RIBBON_TOOLBAR) return false; + + return true; +} +// ----------------------------------------------------------------------------- +bool RibbonGridWidget::leftPressed(const int playerID) { RibbonWidget* w = getSelectedRibbon(); if (w != NULL) @@ -303,27 +329,7 @@ bool RibbonGridWidget::rightPressed() const int listenerAmount = m_hover_listeners.size(); for (int n=0; ngetSelectionIDString()); - } - } - - if (m_rows[0].m_ribbon_type == RIBBON_TOOLBAR) return false; - - return true; -} -// ----------------------------------------------------------------------------- -bool RibbonGridWidget::leftPressed() -{ - RibbonWidget* w = getSelectedRibbon(); - if (w != NULL) - { - updateLabel(); - propagateSelection(); - - const int listenerAmount = m_hover_listeners.size(); - for (int n=0; ngetSelectionIDString()); + m_hover_listeners[n].onSelectionChanged(this, w->getSelectionIDString(playerID), playerID); } } @@ -333,7 +339,7 @@ bool RibbonGridWidget::leftPressed() return true; } // ----------------------------------------------------------------------------- -bool RibbonGridWidget::transmitEvent(Widget* w, std::string& originator) +bool RibbonGridWidget::transmitEvent(Widget* w, std::string& originator, const int playerID) { if (originator=="left") { @@ -352,8 +358,8 @@ bool RibbonGridWidget::transmitEvent(Widget* w, std::string& originator) RibbonWidget* selected_ribbon = (RibbonWidget*)getSelectedRibbon(); if (selected_ribbon != NULL) { - m_selected_item = selected_ribbon->m_selection + m_scroll_offset; - if (m_selected_item >= (int)m_items.size()) m_selected_item -= m_items.size(); + m_selected_item[playerID] = selected_ribbon->m_selection[playerID] + m_scroll_offset; + if (m_selected_item[playerID] >= (int)m_items.size()) m_selected_item[playerID] -= m_items.size(); } } @@ -370,7 +376,9 @@ bool RibbonGridWidget::mouseHovered(Widget* child) const int listenerAmount = m_hover_listeners.size(); for (int n=0; ngetSelectionIDString()); + // FIXME: don't hardcode player 0 + const int playerID = 0; + m_hover_listeners[n].onSelectionChanged(this, getSelectedRibbon()->getSelectionIDString(playerID), playerID); } } @@ -385,7 +393,9 @@ void RibbonGridWidget::focused() const int listenerAmount = m_hover_listeners.size(); for(int n=0; ngetSelectionIDString()); + // FIXME: don't hardcode player 0 + const int playerID = 0; + m_hover_listeners[n].onSelectionChanged(this, getSelectedRibbon()->getSelectionIDString(playerID), playerID); } } // ----------------------------------------------------------------------------- @@ -396,7 +406,9 @@ void RibbonGridWidget::onRowChange(RibbonWidget* row) const int listenerAmount = m_hover_listeners.size(); for (int n=0; ngetSelectionIDString()); + // FIXME: don't hardcode player 0 + const int playerID = 0; + m_hover_listeners[n].onSelectionChanged(this, row->getSelectionIDString(playerID), playerID); } } @@ -422,10 +434,13 @@ void RibbonGridWidget::scroll(const int x_delta) // update selection markers in child ribbon if (m_combo) { - RibbonWidget* ribbon = m_rows.get(0); // there is a single row when we can select items - int id = m_selected_item - m_scroll_offset; - if (id < 0) id += m_items.size(); - ribbon->setSelection(id); + for (int n=0; n<32; n++) + { + RibbonWidget* ribbon = m_rows.get(0); // there is a single row when we can select items + int id = m_selected_item[n] - m_scroll_offset; + if (id < 0) id += m_items.size(); + ribbon->setSelection(id); + } } } // ----------------------------------------------------------------------------- @@ -434,28 +449,33 @@ void RibbonGridWidget::scroll(const int x_delta) (i.e. you remain in the same column when pressing up/down), this method is used to ensure that all children ribbons always select the same column */ void RibbonGridWidget::propagateSelection() -{ +{ // find selection in current ribbon RibbonWidget* selected_ribbon = (RibbonWidget*)getSelectedRibbon(); if (selected_ribbon == NULL) return; - const int relative_selection = selected_ribbon->m_selection; - if (m_combo) + for (int p=0; p<32; p++) { - m_selected_item = relative_selection + m_scroll_offset; - if (m_selected_item >= (int)m_items.size()) m_selected_item -= m_items.size(); - } - - // set same selection in all ribbons - const int row_amount = m_rows.size(); - for (int n=0; nm_selection[p]; + + if (m_combo) { - ribbon->m_selection = relative_selection; - ribbon->updateSelection(); + m_selected_item[p] = relative_selection + m_scroll_offset; + if (m_selected_item[p] >= (int)m_items.size()) m_selected_item[p] -= m_items.size(); } + + // set same selection in all ribbons + const int row_amount = m_rows.size(); + for (int n=0; nm_selection[p] = relative_selection; + ribbon->updateSelection(); + } + } + } } // ----------------------------------------------------------------------------- @@ -546,21 +566,26 @@ void RibbonGridWidget::setSelection(int item_id) return; } - m_selected_item = item_id; - if (m_selected_item >= (int)m_items.size()) m_selected_item -= m_items.size(); + // FIXME: don't hardcode player 0 ? + const int PLAYER_ID = 0; + + m_selected_item[PLAYER_ID] = item_id; + if (m_selected_item[PLAYER_ID] >= (int)m_items.size()) m_selected_item[PLAYER_ID] -= m_items.size(); // scroll so selection is visible - m_scroll_offset = m_selected_item; // works because in this case there is a single row + m_scroll_offset = m_selected_item[PLAYER_ID]; // works because in this case there is a single row updateItemDisplay(); // set selection RibbonWidget* ribbon = m_rows.get(0); // there is a single row when we can select items - int id = m_selected_item - m_scroll_offset; + int id = m_selected_item[PLAYER_ID] - m_scroll_offset; if (id < 0) id += m_items.size(); ribbon->setSelection(id); } + // ----------------------------------------------------------------------------- -void RibbonGridWidget::setSelection(const std::string& code_name) +void RibbonGridWidget::setSelection(int item_id, const int playerID) { - assert(false); + m_selected_item[playerID] = item_id; + propagateSelection(); } diff --git a/src/guiengine/widgets/ribbon_grid_widget.hpp b/src/guiengine/widgets/ribbon_grid_widget.hpp index 4c35126a6..2ce3d88b3 100644 --- a/src/guiengine/widgets/ribbon_grid_widget.hpp +++ b/src/guiengine/widgets/ribbon_grid_widget.hpp @@ -39,7 +39,7 @@ namespace GUIEngine { public: virtual ~RibbonGridHoverListener() {} - virtual void onSelectionChanged(RibbonGridWidget* theWidget, const std::string& selectionID) = 0; + virtual void onSelectionChanged(RibbonGridWidget* theWidget, const std::string& selectionID, const int playerID) = 0; }; struct ItemDescription @@ -127,7 +127,7 @@ namespace GUIEngine /** Callback called widget is focused */ void focused(); - bool transmitEvent(Widget* w, std::string& originator); + bool transmitEvent(Widget* w, std::string& originator, const int playerID); /** Removes all previously added contents icons, and re-adds them (calculating the new amount) */ void setSubElements(); @@ -135,8 +135,8 @@ namespace GUIEngine /** Call this to scroll within a scrollable ribbon */ void scroll(const int x_delta); - /** Used for combo ribbons, to contain the ID of the currently selected item */ - int m_selected_item; + /** Used for combo ribbons, to contain the ID of the currently selected item for each player */ + int m_selected_item[32]; // FIXME: 32 is arbitrary, settle for a max number of players /** Callbacks */ void onRowChange(RibbonWidget* row); @@ -146,25 +146,25 @@ namespace GUIEngine public: RibbonGridWidget(const bool combo=false, const int max_rows=4); + /** Dynamically add an item to the ribbon's list of items (will not be visible until you + call 'updateItemDisplay' or 'add') */ + void addItem( std::string user_name, std::string code_name, std::string image_file ); + /** Register a listener to be notified of selection changes within the ribbon */ void registerHoverListener(RibbonGridHoverListener* listener); /** Called when right key is pressed */ - bool rightPressed(); + bool rightPressed(const int playerID); /** Called when left key is pressed */ - bool leftPressed(); - - /** Dynamically add an item to the ribbon's list of items (will not be visible until you - call 'updateItemDisplay' or 'add') */ - void addItem( std::string user_name, std::string code_name, std::string image_file ); + bool leftPressed(const int playerID); /** Updates icons/labels given current items and scrolling offset, taking care of resizing the dynamic ribbon if the number of items changed */ void updateItemDisplay(); /** Get the internal name (ID) of the selected item */ - const std::string& getSelectionIDString(); + const std::string& getSelectionIDString(const int playerID=0); /** Get the user-visible text of the selected item */ const std::string& getSelectionText(); @@ -173,8 +173,7 @@ namespace GUIEngine ID ranges from {0} to {number of items added through 'addItem' - 1} */ void setSelection(int item_id); - /** Select an item from its internal name */ - void setSelection(const std::string& code_name); + void setSelection(int item_id, const int playerID); }; } diff --git a/src/guiengine/widgets/ribbon_widget.cpp b/src/guiengine/widgets/ribbon_widget.cpp index a1a94ea29..80cb61eec 100644 --- a/src/guiengine/widgets/ribbon_widget.cpp +++ b/src/guiengine/widgets/ribbon_widget.cpp @@ -29,7 +29,12 @@ using namespace GUIEngine; // ----------------------------------------------------------------------------- RibbonWidget::RibbonWidget(const RibbonType type) { - m_selection = 0; + for (int n=0; n<32; n++) + { + m_selection[n] = -1; + } + m_selection[0] = 0; // only player 0 has a selection by default + m_ribbon_type = type; m_focus = NULL; updateSelection(); @@ -196,15 +201,15 @@ void RibbonWidget::add() } // ----------------------------------------------------------------------------- -void RibbonWidget::select(std::string item) +void RibbonWidget::select(std::string item, const int playerID) { const int subbuttons_amount = m_children.size(); - for(int i=0; i= m_children.size()) + m_selection[playerID]++; + if (m_selection[playerID] >= m_children.size()) { - if(m_event_handler != NULL) + if (m_event_handler != NULL) { ((RibbonGridWidget*)m_event_handler)->scroll(1); // FIXME? - find cleaner way to propagate event to parent - m_selection = m_children.size()-1; + m_selection[playerID] = m_children.size()-1; } - else m_selection = 0; + else m_selection[playerID] = 0; } updateSelection(); - m_focus = m_children.get(m_selection); + m_focus = m_children.get(m_selection[playerID]); return m_ribbon_type != RIBBON_TOOLBAR; } // ----------------------------------------------------------------------------- -bool RibbonWidget::leftPressed() +bool RibbonWidget::leftPressed(const int playerID) { - m_selection--; - if(m_selection < 0) + m_selection[playerID]--; + if (m_selection[playerID] < 0) { - if(m_event_handler != NULL) + if (m_event_handler != NULL) { ((RibbonGridWidget*)m_event_handler)->scroll(-1); // FIXME? - find cleaner way to propagate event to parent - m_selection = 0; + m_selection[playerID] = 0; } - else m_selection = m_children.size()-1; + else m_selection[playerID] = m_children.size()-1; } updateSelection(); - m_focus = m_children.get(m_selection); + m_focus = m_children.get(m_selection[playerID]); return m_ribbon_type != RIBBON_TOOLBAR; } @@ -252,11 +257,12 @@ void RibbonWidget::focused() { Widget::focused(); - if (m_focus == NULL) m_focus = m_children.get(m_selection); + if (m_focus == NULL) m_focus = m_children.get(m_selection[0]); // FIXME : don't hardcode player 0 here if (m_event_handler != NULL) { GUIEngine::getGUIEnv()->setFocus(m_focus->m_element); + // FIXME : unclean, children ribbons shouldn't need to know about their parent ((RibbonGridWidget*)m_event_handler)->onRowChange( this ); } @@ -272,8 +278,9 @@ bool RibbonWidget::mouseHovered(Widget* child) { if (m_children.get(i) == child) { - if (m_selection == i) return false; // was already selected, don't send another event - if (m_ribbon_type == RIBBON_TOOLBAR) m_selection = i; // don't change selection on hover for others + // FIXME: don't hardcode player 0 there? + if (m_selection[0] == i) return false; // 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; } } @@ -287,13 +294,24 @@ void RibbonWidget::updateSelection() for (int i=0; i 0 && m_ribbon_type == RIBBON_TOOLBAR) m_focus = m_children.get(m_selection); + // FIXME: don't hardcode player 0 + if (subbuttons_amount > 0 && m_ribbon_type == RIBBON_TOOLBAR) m_focus = m_children.get(m_selection[0]); } // ----------------------------------------------------------------------------- -bool RibbonWidget::transmitEvent(Widget* w, std::string& originator) +bool RibbonWidget::transmitEvent(Widget* w, std::string& originator, const int playerID) { const int subbuttons_amount = m_children.size(); @@ -301,12 +319,16 @@ bool RibbonWidget::transmitEvent(Widget* w, std::string& originator) { if (m_children[i].m_properties[PROP_ID] == originator) { - m_selection = i; + m_selection[playerID] = i; break; } } + updateSelection(); + + // bring focus back to enclosing ribbon widget GUIEngine::getGUIEnv()->setFocus(m_element); + return true; } // ----------------------------------------------------------------------------- diff --git a/src/guiengine/widgets/ribbon_widget.hpp b/src/guiengine/widgets/ribbon_widget.hpp index 7c686b54e..ffe05daf8 100644 --- a/src/guiengine/widgets/ribbon_widget.hpp +++ b/src/guiengine/widgets/ribbon_widget.hpp @@ -45,7 +45,7 @@ namespace GUIEngine friend class RibbonGridWidget; friend class EventHandler; - int m_selection; + int m_selection[32]; // FIXME: 32 is a bit arbitrary, settle for a max number of players /** The type of this ribbon (toolbar, combo, tabs) */ RibbonType m_ribbon_type; @@ -58,10 +58,10 @@ namespace GUIEngine void updateSelection(); /** Callbacks */ - bool rightPressed(); - bool leftPressed(); + bool rightPressed(const int playerID=0); + bool leftPressed(const int playerID=0); bool mouseHovered(Widget* child); - bool transmitEvent(Widget* w, std::string& originator); + bool transmitEvent(Widget* w, std::string& originator, const int playerID=0); void focused(); ptr_vector m_labels; @@ -74,23 +74,23 @@ namespace GUIEngine RibbonWidget(const RibbonType type=RIBBON_COMBO); virtual ~RibbonWidget() {} - /** Returns the numerical ID of the selected item within the ribbon */ - int getSelection() const { return m_selection; } - - /** Returns the string ID (internal name) of the selection */ - const std::string& getSelectionIDString() { return m_children[m_selection].m_properties[PROP_ID]; } - - /** Returns the user-visible text of the selection */ - const std::string& getSelectionText() { return m_children[m_selection].m_properties[PROP_TEXT]; } - - /** Returns the type of this ribbon (see guiengine/engine.hpp for detaield descriptions) */ + /** Returns the type of this ribbon (see guiengine/engine.hpp for detailed descriptions) */ RibbonType getRibbonType() const { return m_ribbon_type; } + /** Returns the numerical ID of the selected item within the ribbon */ + int getSelection(const int playerID) const { return m_selection[playerID]; } + + /** Returns the string ID (internal name) of the selection */ + const std::string& getSelectionIDString(const int playerID=0) { return m_children[m_selection[playerID]].m_properties[PROP_ID]; } + + /** Returns the user-visible text of the selection */ + const std::string& getSelectionText(const int playerID=0) { return m_children[m_selection[playerID]].m_properties[PROP_TEXT]; } + /** Sets the ID of the selected item within the ribbon */ - void setSelection(const int i) { m_selection = i; updateSelection(); } + void setSelection(const int i, const int playerID=0) { m_selection[playerID] = i; updateSelection(); } /** Select an item in the ribbon by its internal name */ - void select(std::string item); + void select(std::string item, const int playerID=0); /** When each item has a label, this method can be used to rename an item (especially used in scrolling ribbons, when scrolling occurs by renaming diff --git a/src/guiengine/widgets/spinner_widget.cpp b/src/guiengine/widgets/spinner_widget.cpp index 2f7dc0d13..8494c153e 100644 --- a/src/guiengine/widgets/spinner_widget.cpp +++ b/src/guiengine/widgets/spinner_widget.cpp @@ -177,22 +177,22 @@ void SpinnerWidget::move(const int x, const int y, const int w, const int h) } // ----------------------------------------------------------------------------- -bool SpinnerWidget::rightPressed() +bool SpinnerWidget::rightPressed(const int playerID) { if(m_value+1 <= m_max) setValue(m_value+1); return true; } // ----------------------------------------------------------------------------- -bool SpinnerWidget::leftPressed() +bool SpinnerWidget::leftPressed(const int playerID) { if(m_value-1 >= m_min) setValue(m_value-1); return true; } // ----------------------------------------------------------------------------- -bool SpinnerWidget::transmitEvent(Widget* w, std::string& originator) +bool SpinnerWidget::transmitEvent(Widget* w, std::string& originator, const int playerID) { - if(originator == "left") leftPressed(); - else if(originator == "right") rightPressed(); + if(originator == "left") leftPressed(playerID); + else if(originator == "right") rightPressed(playerID); GUIEngine::getGUIEnv()->setFocus(m_element); return true; diff --git a/src/guiengine/widgets/spinner_widget.hpp b/src/guiengine/widgets/spinner_widget.hpp index 964be9f25..4cdc8ea92 100644 --- a/src/guiengine/widgets/spinner_widget.hpp +++ b/src/guiengine/widgets/spinner_widget.hpp @@ -38,9 +38,9 @@ namespace GUIEngine bool m_graphical; bool m_gauge; - bool transmitEvent(Widget* w, std::string& originator); - bool rightPressed(); - bool leftPressed(); + bool transmitEvent(Widget* w, std::string& originator, const int playerID); + bool rightPressed(const int playerID); + bool leftPressed(const int playerID); public: SpinnerWidget(const bool gauge=false); diff --git a/src/input/input_manager.cpp b/src/input/input_manager.cpp index 88489253d..ae73916b4 100644 --- a/src/input/input_manager.cpp +++ b/src/input/input_manager.cpp @@ -247,7 +247,7 @@ void InputManager::input(Input::InputType type, int deviceID, int btnID, int axi // 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()->isGameState() && type == Input::IT_KEYBOARD && m_mode == MENU && + if (!StateManager::get()->isGameState() && type == Input::IT_KEYBOARD && m_mode == MENU && m_device_manager->playerAssignMode() == NO_ASSIGN) { action = PA_FIRST; @@ -358,7 +358,8 @@ void InputManager::input(Input::InputType type, int deviceID, int btnID, int axi m_timer_in_use = true; m_timer = 0.25; } - GUIEngine::EventHandler::get()->processAction(action, abs(value), type); + int playerID = (player == NULL ? 0 : player->m_id); + GUIEngine::EventHandler::get()->processAction(action, abs(value), type, playerID); } } } diff --git a/src/states_screens/kart_selection.cpp b/src/states_screens/kart_selection.cpp index 7476fcf9b..da5582513 100644 --- a/src/states_screens/kart_selection.cpp +++ b/src/states_screens/kart_selection.cpp @@ -49,6 +49,11 @@ namespace KartSelectionScreen // FIXME : delete these objects when leaving the screen (especially when using escape) ptr_vector g_player_karts; +#if 0 +#pragma mark - +#pragma mark PlayerKartWidget +#endif + class PlayerKartWidget : public Widget { float x_speed, y_speed, w_speed, h_speed; @@ -304,7 +309,7 @@ namespace KartSelectionScreen } - virtual bool transmitEvent(Widget* w, std::string& originator) + virtual bool transmitEvent(Widget* w, std::string& originator, const int playerID) { std::cout << "= kart selection :: transmitEvent " << originator << "=\n"; Widget* topmost = w; @@ -316,7 +321,7 @@ namespace KartSelectionScreen { // transmit events to all listeners in the chain std::cout << "transmitting event to widget " << topmost->m_type << std::endl; - if (!topmost->transmitEvent(w, originator)) return false; + if (!topmost->transmitEvent(w, originator, playerID)) return false; topmost = topmost->m_event_handler; std::string name = topmost->m_properties[PROP_ID]; @@ -327,7 +332,7 @@ namespace KartSelectionScreen // transmit events to all listeners in the chain std::cout << "transmitting event to widget " << topmost->m_type << std::endl; - if (!topmost->transmitEvent(w, originator)) return false; + if (!topmost->transmitEvent(w, originator, playerID)) return false; return false; // do not continue propagating the event } @@ -384,23 +389,27 @@ namespace KartSelectionScreen } }; - +#if 0 +#pragma mark - +#pragma mark KartHoverListener +#endif + class KartHoverListener : public RibbonGridHoverListener { public: - void onSelectionChanged(RibbonGridWidget* theWidget, const std::string& selectionID) + void onSelectionChanged(RibbonGridWidget* theWidget, const std::string& selectionID, const int playerID) { + std::cout << "Player " << playerID << " selected kart " << selectionID.c_str() << std::endl; + /* InputDevice *device; ActivePlayer *player; int pKartIndex = -1; //std::cout << "hovered " << selectionID.c_str() << std::endl; - // FIXME: temporary work around for multiplayer support on the kart selection screen - // The ribbon grid widget needs to be rewritten to support multiple selection boxes - + device = input_manager->getDeviceList()->getLatestUsedDevice(); - if(selectionID.size() == 0) return; - if((player = device->getPlayer()) == NULL) return; + if (selectionID.size() == 0) return; + if ((player = device->getPlayer()) == NULL) return; for (int n = 0; (n < g_player_karts.size() && pKartIndex == -1); n++) { @@ -412,9 +421,9 @@ class KartHoverListener : public RibbonGridHoverListener fprintf(stderr, "onSelectionChanged(): Unable to determine kart associated with device\n"); return; } + */ - - ModelViewWidget* w3 = g_player_karts[pKartIndex].modelView; + ModelViewWidget* w3 = g_player_karts[playerID].modelView; assert( w3 != NULL ); printf("%s\n", selectionID.c_str()); @@ -430,19 +439,24 @@ class KartHoverListener : public RibbonGridHoverListener w3->addModel( kartModel->getWheelModel(3), kartModel->getWheelGraphicsPosition(3) ); w3->update(0); - g_player_karts[pKartIndex].kartName->m_properties[PROP_TEXT] = selectionID; - g_player_karts[pKartIndex].kartName->setText( selectionID.c_str() ); + g_player_karts[playerID].kartName->m_properties[PROP_TEXT] = selectionID; + g_player_karts[playerID].kartName->setText( selectionID.c_str() ); } }; KartHoverListener* karthoverListener = NULL; +#if 0 +#pragma mark - +#pragma mark Functions +#endif + // Return true if event was handled successfully bool playerJoin(InputDevice* device, bool firstPlayer) { std::cout << "playerJoin() ==========\n"; RibbonGridWidget* w = getCurrentScreen()->getWidget("karts"); - if (w == NULL ) + if (w == NULL) { std::cerr << "playerJoin(): Called outside of kart selection screen.\n"; return false; @@ -453,14 +467,16 @@ bool playerJoin(InputDevice* device, bool firstPlayer) return false; } + // ---- Get available area for karts // make a copy of the area, ands move it to be outside the screen Widget rightarea = *getCurrentScreen()->getWidget("playerskarts"); - rightarea.x = irr_driver->getFrameSize().Width; + rightarea.x = irr_driver->getFrameSize().Width; // start at the rightmost of the screen - // Create new active player + // ---- Create new active player int id = StateManager::get()->createActivePlayer( UserConfigParams::m_all_players.get(0), device ); ActivePlayer *aplayer = StateManager::get()->getActivePlayer(id); + // ---- Create player/kart widget // FIXME : player ID needs to be synced with active player list PlayerKartWidget* newPlayer; if (firstPlayer) @@ -472,6 +488,8 @@ bool playerJoin(InputDevice* device, bool firstPlayer) newPlayer->add(); g_player_karts.push_back(newPlayer); + + // ---- Divide screen space among all karts const int amount = g_player_karts.size(); Widget* fullarea = getCurrentScreen()->getWidget("playerskarts"); const int splitWidth = fullarea->w / amount; @@ -481,6 +499,10 @@ bool playerJoin(InputDevice* device, bool firstPlayer) g_player_karts[n].move( fullarea->x + splitWidth*n, fullarea->y, splitWidth, fullarea->h ); } + // ---- Focus a kart for this player + const int playerID = amount-1; + w->setSelection(playerID, playerID); + return true; } diff --git a/src/states_screens/state_manager.cpp b/src/states_screens/state_manager.cpp index a0d794d81..eb2dd42b3 100644 --- a/src/states_screens/state_manager.cpp +++ b/src/states_screens/state_manager.cpp @@ -72,14 +72,20 @@ ActivePlayer* StateManager::getActivePlayer(const int id) { fprintf(stderr, "getActivePlayer(): id out of bounds\n"); } + + assert( returnPlayer->m_id == id ); + return returnPlayer; } -/* -void StateManager::addActivePlayer(ActivePlayer* p) +void StateManager::updateActivePlayerIDs() { - m_active_players.push_back(p); + const int amount = m_active_players.size(); + for (int n=0; n m_active_players; + void updateActivePlayerIDs(); + /** The main 'eventCallback' will dispatch to one of those. * A few screens have their callbacks in a file of their own because they are * too big to fit in here.