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
This commit is contained in:
auria 2009-08-27 18:41:20 +00:00
parent dde666bf9a
commit d9707351ea
22 changed files with 312 additions and 171 deletions

View File

@ -89,8 +89,16 @@ when the border that intersect at this corner are enabled.
<element type="squareFocusHalo" image="glass/glass_square_focused.png"
left_border="6" right_border ="6" top_border="6" bottom_border="6"
hborder_out_portion="1.0" />
<element type="squareFocusHalo2" image="glass/glass_square_focused2.png"
left_border="6" right_border ="6" top_border="6" bottom_border="6"
hborder_out_portion="1.0" />
<element type="squareFocusHalo3" image="glass/glass_square_focused3.png"
left_border="6" right_border ="6" top_border="6" bottom_border="6"
hborder_out_portion="1.0" />
<element type="squareFocusHalo4" image="glass/glass_square_focused4.png"
left_border="6" right_border ="6" top_border="6" bottom_border="6"
hborder_out_portion="1.0" />
<!-- Stateless. No splitting into 9 areas is done; the image is just stretched. -->
<element type="selectionHalo" image="glass/bubble.png" />
<element type="focusHalo" image="glass/glass_iconhighlight_focus.png" />

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

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

View File

@ -70,7 +70,8 @@ bool EventHandler::onGUIEvent(const SEvent& event)
Widget* w = GUIEngine::getCurrentScreen()->getWidget(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 );
}
/*

View File

@ -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();

View File

@ -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<RibbonWidget*>(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
}

View File

@ -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.

View File

@ -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.

View File

@ -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;

View File

@ -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();

View File

@ -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; n<listenerAmount; n++)
{
m_hover_listeners[n].onSelectionChanged(this, getSelectedRibbon()->getSelectionIDString(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; n<listenerAmount; n++)
{
m_hover_listeners[n].onSelectionChanged(this, getSelectedRibbon()->getSelectionIDString());
}
}
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; n<listenerAmount; n++)
{
m_hover_listeners[n].onSelectionChanged(this, w->getSelectionIDString());
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; n<listenerAmount; n++)
{
m_hover_listeners[n].onSelectionChanged(this, getSelectedRibbon()->getSelectionIDString());
// 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; n<listenerAmount; n++)
{
m_hover_listeners[n].onSelectionChanged(this, getSelectedRibbon()->getSelectionIDString());
// 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; n<listenerAmount; n++)
{
m_hover_listeners[n].onSelectionChanged(this, row->getSelectionIDString());
// 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; n<row_amount; n++)
{
RibbonWidget* ribbon = m_rows.get(n);
if (ribbon != selected_ribbon)
const int relative_selection = selected_ribbon->m_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; n<row_amount; n++)
{
RibbonWidget* ribbon = m_rows.get(n);
if (ribbon != selected_ribbon)
{
ribbon->m_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();
}

View File

@ -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);
};
}

View File

@ -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<subbuttons_amount; i++)
for (int i=0; i<subbuttons_amount; i++)
{
if(m_children[i].m_properties[PROP_ID] == item)
if (m_children[i].m_properties[PROP_ID] == item)
{
m_selection = i;
m_selection[playerID] = i;
updateSelection();
return;
}
@ -212,38 +217,38 @@ void RibbonWidget::select(std::string item)
}
// -----------------------------------------------------------------------------
bool RibbonWidget::rightPressed()
bool RibbonWidget::rightPressed(const int playerID)
{
m_selection++;
if(m_selection >= 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<subbuttons_amount; i++)
{
m_children[i].m_selected = (i == m_selection);
// Player 0 selection
m_children[i].m_selected = (i == m_selection[0]);
// Other player selection (FIXME: merge with player 0 selection)
for (int n=1; n<32; n++)
{
if (i == m_selection[n])
m_children[i].setFocusForPlayer(n, true);
else
m_children[i].setFocusForPlayer(n, false);
}
}
if (subbuttons_amount > 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;
}
// -----------------------------------------------------------------------------

View File

@ -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<IGUIStaticText, REF> 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

View File

@ -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;

View File

@ -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);

View File

@ -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);
}
}
}

View File

@ -49,6 +49,11 @@ namespace KartSelectionScreen
// FIXME : delete these objects when leaving the screen (especially when using escape)
ptr_vector<PlayerKartWidget, REF> 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<RibbonGridWidget>("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;
}

View File

@ -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<amount; n++)
{
m_active_players[n].m_id = n;
}
}
*/
int StateManager::createActivePlayer(PlayerProfile *profile, InputDevice *device)
{
ActivePlayer *p;
@ -87,11 +93,16 @@ int StateManager::createActivePlayer(PlayerProfile *profile, InputDevice *device
p = new ActivePlayer(profile, device);
i = m_active_players.size();
m_active_players.push_back(p);
updateActivePlayerIDs();
return i;
}
void StateManager::removeActivePlayer(int id)
{
m_active_players.erase(id);
updateActivePlayerIDs();
}
int StateManager::activePlayerCount()
{

View File

@ -40,6 +40,8 @@ class StateManager : public GUIEngine::AbstractStateManager
*/
ptr_vector<ActivePlayer, HOLD> 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.