New main menu, more minimalistic, based on mockup by samuncle. Please comment
git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@10372 178a84e3-b1eb-0310-8ba1-8eac791a3b58
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 127 KiB |
@ -1,36 +1,40 @@
|
||||
<stkgui>
|
||||
|
||||
<div x="5%" y="0" width="90%" height="100%" layout="vertical-row" >
|
||||
|
||||
<icon id="logo" align="center" proportion="8" width="100%" icon="gui/logo.png"/>
|
||||
<buttonbar id="menu_toprow" proportion="3" width="75%" align="center">
|
||||
<div x="0" y="0" width="100%" height="100%" layout="vertical-row" >
|
||||
|
||||
<topbar width="100%" height="9%" layout="horizontal-row">
|
||||
<spacer proportion="1" height="1"/>
|
||||
<buttonbar id="menu_bottomrow" x="0" y="0" width="30%" height="100%" align="center">
|
||||
<icon-button id="options" width="64" height="64" icon="gui/main_options.png"
|
||||
I18N="Main menu button" text="Options" label_location="hover"/>
|
||||
<icon-button id="help" width="64" height="64" icon="gui/main_help.png"
|
||||
I18N="Main menu button" text="Help" label_location="hover"/>
|
||||
<icon-button id="about" width="64" height="64" icon="gui/main_about.png"
|
||||
I18N="Main menu button" text="About" label_location="hover"/>
|
||||
<icon-button id="quit" width="64" height="64" icon="gui/main_quit.png"
|
||||
I18N="Main menu button" text="Quit" label_location="hover"/>
|
||||
</buttonbar>
|
||||
</topbar>
|
||||
|
||||
<icon id="logo" align="center" proportion="5" width="100%" icon="gui/logo.png"/>
|
||||
|
||||
<buttonbar id="menu_toprow" proportion="4" width="75%" align="center">
|
||||
<icon-button id="story" width="128" height="128"
|
||||
icon="gui/challenge.png"
|
||||
icon="gui/challenge.png" label_location="hover"
|
||||
I18N="Main menu button" text="Story Mode"/>
|
||||
<icon-button id="new" width="128" height="128" icon="gui/main_race.png"
|
||||
I18N="Main menu button" text="Single-player"/>
|
||||
label_location="hover"
|
||||
I18N="Main menu button" text="Single-player"/>
|
||||
<icon-button id="multiplayer" width="128" height="128" icon="gui/main_race_multi.png"
|
||||
I18N="Main menu button" text="Multiplayer"/>
|
||||
label_location="hover"
|
||||
I18N="Main menu button" text="Multiplayer"/>
|
||||
<icon-button id="addons" width="128" height="128"
|
||||
icon="gui/addons.png"
|
||||
icon="gui/addons.png" label_location="hover"
|
||||
I18N="Main menu button" text="Addons"/>
|
||||
</buttonbar>
|
||||
|
||||
<spacer width="10" proportion="1"/>
|
||||
|
||||
<buttonbar id="menu_bottomrow" proportion="3" width="85%" align="center">
|
||||
<icon-button id="options" width="128" height="128" icon="gui/main_options.png"
|
||||
I18N="Main menu button" text="Options"/>
|
||||
<icon-button id="help" width="128" height="128" icon="gui/main_help.png"
|
||||
I18N="Main menu button" text="Help"/>
|
||||
<icon-button id="about" width="128" height="128" icon="gui/main_about.png"
|
||||
I18N="Main menu button" text="About"/>
|
||||
<icon-button id="quit" width="128" height="128" icon="gui/main_quit.png"
|
||||
I18N="Main menu button" text="Quit"/>
|
||||
</buttonbar>
|
||||
|
||||
<spacer width="10" proportion="1"/>
|
||||
|
||||
<spacer width="10" height="3%"/>
|
||||
|
||||
<bottombar width="100%" height="10%" layout="horizontal-row">
|
||||
|
||||
<spacer width="10" height="10" />
|
||||
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 127 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 49 KiB |
BIN
data/gui/top_bar.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
@ -77,6 +77,12 @@ void Screen::parseScreenFileDiv(irr::io::IXMLReader* xml, PtrVector<Widget>& app
|
||||
w->m_bottom_bar = true;
|
||||
append_to.push_back(w);
|
||||
}
|
||||
else if (wcscmp(L"topbar", xml->getNodeName()) == 0)
|
||||
{
|
||||
Widget* w = new Widget(WTYPE_DIV);
|
||||
w->m_top_bar = true;
|
||||
append_to.push_back(w);
|
||||
}
|
||||
else if (wcscmp(L"roundedbox", xml->getNodeName()) == 0)
|
||||
{
|
||||
Widget* w = new Widget(WTYPE_DIV);
|
||||
@ -243,6 +249,10 @@ if(prop_name != NULL) widget.m_properties[prop_flag] = core::stringc(prop_name).
|
||||
return;
|
||||
if (wcscmp(L"roundedbox", xml->getNodeName()) == 0)
|
||||
return;
|
||||
if (wcscmp(L"bottombar", xml->getNodeName()) == 0)
|
||||
return;
|
||||
if (wcscmp(L"topbar", xml->getNodeName()) == 0)
|
||||
return;
|
||||
|
||||
// we're done parsing this 'ribbon', return one step back in the recursive call
|
||||
if (wcscmp(L"ribbon", xml->getNodeName()) == 0 ||
|
||||
|
@ -1578,6 +1578,18 @@ void Skin::renderSections(PtrVector<Widget>* within_vector)
|
||||
irr_driver->getVideoDriver()->draw2DImage(tex, r1, r2,
|
||||
0, 0, /*alpha*/true);
|
||||
}
|
||||
else if (widget.isTopBar())
|
||||
{
|
||||
ITexture* tex =
|
||||
irr_driver->getTexture( file_manager->getGUIDir()
|
||||
+ "top_bar.png" );
|
||||
|
||||
core::recti r1(0, 0,
|
||||
(int)widget.m_w, (int)widget.m_h);
|
||||
core::recti r2(core::dimension2di(0,0), tex->getSize());
|
||||
irr_driver->getVideoDriver()->draw2DImage(tex, r1, r2,
|
||||
0, 0, /*alpha*/false);
|
||||
}
|
||||
else
|
||||
{
|
||||
renderSections( &widget.m_children );
|
||||
|
@ -74,6 +74,7 @@ Widget::Widget(WidgetType type, bool reserve_id)
|
||||
m_parent = NULL;
|
||||
m_focusable = true;
|
||||
m_bottom_bar = false;
|
||||
m_top_bar = false;
|
||||
m_event_handler = NULL;
|
||||
m_reserve_id = reserve_id;
|
||||
m_show_bounding_box = false;
|
||||
@ -259,7 +260,7 @@ void Widget::setFocusForPlayer(const int playerID)
|
||||
// Unset focus flag on previous widget that had focus
|
||||
if (GUIEngine::getFocusForPlayer(playerID) != NULL)
|
||||
{
|
||||
GUIEngine::getFocusForPlayer(playerID)->unfocused(playerID);
|
||||
GUIEngine::getFocusForPlayer(playerID)->unfocused(playerID, this);
|
||||
GUIEngine::getFocusForPlayer(playerID)->m_player_focus[playerID] = false;
|
||||
}
|
||||
|
||||
@ -276,7 +277,7 @@ void Widget::unsetFocusForPlayer(const int playerID)
|
||||
{
|
||||
assert(m_magic_number == 0xCAFEC001);
|
||||
|
||||
if (m_player_focus[playerID]) this->unfocused(playerID);
|
||||
if (m_player_focus[playerID]) this->unfocused(playerID, NULL);
|
||||
m_player_focus[playerID] = false;
|
||||
}
|
||||
|
||||
|
@ -191,7 +191,7 @@ namespace GUIEngine
|
||||
virtual EventPropagation focused(const int playerID) { setWithinATextBox(false); return EVENT_LET; }
|
||||
|
||||
/** override in children if you need to know when the widget is unfocused. */
|
||||
virtual void unfocused(const int playerID) { }
|
||||
virtual void unfocused(const int playerID, Widget* new_focus) { }
|
||||
|
||||
/**
|
||||
* An irrlicht parent (most often used to put widgets in dialogs)
|
||||
@ -238,7 +238,8 @@ namespace GUIEngine
|
||||
bool m_focusable;
|
||||
|
||||
bool m_bottom_bar;
|
||||
|
||||
bool m_top_bar;
|
||||
|
||||
/** If a badge wouldn't look too pretty on the very side of the widget */
|
||||
int m_badge_x_shift;
|
||||
|
||||
@ -332,7 +333,8 @@ namespace GUIEngine
|
||||
bool isSelected(const int playerID) const { return m_selected[playerID]; }
|
||||
|
||||
bool isBottomBar() const { return m_bottom_bar; }
|
||||
|
||||
bool isTopBar () const { return m_top_bar; }
|
||||
|
||||
/**
|
||||
* \name Enabling or disabling widgets
|
||||
* \{
|
||||
|
@ -156,7 +156,7 @@ EventPropagation BubbleWidget::focused(const int playerID)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/*
|
||||
void BubbleWidget::unfocused(const int playerID)
|
||||
void BubbleWidget::unfocused(const int playerID, Widget* new_focus)
|
||||
{
|
||||
if (m_element != NULL)
|
||||
{
|
||||
|
@ -59,3 +59,6 @@ EventPropagation CheckBoxWidget::transmitEvent(Widget* w,
|
||||
/* notify main event handler */
|
||||
return EVENT_LET;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
@ -53,6 +53,7 @@ namespace GUIEngine
|
||||
/** Set whether the checkbox is checked */
|
||||
void setState(const bool checked) { m_state = checked; }
|
||||
|
||||
|
||||
/** When inferring widget size from its label length, this method will be called to
|
||||
* if/how much space must be added to the raw label's size for the widget to be large enough */
|
||||
virtual int getHeightNeededAroundLabel() const { return 10; }
|
||||
|
@ -139,6 +139,11 @@ void IconButtonWidget::add()
|
||||
m_label->setTabStop(false);
|
||||
m_label->setNotClipped(true);
|
||||
|
||||
if (m_properties[PROP_LABELS_LOCATION] == "hover")
|
||||
{
|
||||
m_label->setVisible(false);
|
||||
}
|
||||
|
||||
const int max_w = m_label->getAbsolutePosition().getWidth();
|
||||
if (!word_wrap &&
|
||||
(int)GUIEngine::getFont()->getDimension(message.c_str()).Width > max_w + 4) // arbitrarily allow for 4 pixels
|
||||
@ -225,3 +230,25 @@ void IconButtonWidget::setLabel(stringw new_label)
|
||||
m_label->setOverrideFont( NULL );
|
||||
}
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
EventPropagation IconButtonWidget::focused(const int playerID)
|
||||
{
|
||||
Widget::focused(playerID);
|
||||
|
||||
if (m_label != NULL && m_properties[PROP_LABELS_LOCATION] == "hover")
|
||||
{
|
||||
m_label->setVisible(true);
|
||||
}
|
||||
return EVENT_LET;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
void IconButtonWidget::unfocused(const int playerID, Widget* new_focus)
|
||||
{
|
||||
Widget::unfocused(playerID, new_focus);
|
||||
if (m_label != NULL && m_properties[PROP_LABELS_LOCATION] == "hover")
|
||||
{
|
||||
m_label->setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -122,6 +122,12 @@ namespace GUIEngine
|
||||
{
|
||||
m_highlight_texture = texture;
|
||||
}
|
||||
|
||||
/** \brief override from base class */
|
||||
virtual EventPropagation focused(const int playerID);
|
||||
|
||||
/** \brief override from base class */
|
||||
virtual void unfocused(const int playerID, Widget* new_focus);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -231,7 +231,7 @@ void ListWidget::selectItemWithLabel(const irr::core::stringw& name)
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void ListWidget::unfocused(const int playerID)
|
||||
void ListWidget::unfocused(const int playerID, Widget* new_focus)
|
||||
{
|
||||
IGUIListBox* list = getIrrlichtElement<IGUIListBox>();
|
||||
|
||||
|
@ -96,7 +96,7 @@ namespace GUIEngine
|
||||
virtual void add();
|
||||
|
||||
/** \brief implement callback from base class GUIEngine::Widget */
|
||||
virtual void unfocused(const int playerID);
|
||||
virtual void unfocused(const int playerID, Widget* new_focus);
|
||||
|
||||
/** \brief implement callback from base class GUIEngine::Widget */
|
||||
virtual void elementRemoved();
|
||||
|
@ -66,10 +66,16 @@ RibbonWidget::RibbonWidget(const RibbonType type) : Widget(WTYPE_RIBBON)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void RibbonWidget::add()
|
||||
{
|
||||
m_labels.clearWithoutDeleting();
|
||||
{
|
||||
assert(m_magic_number == 0xCAFEC001);
|
||||
assert(m_x > -10.0f);
|
||||
assert(m_y > -10.0f);
|
||||
assert(m_w > 0.0f);
|
||||
assert(m_h > 0.0f);
|
||||
|
||||
|
||||
m_labels.clearWithoutDeleting();
|
||||
|
||||
rect<s32> widget_size = rect<s32>(m_x, m_y, m_x + m_w, m_y + m_h);
|
||||
|
||||
int id = (m_reserved_id == -1 ? getNewID() : m_reserved_id);
|
||||
@ -111,8 +117,14 @@ void RibbonWidget::add()
|
||||
}
|
||||
|
||||
|
||||
if (m_children[i].m_text.size() > 0) with_label++;
|
||||
else without_label++;
|
||||
bool has_label_underneath = m_children[i].m_text.size() > 0;
|
||||
if (m_children[i].m_properties[PROP_LABELS_LOCATION].size() > 0)
|
||||
{
|
||||
has_label_underneath = false;
|
||||
}
|
||||
|
||||
if (has_label_underneath) with_label++;
|
||||
else without_label++;
|
||||
|
||||
total_needed_space += m_children[i].m_w;
|
||||
}
|
||||
@ -267,7 +279,12 @@ void RibbonWidget::add()
|
||||
|
||||
// find how much space to keep for the label under the button.
|
||||
// consider font size, whether the label is multiline, etc...
|
||||
const bool has_label = m_children[i].m_text.size() > 0;
|
||||
bool has_label = m_children[i].m_text.size() > 0;
|
||||
|
||||
if (m_children[i].m_properties[PROP_LABELS_LOCATION].size() > 0)
|
||||
{
|
||||
has_label = false;
|
||||
}
|
||||
|
||||
const int needed_space_under_button = has_label
|
||||
? GUIEngine::getFontHeight()
|
||||
@ -422,6 +439,7 @@ EventPropagation RibbonWidget::rightPressed(const int playerID)
|
||||
if (m_children.size() < 2) return EVENT_LET;
|
||||
|
||||
m_selection[playerID]++;
|
||||
|
||||
if (m_selection[playerID] >= m_children.size())
|
||||
{
|
||||
if (m_listener != NULL) m_listener->onRibbonWidgetScroll(1);
|
||||
@ -457,7 +475,7 @@ EventPropagation RibbonWidget::leftPressed(const int playerID)
|
||||
if (m_deactivated) return EVENT_LET;
|
||||
// empty ribbon, or only one item (can't move left)
|
||||
if (m_children.size() < 2) return EVENT_LET;
|
||||
|
||||
|
||||
m_selection[playerID]--;
|
||||
if (m_selection[playerID] < 0)
|
||||
{
|
||||
@ -467,6 +485,7 @@ EventPropagation RibbonWidget::leftPressed(const int playerID)
|
||||
? 0
|
||||
: m_children.size()-1;
|
||||
}
|
||||
|
||||
updateSelection();
|
||||
|
||||
if (m_ribbon_type == RIBBON_COMBO)
|
||||
@ -510,6 +529,14 @@ EventPropagation RibbonWidget::focused(const int playerID)
|
||||
(playerID == mousePlayerID || playerID == PLAYER_ID_GAME_MASTER))
|
||||
{
|
||||
m_mouse_focus = m_children.get(m_selection[playerID]);
|
||||
m_mouse_focus->focused(playerID);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_selection[playerID] != -1)
|
||||
{
|
||||
m_children.get(m_selection[playerID])->focused(playerID);
|
||||
}
|
||||
}
|
||||
|
||||
@ -521,8 +548,17 @@ EventPropagation RibbonWidget::focused(const int playerID)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void RibbonWidget::unfocused(const int playerID)
|
||||
void RibbonWidget::unfocused(const int playerID, Widget* new_focus)
|
||||
{
|
||||
if (new_focus != NULL && new_focus != this && !m_children.contains(new_focus))
|
||||
{
|
||||
if (m_selection[playerID] != -1)
|
||||
{
|
||||
m_children.get(m_selection[playerID])->unfocused(playerID, new_focus);
|
||||
}
|
||||
}
|
||||
|
||||
//if (m_selection[0] != -1) m_children.get(m_selection[0])->unfocused(0);
|
||||
} // unfocused
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -548,6 +584,7 @@ EventPropagation RibbonWidget::mouseHovered(Widget* child,
|
||||
{
|
||||
// Was already selected, don't send another event
|
||||
if (m_selection[mousePlayerID] == i) return EVENT_BLOCK;
|
||||
|
||||
// Don't change selection on hover for others
|
||||
m_selection[mousePlayerID] = i;
|
||||
break;
|
||||
@ -588,7 +625,13 @@ void RibbonWidget::updateSelection()
|
||||
{
|
||||
for (int i=0; i<subbuttons_amount; i++)
|
||||
{
|
||||
m_children[i].m_selected[p] = (i == m_selection[p]);
|
||||
bool new_val = (i == m_selection[p]);
|
||||
if (!new_val && m_children[i].m_selected[p])
|
||||
{
|
||||
m_children[i].unfocused(PLAYER_ID_GAME_MASTER, NULL);
|
||||
}
|
||||
m_children[i].m_selected[p] = new_val;
|
||||
if (new_val) m_children[i].focused(PLAYER_ID_GAME_MASTER);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,7 @@ namespace GUIEngine
|
||||
const std::string& originator,
|
||||
const int playerID=0);
|
||||
virtual EventPropagation focused(const int playerID);
|
||||
virtual void unfocused(const int playerID);
|
||||
virtual void unfocused(const int playerID, Widget* new_focus);
|
||||
|
||||
PtrVector<irr::gui::IGUIStaticText, REF> m_labels;
|
||||
|
||||
|
@ -140,7 +140,7 @@ EventPropagation TextBoxWidget::focused(const int playerID)
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void TextBoxWidget::unfocused(const int playerID)
|
||||
void TextBoxWidget::unfocused(const int playerID, Widget* new_focus)
|
||||
{
|
||||
assert(playerID == 0); // No support for multiple players in text areas!
|
||||
|
||||
|
@ -62,7 +62,7 @@ namespace GUIEngine
|
||||
void addItem(const char* item);
|
||||
|
||||
virtual EventPropagation focused(const int playerID);
|
||||
virtual void unfocused(const int playerID);
|
||||
virtual void unfocused(const int playerID, Widget* new_focus);
|
||||
|
||||
void addListener(ITextBoxWidgetListener* listener);
|
||||
void clearListeners();
|
||||
|