diff --git a/data/gui/tracks.stkgui b/data/gui/tracks.stkgui index 9d087a6ce..f40ee4c71 100644 --- a/data/gui/tracks.stkgui +++ b/data/gui/tracks.stkgui @@ -6,10 +6,10 @@ align="center" text_align="center" /> - - - - + + + +
m_focusable) return GUIEngine::EVENT_BLOCK; + // These events are only triggered by keyboard/mouse (or so I hope...) const int playerID = input_manager->getPlayerKeyboardID(); if (input_manager->masterPlayerOnly() && playerID != 0) break; @@ -92,6 +94,8 @@ EventPropagation EventHandler::onGUIEvent(const SEvent& event) Widget* w = GUIEngine::getWidget(id); if (w == NULL) break; + if (!w->m_focusable) return GUIEngine::EVENT_BLOCK; + // When a modal dialog is shown, don't select widgets out of the dialog if (ModalDialog::isADialogActive() && !ModalDialog::getCurrent()->isMyChild(w)) { diff --git a/src/guiengine/screen.cpp b/src/guiengine/screen.cpp index 47adbf229..9f0cd9f0b 100644 --- a/src/guiengine/screen.cpp +++ b/src/guiengine/screen.cpp @@ -391,17 +391,19 @@ Widget* Screen::getWidget(const int id, ptr_vector* within_vector) // ----------------------------------------------------------------------------- Widget* Screen::getFirstWidget(ptr_vector* within_vector) { - if(within_vector == NULL) within_vector = &m_widgets; + if (within_vector == NULL) within_vector = &m_widgets; - for(int i = 0; i < within_vector->size(); i++) + for (int i = 0; i < within_vector->size(); i++) { + if (!within_vector->get(i)->m_focusable) continue; + // if container, also checks children - if(within_vector->get(i)->m_children.size() > 0 && - within_vector->get(i)->m_type != WTYPE_RIBBON && - within_vector->get(i)->m_type != WTYPE_SPINNER) + if (within_vector->get(i)->m_children.size() > 0 && + within_vector->get(i)->m_type != WTYPE_RIBBON && + within_vector->get(i)->m_type != WTYPE_SPINNER) { Widget* w = getFirstWidget(&within_vector->get(i)->m_children); - if(w != NULL) return w; + if (w != NULL) return w; } if (within_vector->get(i)->m_element == NULL || within_vector->get(i)->m_element->getTabOrder() == -1 || @@ -416,15 +418,17 @@ Widget* Screen::getLastWidget(ptr_vector* within_vector) { if (within_vector == NULL) within_vector = &m_widgets; - for(int i = within_vector->size()-1; i >= 0; i--) + for (int i = within_vector->size()-1; i >= 0; i--) { + if (!within_vector->get(i)->m_focusable) continue; + // if container, also checks children - if(within_vector->get(i)->m_children.size() > 0 && - within_vector->get(i)->m_type != WTYPE_RIBBON && - within_vector->get(i)->m_type != WTYPE_SPINNER) + if (within_vector->get(i)->m_children.size() > 0 && + within_vector->get(i)->m_type != WTYPE_RIBBON && + within_vector->get(i)->m_type != WTYPE_SPINNER) { Widget* w = getLastWidget(&within_vector->get(i)->m_children); - if(w != NULL) return w; + if (w != NULL) return w; } if (within_vector->get(i)->m_element == NULL || within_vector->get(i)->m_element->getTabOrder() == -1 || diff --git a/src/guiengine/skin.cpp b/src/guiengine/skin.cpp index 4bfa4a89f..1767a4696 100644 --- a/src/guiengine/skin.cpp +++ b/src/guiengine/skin.cpp @@ -589,12 +589,12 @@ void Skin::drawButton(Widget* w, const core::rect< s32 > &rect, const bool press { core::rect< s32 > sized_rect = rect; core::position2d center = core::position2d(irr_driver->getFrameSize()/2); - const float size = sin(m_dialog_size*M_PI*0.5f); + const float texture_size = sin(m_dialog_size*M_PI*0.5f); - sized_rect.UpperLeftCorner.X = center.X + (int)((rect.UpperLeftCorner.X - center.X)*size); - sized_rect.UpperLeftCorner.Y = center.Y + (int)((rect.UpperLeftCorner.Y - center.Y)*size); - sized_rect.LowerRightCorner.X = center.X + (int)((rect.LowerRightCorner.X - center.X)*size); - sized_rect.LowerRightCorner.Y = center.Y + (int)((rect.LowerRightCorner.Y - center.Y)*size); + sized_rect.UpperLeftCorner.X = center.X + (int)((rect.UpperLeftCorner.X - center.X)*texture_size); + sized_rect.UpperLeftCorner.Y = center.Y + (int)((rect.UpperLeftCorner.Y - center.Y)*texture_size); + sized_rect.LowerRightCorner.X = center.X + (int)((rect.LowerRightCorner.X - center.X)*texture_size); + sized_rect.LowerRightCorner.Y = center.Y + (int)((rect.LowerRightCorner.Y - center.Y)*texture_size); if (focused) drawBoxFromStretchableTexture(w, sized_rect, SkinConfig::m_render_params["button::focused"]); @@ -633,13 +633,13 @@ void Skin::drawRibbonChild(const core::rect< s32 > &rect, Widget* widget, const RibbonType type = parentRibbon->getRibbonType(); /* tab-bar ribbons */ - if(type == RIBBON_TABS) + if (type == RIBBON_TABS) { BoxRenderParams* params; - if(mark_selected && (focused || parent_focused)) + if (mark_selected && (focused || parent_focused)) params = &SkinConfig::m_render_params["tab::focused"]; - else if(mark_selected) + else if (mark_selected) params = &SkinConfig::m_render_params["tab::down"]; else params = &SkinConfig::m_render_params["tab::neutral"]; @@ -794,6 +794,8 @@ void Skin::drawRibbonChild(const core::rect< s32 > &rect, Widget* widget, const { drawBoxFromStretchableTexture(w, rect, SkinConfig::m_render_params["squareFocusHalo4::neutral"]); } + + drawIconButton(rect, widget, pressed, focused); } // end if icon ribbons @@ -902,6 +904,50 @@ void Skin::drawSpinnerChild(const core::rect< s32 > &rect, Widget* widget, const } +void Skin::drawIconButton(const core::rect< s32 > &rect, Widget* widget, const bool pressed, bool focused) +{ + if (focused) + { + int grow = 45; + static float glow_effect = 0; + + + const float dt = GUIEngine::getLatestDt(); + glow_effect += dt*3; + if (glow_effect > 6.2832f /* 2*PI */) glow_effect -= 6.2832f; + grow = (int)(45 + 10*sin(glow_effect)); + + + const int glow_center_x = rect.UpperLeftCorner.X + rect.getWidth()/2; + const int glow_center_y = rect.LowerRightCorner.Y; + + ITexture* tex_ficonhighlight = SkinConfig::m_render_params["focusHalo::neutral"].getImage(); + const int texture_w = tex_ficonhighlight->getSize().Width; + const int texture_h = tex_ficonhighlight->getSize().Height; + + core::rect source_area = core::rect(0, 0, texture_w, texture_h); + + + const core::rect< s32 > rect2 = core::rect< s32 >(glow_center_x - 45 - grow, + glow_center_y - 25 - grow/2, + glow_center_x + 45 + grow, + glow_center_y + 25 + grow/2); + + GUIEngine::getDriver()->draw2DImage(tex_ficonhighlight, rect2, source_area, + 0 /* no clipping */, 0, true /* alpha */); + } + + IconButtonWidget* icon_widget = (IconButtonWidget*) widget; + //std::cout << "Drawing icon button '" << icon_widget->m_properties[PROP_ID] << "' : " << icon_widget->m_texture->getName().c_str() << "; size : " << + // icon_widget->m_texture_w << "," << icon_widget->m_texture_h << + // " --> " << rect.UpperLeftCorner.X << ", " << rect.UpperLeftCorner.Y << " " << rect.getWidth() << "x" << rect.getHeight() << "\n"; + GUIEngine::getDriver()->draw2DImage(icon_widget->m_texture, rect, + core::rect(0,0,icon_widget->m_texture_w, icon_widget->m_texture_h), + 0 /* no clipping */, 0, true /* alpha */); + +} + + void Skin::drawCheckBox(const core::rect< s32 > &rect, Widget* widget, bool focused) { CheckBoxWidget* w = dynamic_cast(widget); @@ -1030,45 +1076,15 @@ void Skin::process3DPane(IGUIElement *element, const core::rect< s32 > &rect, co if (widget->m_event_handler != NULL && widget->m_event_handler->m_type == WTYPE_RIBBON) { - drawRibbonChild(rect, widget, pressed /* pressed */, focused /* focused */); + drawRibbonChild(rect, widget, pressed, focused); } else if (widget->m_event_handler != NULL && widget->m_event_handler->m_type == WTYPE_SPINNER) { - drawSpinnerChild(rect, widget, pressed /* pressed */, focused /* focused */); + drawSpinnerChild(rect, widget, pressed, focused); } else if (type == WTYPE_ICON_BUTTON) { - if (focused) - { - int grow = 45; - static float glow_effect = 0; - - - const float dt = GUIEngine::getLatestDt(); - glow_effect += dt*3; - if (glow_effect > 6.2832f /* 2*PI */) glow_effect -= 6.2832f; - grow = (int)(45 + 10*sin(glow_effect)); - - - const int glow_center_x = rect.UpperLeftCorner.X + rect.getWidth()/2; - const int glow_center_y = rect.LowerRightCorner.Y; - - ITexture* tex_ficonhighlight = SkinConfig::m_render_params["focusHalo::neutral"].getImage(); - const int texture_w = tex_ficonhighlight->getSize().Width; - const int texture_h = tex_ficonhighlight->getSize().Height; - - core::rect source_area = core::rect(0, 0, texture_w, texture_h); - - - const core::rect< s32 > rect2 = core::rect< s32 >(glow_center_x - 45 - grow, - glow_center_y - 25 - grow/2, - glow_center_x + 45 + grow, - glow_center_y + 25 + grow/2); - - GUIEngine::getDriver()->draw2DImage(tex_ficonhighlight, rect2, source_area, - 0 /* no clipping */, 0, true /* alpha */); - - } + drawIconButton(rect, widget, pressed, focused); } else if(type == WTYPE_BUTTON) { @@ -1094,6 +1110,30 @@ void Skin::process3DPane(IGUIElement *element, const core::rect< s32 > &rect, co SColor color(255, 255, 0, 0); GUIEngine::getFont()->draw(idstring.c_str(), rect, color, true, true); } + + if (widget->m_lock_badge || widget->m_okay_badge) + { + // TODO + video::ITexture* texture = NULL; + + if (widget->m_lock_badge) texture = irr_driver->getTexture(file_manager->getTextureFile("gui_lock.png")); + else if (widget->m_okay_badge) texture = irr_driver->getTexture(file_manager->getTextureFile("green_check.png")); + else { assert(false); return; } + const core::dimension2d& texture_size = texture->getSize(); + const float aspectRatio = (float)texture_size.Width / (float)texture_size.Height; + const int h = std::min( rect.getHeight()/2 , (int)(texture_size.Height) ); + int w = aspectRatio*h; + + const core::rect source_area = core::rect(0, 0, texture_size.Width, texture_size.Height); + + const core::rect< s32 > rect2 = core::rect< s32 >(rect.UpperLeftCorner.X, + rect.LowerRightCorner.Y - h, + rect.UpperLeftCorner.X + w, + rect.LowerRightCorner.Y); + + GUIEngine::getDriver()->draw2DImage(texture, rect2, source_area, + 0 /* no clipping */, 0, true /* alpha */); + } } void Skin::draw3DButtonPanePressed (IGUIElement *element, const core::rect< s32 > &rect, const core::rect< s32 > *clip) @@ -1140,12 +1180,12 @@ void Skin::draw3DSunkenPane (IGUIElement *element, video::SColor bgcolor, bool f if (m_dialog && m_dialog_size < 1.0f && widget->m_parent != NULL && widget->m_parent->getType() == gui::EGUIET_WINDOW) { core::position2d center = core::position2d(irr_driver->getFrameSize()/2); - const float size = sin(m_dialog_size*M_PI*0.5f); + const float texture_size = sin(m_dialog_size*M_PI*0.5f); - borderArea.UpperLeftCorner.X = center.X + (int)((rect.UpperLeftCorner.X - center.X)*size); - borderArea.UpperLeftCorner.Y = center.Y + (int)((rect.UpperLeftCorner.Y - center.Y)*size); - borderArea.LowerRightCorner.X = center.X + (int)((rect.LowerRightCorner.X - center.X)*size); - borderArea.LowerRightCorner.Y = center.Y + (int)((rect.LowerRightCorner.Y - center.Y)*size); + borderArea.UpperLeftCorner.X = center.X + (int)((rect.UpperLeftCorner.X - center.X)*texture_size); + borderArea.UpperLeftCorner.Y = center.Y + (int)((rect.UpperLeftCorner.Y - center.Y)*texture_size); + borderArea.LowerRightCorner.X = center.X + (int)((rect.LowerRightCorner.X - center.X)*texture_size); + borderArea.LowerRightCorner.Y = center.Y + (int)((rect.LowerRightCorner.Y - center.Y)*texture_size); } GUIEngine::getDriver()->draw2DRectangle( colorFocus, borderArea ); @@ -1160,12 +1200,12 @@ void Skin::draw3DSunkenPane (IGUIElement *element, video::SColor bgcolor, bool f if (m_dialog && m_dialog_size < 1.0f && widget->m_parent != NULL && widget->m_parent->getType() == gui::EGUIET_WINDOW) { core::position2d center = core::position2d(irr_driver->getFrameSize()/2); - const float size = sin(m_dialog_size*M_PI*0.5f); + const float texture_size = sin(m_dialog_size*M_PI*0.5f); core::rect< s32 > sizedRect; - sizedRect.UpperLeftCorner.X = center.X + (int)((rect.UpperLeftCorner.X - center.X)*size); - sizedRect.UpperLeftCorner.Y = center.Y + (int)((rect.UpperLeftCorner.Y - center.Y)*size); - sizedRect.LowerRightCorner.X = center.X + (int)((rect.LowerRightCorner.X - center.X)*size); - sizedRect.LowerRightCorner.Y = center.Y + (int)((rect.LowerRightCorner.Y - center.Y)*size); + sizedRect.UpperLeftCorner.X = center.X + (int)((rect.UpperLeftCorner.X - center.X)*texture_size); + sizedRect.UpperLeftCorner.Y = center.Y + (int)((rect.UpperLeftCorner.Y - center.Y)*texture_size); + sizedRect.LowerRightCorner.X = center.X + (int)((rect.LowerRightCorner.X - center.X)*texture_size); + sizedRect.LowerRightCorner.Y = center.Y + (int)((rect.LowerRightCorner.Y - center.Y)*texture_size); GUIEngine::getDriver()->draw2DRectangle( color, sizedRect ); } else @@ -1207,11 +1247,11 @@ core::rect< s32 > Skin::draw3DWindowBackground (IGUIElement *element, bool drawT core::position2d center = sized_rect.getCenter(); const int w = sized_rect.getWidth(); const int h = sized_rect.getHeight(); - const float size = sin(m_dialog_size*M_PI*0.5f); - sized_rect.UpperLeftCorner.X = (int)(center.X - (w/2.0f)*size); - sized_rect.UpperLeftCorner.Y = (int)(center.Y - (h/2.0f)*size); - sized_rect.LowerRightCorner.X = (int)(center.X + (w/2.0f)*size); - sized_rect.LowerRightCorner.Y = (int)(center.Y + (h/2.0f)*size); + const float texture_size = sin(m_dialog_size*M_PI*0.5f); + sized_rect.UpperLeftCorner.X = (int)(center.X - (w/2.0f)*texture_size); + sized_rect.UpperLeftCorner.Y = (int)(center.Y - (h/2.0f)*texture_size); + sized_rect.LowerRightCorner.X = (int)(center.X + (w/2.0f)*texture_size); + sized_rect.LowerRightCorner.Y = (int)(center.Y + (h/2.0f)*texture_size); drawBoxFromStretchableTexture( ModalDialog::getCurrent(), sized_rect, SkinConfig::m_render_params["window::neutral"]); m_dialog_size += GUIEngine::getLatestDt()*5; @@ -1309,9 +1349,9 @@ u32 Skin::getIcon (EGUI_DEFAULT_ICON icon) const return 0; } -s32 Skin::getSize (EGUI_DEFAULT_SIZE size) const +s32 Skin::getSize (EGUI_DEFAULT_SIZE texture_size) const { - return m_fallback_skin->getSize(size); + return m_fallback_skin->getSize(texture_size); } IGUISpriteBank* Skin::getSpriteBank () const @@ -1341,9 +1381,9 @@ void Skin::setIcon (EGUI_DEFAULT_ICON icon, u32 index) m_fallback_skin->setIcon(icon, index); } -void Skin::setSize (EGUI_DEFAULT_SIZE which, s32 size) +void Skin::setSize (EGUI_DEFAULT_SIZE which, s32 texture_size) { - m_fallback_skin->setSize(which, size); + m_fallback_skin->setSize(which, texture_size); //printf("setting size\n"); } diff --git a/src/guiengine/skin.hpp b/src/guiengine/skin.hpp index c6d41a8e8..4cab80558 100644 --- a/src/guiengine/skin.hpp +++ b/src/guiengine/skin.hpp @@ -230,6 +230,7 @@ namespace GUIEngine void drawCheckBox(const irr::core::rect< irr::s32 > &rect, Widget* widget, bool focused); void drawList(const irr::core::rect< irr::s32 > &rect, Widget* widget, bool focused); void drawListSelection(const irr::core::rect< irr::s32 > &rect, Widget* widget, bool focused); + void drawIconButton(const irr::core::rect< irr::s32 > &rect, Widget* widget, const bool pressed, bool focused); public: // dirty way to have dialogs that zoom in diff --git a/src/guiengine/widget.cpp b/src/guiengine/widget.cpp index 92511b048..550897fa5 100644 --- a/src/guiengine/widget.cpp +++ b/src/guiengine/widget.cpp @@ -64,6 +64,7 @@ Widget::Widget(bool reserve_id) m_element = NULL; m_title_font = false; m_type = WTYPE_NONE; + m_focusable = true; m_event_handler = NULL; m_show_bounding_box = false; @@ -80,6 +81,9 @@ Widget::Widget(bool reserve_id) } m_reserved_id = -1; + + m_lock_badge = false; + m_okay_badge = false; } Widget::~Widget() diff --git a/src/guiengine/widget.hpp b/src/guiengine/widget.hpp index af02c9fe4..c38021a30 100644 --- a/src/guiengine/widget.hpp +++ b/src/guiengine/widget.hpp @@ -196,6 +196,15 @@ namespace GUIEngine /** Whether to show a bounding box around this widget (used for sections) */ bool m_show_bounding_box; + /** Show a 'locked' badge on this widget */ + bool m_lock_badge; + + /** Show a 'good' badge on this widget */ + bool m_okay_badge; + + /** Set to false if widget is something that should not receieve focus */ + bool m_focusable; + /** Used in two cases : 1) For 'placeholder' divisions; at the time the layout is created, there is nothing to place there yet, but we know there eventually will. So in this case pass 'true' to the diff --git a/src/guiengine/widgets/dynamic_ribbon_widget.cpp b/src/guiengine/widgets/dynamic_ribbon_widget.cpp index d954faa6a..70447a304 100644 --- a/src/guiengine/widgets/dynamic_ribbon_widget.cpp +++ b/src/guiengine/widgets/dynamic_ribbon_widget.cpp @@ -220,11 +220,11 @@ void DynamicRibbonWidget::setSubElements() // set size to get proper ratio (as most textures are saved scaled down to 256x256) icon->m_properties[PROP_WIDTH] = m_properties[PROP_CHILD_WIDTH]; icon->m_properties[PROP_HEIGHT] = m_properties[PROP_CHILD_HEIGHT]; - if (m_text == "all") icon->m_text = " "; + + if (m_text == "all") icon->m_text = " "; // FIXME: what's that?? // std::cout << "ribbon text = " << m_properties[PROP_TEXT].c_str() << std::endl; - icon->m_type = WTYPE_ICON_BUTTON; ribbon->m_children.push_back( icon ); } m_children.push_back( ribbon ); @@ -234,12 +234,14 @@ void DynamicRibbonWidget::setSubElements() } // ----------------------------------------------------------------------------- -void DynamicRibbonWidget::addItem( const irr::core::stringw& user_name, const std::string& code_name, const std::string& image_file ) +void DynamicRibbonWidget::addItem( const irr::core::stringw& user_name, const std::string& code_name, + const std::string& image_file, const bool locked ) { ItemDescription desc; desc.m_user_name = user_name; desc.m_code_name = code_name; desc.m_sshot_file = image_file; + desc.m_locked = locked; m_items.push_back(desc); } @@ -248,7 +250,7 @@ void DynamicRibbonWidget::clearItems() { m_items.clear(); } - +// ----------------------------------------------------------------------------- void DynamicRibbonWidget::elementRemoved() { Widget::elementRemoved(); @@ -566,8 +568,6 @@ void DynamicRibbonWidget::updateItemDisplay() { IconButtonWidget* icon = dynamic_cast(&row.m_children[i]); assert(icon != NULL); - IGUIButton* button = icon->getIrrlichtElement(); - assert(button != NULL); int col_scroll = i + m_scroll_offset; while (col_scroll > max_scroll) col_scroll -= max_scroll+1; @@ -576,20 +576,19 @@ void DynamicRibbonWidget::updateItemDisplay() if (icon_id < item_amount) { - std::string track_sshot = m_items[icon_id].m_sshot_file; - button->setImage( GUIEngine::getDriver()->getTexture( track_sshot.c_str() )); - button->setPressedImage( GUIEngine::getDriver()->getTexture( track_sshot.c_str()) ); + std::string item_icon = m_items[icon_id].m_sshot_file; + icon->setImage( item_icon.c_str() ); icon->m_properties[PROP_ID] = m_items[icon_id].m_code_name; icon->m_text = m_items[icon_id].m_user_name; + icon->m_lock_badge = m_items[icon_id].m_locked; row.setLabel(i, m_items[icon_id].m_user_name); } else { - button->setImage( GUIEngine::getDriver()->getTexture( (file_manager->getGUIDir() + "/main_help.png").c_str() ) ); - button->setPressedImage( GUIEngine::getDriver()->getTexture( (file_manager->getGUIDir() + "/main_help.png").c_str() ) ); - icon->m_properties[PROP_ID] = "gui/main_help.png"; + icon->setImage( "/gui/main_help.png" ); + icon->m_properties[PROP_ID] = "?"; } } // next column } // next row diff --git a/src/guiengine/widgets/dynamic_ribbon_widget.hpp b/src/guiengine/widgets/dynamic_ribbon_widget.hpp index a5fa76105..42dd8d59b 100644 --- a/src/guiengine/widgets/dynamic_ribbon_widget.hpp +++ b/src/guiengine/widgets/dynamic_ribbon_widget.hpp @@ -46,6 +46,7 @@ namespace GUIEngine irr::core::stringw m_user_name; std::string m_code_name; std::string m_sshot_file; + bool m_locked; }; /** A dynamic ribbon (builds upon RibbonWidget, adding dynamic contents creation and sizing, scrolling, multiple-row @@ -147,8 +148,14 @@ namespace GUIEngine ptr_vector m_rows; /** Dynamically add an item to the ribbon's list of items (will not be visible until you - call 'updateItemDisplay' or 'add') */ - void addItem( const irr::core::stringw& user_name, const std::string& code_name, const std::string& image_file ); + * call 'updateItemDisplay' or 'add'). + * + * \param user_name The name that will shown to the user (may be translated) + * \param code_name The non-translated internal name used to uniquely identify this item. + * \param image_name A path to a texture that will the icon of this item (path relative to data dir, just like PROP_ICON) + * \param locked Whether to add a lock icon to this item (does nop actual locing, only adds an icon) + */ + void addItem( const irr::core::stringw& user_name, const std::string& code_name, const std::string& image_file, const bool locked=false ); /** Clears all items added through 'addItem'. You can then add new items with 'addItem' and call 'updateItemDisplay' to update the display. */ diff --git a/src/guiengine/widgets/icon_button_widget.cpp b/src/guiengine/widgets/icon_button_widget.cpp index e09fc9a0b..050222b1a 100644 --- a/src/guiengine/widgets/icon_button_widget.cpp +++ b/src/guiengine/widgets/icon_button_widget.cpp @@ -26,47 +26,33 @@ using namespace irr::gui; // ----------------------------------------------------------------------------- IconButtonWidget::IconButtonWidget(const bool clickable) { - IconButtonWidget::clickable = clickable; - label = NULL; + m_clickable = clickable; + m_label = NULL; m_type = WTYPE_ICON_BUTTON; + m_texture = NULL; + m_focusable = clickable; } // ----------------------------------------------------------------------------- void IconButtonWidget::add() { // ---- Icon - ITexture* texture = GUIEngine::getDriver()->getTexture((file_manager->getDataDir() + "/" +m_properties[PROP_ICON]).c_str()); - assert(texture != NULL); - const int texture_w = texture->getSize().Width, texture_h = texture->getSize().Height; + m_texture = GUIEngine::getDriver()->getTexture((file_manager->getDataDir() + "/" +m_properties[PROP_ICON]).c_str()); + assert(m_texture != NULL); + m_texture_w = m_texture->getSize().Width; + m_texture_h = m_texture->getSize().Height; // irrlicht widgets don't support scaling while keeping aspect ratio // so, happily, let's implement it ourselves - const int x_gap = (int)((float)w - (float)texture_w * (float)h / texture_h); + const int x_gap = (int)((float)w - (float)m_texture_w * (float)h / m_texture_h); - rect widget_size; - if (clickable) - { - widget_size = rect(x + x_gap/2, y, x + w - x_gap/2, y + h); + rect widget_size = rect(x + x_gap/2, y, x + w - x_gap/2, y + h); + //std::cout << "Creating a IGUIButton " << widget_size.UpperLeftCorner.X << ", " << widget_size.UpperLeftCorner.Y << + //" : " << widget_size.getWidth() << "x" << widget_size.getHeight() << std::endl; + + IGUIButton* btn = GUIEngine::getGUIEnv()->addButton(widget_size, m_parent, (m_clickable ? getNewID() : getNewNoFocusID()), L""); - //MyGUIButton* btn = new MyGUIButton(GUIEngine::getGUIEnv(), m_parent, getNewID(), widget_size, true); - IGUIButton* btn = GUIEngine::getGUIEnv()->addButton(widget_size, m_parent, getNewID(), L""); - btn->setUseAlphaChannel(true); - btn->setImage(texture); - btn->setScaleImage(true); - //btn->setDrawBorder(false); - btn->setTabStop(true); - m_element = btn; - } - else - { - widget_size = rect(x + x_gap/2, y, x + w - x_gap/2, y + h); - - IGUIImage* btn = GUIEngine::getGUIEnv()->addImage(widget_size, m_parent, getNewNoFocusID()); - m_element = btn; - btn->setUseAlphaChannel(true); - btn->setImage(texture); - btn->setTabStop(false); - btn->setScaleImage(true); - } + btn->setTabStop(m_clickable); + m_element = btn; id = m_element->getID(); // ---- label if any @@ -75,40 +61,39 @@ void IconButtonWidget::add() { widget_size = rect(x, y + h, x + w, y + h*2); - label = GUIEngine::getGUIEnv()->addStaticText(message.c_str(), widget_size, false, false /* word wrap */, m_parent); - label->setTextAlignment(EGUIA_CENTER, EGUIA_UPPERLEFT); - label->setTabStop(false); + m_label = GUIEngine::getGUIEnv()->addStaticText(message.c_str(), widget_size, false, false /* word wrap */, m_parent); + m_label->setTextAlignment(EGUIA_CENTER, EGUIA_UPPERLEFT); + m_label->setTabStop(false); } // ---- IDs id = m_element->getID(); - if(clickable) m_element->setTabOrder(id); + if (m_clickable) m_element->setTabOrder(id); m_element->setTabGroup(false); - - /* - IGUISpriteBank* sprite_bank = GUIEngine::getGUIEnv()->getSkin()->getSpriteBank(); - // GUIEngine::getDriver()->makeColorKeyTexture(GUIEngine::getDriver()->getTexture("irrlichtlogo2.png"), position2di(0,0)); - sprite_bank->addTexture( GUIEngine::getDriver()->getTexture("irrlichtlogo2.png") ); - - SGUISprite sprite; - sprite.frameTime = 3000; - SGUISpriteFrame frame; - core::array >& rectangles = sprite_bank->getPositions(); - rectangles.push_back(rect(0,0,128,128)); - frame.rectNumber = rectangles.size()-1; - frame.textureNumber = sprite_bank->getTextureCount() - 1; - sprite.Frames.push_back(frame); - sprite_bank->getSprites().push_back(sprite); - - button->setSpriteBank(sprite_bank); - button->setSprite(EGBS_BUTTON_UP, sprite_bank->getSprites().size()-1); - button->setSprite(EGBS_BUTTON_DOWN, sprite_bank->getSprites().size()-1); - */ +} +// ----------------------------------------------------------------------------- +/** \precondition At the moment, the new texture must have the same aspct ratio as the previous one since the object will not + * be modified to fit a different aspect ratio + */ +void IconButtonWidget::setImage(const char* path_to_texture) +{ + m_properties[PROP_ICON] = path_to_texture; + m_texture = GUIEngine::getDriver()->getTexture((file_manager->getDataDir() + "/" + m_properties[PROP_ICON]).c_str()); + + if (m_texture == NULL) + { + // texture not found, try with absolute path + m_texture = GUIEngine::getDriver()->getTexture(m_properties[PROP_ICON].c_str()); + } + assert(m_texture != NULL); + + m_texture_w = m_texture->getSize().Width; + m_texture_h = m_texture->getSize().Height; } // ----------------------------------------------------------------------------- void IconButtonWidget::setLabel(std::string new_label) { - if (label == NULL) return; + if (m_label == NULL) return; - label->setText( stringw(new_label.c_str()).c_str() ); + m_label->setText( stringw(new_label.c_str()).c_str() ); } diff --git a/src/guiengine/widgets/icon_button_widget.hpp b/src/guiengine/widgets/icon_button_widget.hpp index 6bbbe5f64..0d9ba985c 100644 --- a/src/guiengine/widgets/icon_button_widget.hpp +++ b/src/guiengine/widgets/icon_button_widget.hpp @@ -31,16 +31,25 @@ namespace GUIEngine See guiengine/engine.hpp for a detailed overview */ class IconButtonWidget : public Widget { - bool clickable; - irr::gui::IGUIStaticText* label; + friend class Skin; + + bool m_clickable; + irr::gui::IGUIStaticText* m_label; + irr::video::ITexture* m_texture; + int m_texture_w, m_texture_h; public: + IconButtonWidget(const bool clickable=true); virtual ~IconButtonWidget() {} - void add(); + /** Callback called when this widget needs to be added (see base class Widget) */ + virtual void add(); /** Change the text label if there is a label (label won't be added if there initially wasn't one) */ void setLabel(std::string new_label); + + /** Change the texture used for this icon. The path is relative to the data directory, just like PROP_ICON. */ + void setImage(const char* path_to_texture); }; } diff --git a/src/guiengine/widgets/ribbon_widget.cpp b/src/guiengine/widgets/ribbon_widget.cpp index 62308c671..0e73b92a6 100644 --- a/src/guiengine/widgets/ribbon_widget.cpp +++ b/src/guiengine/widgets/ribbon_widget.cpp @@ -74,7 +74,7 @@ void RibbonWidget::add() int free_h_space = w - total_needed_space; - int biggest_y = 0; + //int biggest_y = 0; const int button_y = 10; float global_zoom = 1; @@ -85,27 +85,26 @@ void RibbonWidget::add() const int one_button_space = (int)round((float)w / (float)subbuttons_amount); // ---- add children - for(int i=0; i subsize = rect(widget_x - one_button_space/2+2, 0, widget_x + one_button_space/2-2, h); stringw& message = m_children[i].m_text; - if(m_children[i].m_type == WTYPE_BUTTON) + if (m_children[i].m_type == WTYPE_BUTTON) { subbtn = GUIEngine::getGUIEnv()->addButton(subsize, btn, getNewNoFocusID(), message.c_str(), L""); subbtn->setTabStop(false); subbtn->setTabGroup(false); } - else if(m_children[i].m_type == WTYPE_ICON_BUTTON) + else if (m_children[i].m_type == WTYPE_ICON_BUTTON) { rect icon_part = rect(15, 0, @@ -145,34 +144,46 @@ void RibbonWidget::add() m_children[i].m_element = subbtn; } - else if(m_children[i].m_type == WTYPE_ICON_BUTTON) + else if (m_children[i].m_type == WTYPE_ICON_BUTTON) { - const bool has_label = m_children[i].m_text.size() > 0; - // how much space to keep for the label under the button + const bool has_label = m_children[i].m_text.size() > 0; const int needed_space_under_button = has_label ? 30 : 10; // quite arbitrary for now + + // For now, the image stretches to keep the aspect ratio of the widget (FIXME, doesn't work) + //float imageRatio = (float)m_children[i].w/(float)m_children[i].h; + + // size of the image + video::ITexture* image = GUIEngine::getDriver()->getTexture((file_manager->getDataDir() + "/" + m_children[i].m_properties[PROP_ICON]).c_str()); + float image_h = image->getSize().Height; + float image_w = image->getSize().Width; + //float image_w = image_h*imageRatio; + // if button too high to fit, scale down float zoom = global_zoom; - while(button_y + m_children[i].h*zoom + needed_space_under_button > h) zoom -= 0.01f; + while (button_y + image_h*zoom + needed_space_under_button > h) zoom -= 0.01f; // ---- add bitmap button part - const float image_w = m_children[i].w*zoom; - rect subsize = rect(widget_x - (int)(image_w/2.0f), button_y, - widget_x + (int)(image_w/2.0f), button_y + (int)(m_children[i].h*zoom)); + //rect subsize = rect(widget_x - (int)(image_w/2.0f), button_y, + // widget_x + (int)(image_w/2.0f), button_y + (int)(m_children[i].h*zoom)); - //subbtn = new MyGUIButton(GUIEngine::getGUIEnv(), btn, getNewNoFocusID(), subsize, true); - subbtn = GUIEngine::getGUIEnv()->addButton(subsize, btn, getNewNoFocusID(), L""); - subbtn->setScaleImage(true); + m_children[i].x = widget_x - (int)(image_w*zoom/2.0f); + m_children[i].y = button_y; + m_children[i].w = image_w*zoom; + m_children[i].h = image_h*zoom; + - m_children[i].m_element = subbtn; - subbtn->setUseAlphaChannel(true); - subbtn->setImage( GUIEngine::getDriver()->getTexture((file_manager->getDataDir() + "/" + m_children[i].m_properties[PROP_ICON]).c_str()) ); + m_children.get(i)->m_parent = btn; + m_children.get(i)->add(); + //subbtn->setUseAlphaChannel(true); + //subbtn->setImage( GUIEngine::getDriver()->getTexture((file_manager->getDataDir() + "/" + m_children[i].m_properties[PROP_ICON]).c_str()) ); // ---- label part - if(has_label) + /* + if (has_label) { subsize = rect(widget_x - one_button_space/2, - (int)((button_y + m_children[i].h)*zoom) + 5 /* leave 5 pixels between button and label */, + (int)((button_y + m_children[i].h)*zoom) + 5, // leave 5 pixels between button and label widget_x + (int)(one_button_space/2.0f), h); stringw& message = m_children[i].m_text; @@ -186,9 +197,9 @@ void RibbonWidget::add() const int final_y = subsize.getHeight() + label->getTextHeight(); if(final_y > biggest_y) biggest_y = final_y; } - - subbtn->setTabStop(false); - subbtn->setTabGroup(false); + */ + //subbtn->setTabStop(false); + //subbtn->setTabGroup(false); } else { @@ -196,7 +207,7 @@ void RibbonWidget::add() } - m_children[i].id = subbtn->getID(); + //m_children[i].id = subbtn->getID(); m_children[i].m_event_handler = this; }// next sub-button diff --git a/src/states_screens/challenges.cpp b/src/states_screens/challenges.cpp index 069a528fd..a22a3e88d 100644 --- a/src/states_screens/challenges.cpp +++ b/src/states_screens/challenges.cpp @@ -67,7 +67,7 @@ namespace GUIEngine { sprintf(buffer, "challenge%i", n); w->addItem(activeChallenges[n]->getName() + L"\n" + activeChallenges[n]->getChallengeDescription(), - buffer, file_manager->getGUIDir() + "/challenge.png"); + buffer, "/gui/challenge.png"); } for (int n=0; ngetKartById(group[n]); if (prop->getIdent() == default_kart) { - std::string icon_path = file_manager->getDataDir() ; - icon_path += "/karts/" + prop->getIdent() + "/" + prop->getIconFile(); + std::string icon_path = "/karts/" + prop->getIdent() + "/" + prop->getIconFile(); w->addItem(prop->getName(), prop->getIdent().c_str(), icon_path.c_str()); //std::cout << "Add item : " << prop->getIdent().c_str() << std::endl; break; @@ -914,15 +913,14 @@ void KartSelectionScreen::init() const KartProperties* prop = kart_properties_manager->getKartById(group[n]); if (prop->getIdent() != default_kart) { - std::string icon_path = file_manager->getDataDir() ; - icon_path += "/karts/" + prop->getIdent() + "/" + prop->getIconFile(); + std::string icon_path = "/karts/" + prop->getIdent() + "/" + prop->getIconFile(); w->addItem(prop->getName(), prop->getIdent().c_str(), icon_path.c_str()); //std::cout << "Add item : " << prop->getIdent().c_str() << std::endl; } } // add random - w->addItem(_("Random Kart"), "randomkart", file_manager->getGUIDir()+"/random_kart.png"); + w->addItem(_("Random Kart"), "randomkart", "/gui/random_kart.png"); /* @@ -1090,8 +1088,7 @@ void KartSelectionScreen::eventCallback(Widget* widget, const std::string& name, { const KartProperties* prop = kart_properties_manager->getKartById(n); - std::string icon_path = file_manager->getDataDir() ; - icon_path += "/karts/" + prop->getIdent() + "/" + prop->getIconFile(); + std::string icon_path = "/karts/" + prop->getIdent() + "/" + prop->getIconFile(); w->addItem(prop->getName().c_str(), prop->getIdent().c_str(), icon_path.c_str()); } } @@ -1104,13 +1101,12 @@ void KartSelectionScreen::eventCallback(Widget* widget, const std::string& name, { const KartProperties* prop = kart_properties_manager->getKartById(group[n]); - std::string icon_path = file_manager->getDataDir() ; - icon_path += "/karts/" + prop->getIdent() + "/" + prop->getIconFile(); + std::string icon_path = "/karts/" + prop->getIdent() + "/" + prop->getIconFile(); w->addItem(prop->getName().c_str(), prop->getIdent().c_str(), icon_path.c_str()); } } // add random - w->addItem(_("Random Kart"), "randomkart", file_manager->getGUIDir()+"/random_kart.png"); + w->addItem(_("Random Kart"), "randomkart", "/gui/random_kart.png"); w->updateItemDisplay(); diff --git a/src/states_screens/options_screen_av.cpp b/src/states_screens/options_screen_av.cpp index 83b94eb1d..9c2792198 100644 --- a/src/states_screens/options_screen_av.cpp +++ b/src/states_screens/options_screen_av.cpp @@ -88,16 +88,11 @@ void OptionsScreenAV::init() #define ABOUT_EQUAL(a , b) (fabsf( a - b ) < 0.01) - if( ABOUT_EQUAL( ratio, (5.0f/4.0f) ) ) - res->addItem(name, name, file_manager->getDataDir() + "/gui/screen54.png"); - else if( ABOUT_EQUAL( ratio, (4.0f/3.0f) ) ) - res->addItem(name, name, file_manager->getDataDir() + "/gui/screen43.png"); - else if( ABOUT_EQUAL( ratio, (16.0f/10.0f) ) ) - res->addItem(name, name, file_manager->getDataDir() + "/gui/screen1610.png"); - else if( ABOUT_EQUAL( ratio, (5.0f/3.0f) ) ) - res->addItem(name, name, file_manager->getDataDir() + "/gui/screen53.png"); - else if( ABOUT_EQUAL( ratio, (3.0f/2.0f) ) ) - res->addItem(name, name, file_manager->getDataDir() + "/gui/screen32.png"); + if (ABOUT_EQUAL( ratio, (5.0f/4.0f) )) res->addItem(name, name, "/gui/screen54.png"); + else if (ABOUT_EQUAL( ratio, (4.0f/3.0f) )) res->addItem(name, name, "/gui/screen43.png"); + else if (ABOUT_EQUAL( ratio, (16.0f/10.0f))) res->addItem(name, name, "/gui/screen1610.png"); + else if (ABOUT_EQUAL( ratio, (5.0f/3.0f) )) res->addItem(name, name, "/gui/screen53.png"); + else if (ABOUT_EQUAL( ratio, (3.0f/2.0f) )) res->addItem(name, name, "/gui/screen32.png"); else { std::cout << "Unknown screen size ratio : " << ratio << std::endl; diff --git a/src/states_screens/options_screen_input.cpp b/src/states_screens/options_screen_input.cpp index 17a9b183e..c101ef80a 100644 --- a/src/states_screens/options_screen_input.cpp +++ b/src/states_screens/options_screen_input.cpp @@ -103,15 +103,14 @@ void OptionsScreenInput::init() for (int i=0; igetDeviceList()->getKeyboardConfig(i); + //KeyboardConfig *config = input_manager->getDeviceList()->getKeyboardConfig(i); std::ostringstream kbname; kbname << "keyboard" << i; const std::string internal_name = kbname.str(); - devices->addItem(StringUtils::insertValues(_("Keyboard %i"), i), internal_name, - file_manager->getDataDir() + "/gui/keyboard.png"); + devices->addItem(StringUtils::insertValues(_("Keyboard %i"), i), internal_name, "/gui/keyboard.png"); } const int gpad_config_count = input_manager->getDeviceList()->getGamePadConfigAmount(); @@ -128,8 +127,7 @@ void OptionsScreenInput::init() gpname << "gamepad" << i; const std::string internal_name = gpname.str(); - const std::string iconpath = file_manager->getDataDir() + "/gui/gamepad.png"; - devices->addItem(name, internal_name, iconpath); + devices->addItem(name, internal_name, "/gui/gamepad.png"); } } diff --git a/src/states_screens/race_setup_screen.cpp b/src/states_screens/race_setup_screen.cpp index cc5b5c953..1328c4791 100644 --- a/src/states_screens/race_setup_screen.cpp +++ b/src/states_screens/race_setup_screen.cpp @@ -156,31 +156,26 @@ void RaceSetupScreen::init() { // FIXME: find a nice name than 'regular race' -.- w2->addItem( _("Regular Race\nAll blows allowed, so catch weapons and make clever use of them!"), - "normal", - file_manager->getDataDir() + "/gui/mode_normal.png"); + "normal", "/gui/mode_normal.png"); w2->addItem( _("Time Trial\nContains no powerups, so only your driving skills matter!"), - "timetrial", - file_manager->getDataDir() + "/gui/mode_tt.png"); + "timetrial", "/gui/mode_tt.png"); if (unlock_manager->isLocked("followtheleader")) { - w2->addItem( _("Locked!\nFulfill challenges to gain access to locked areas"), - "locked", - file_manager->getDataDir() + "textures/gui_lock.png"); + w2->addItem( _("Locked : solve active challenges to gain access to more!"), + "locked", "/gui/mode_ftl.png", true); } else { w2->addItem( _("Follow the Leader\nrun for second place, as the last kart will be disqualified every time the counter hits zero. Beware : going in front of the leader will get you eliminated too!"), - "ftl", - file_manager->getDataDir() + "/gui/mode_ftl.png"); + "ftl", "/gui/mode_ftl.png", false); } if (race_manager->getNumPlayers() > 1) { w2->addItem( _("3-Strikes Battle\nonly in multiplayer games. Hit others with weapons until they lose all their lives."), - "3strikes", - file_manager->getDataDir() + "/gui/mode_3strikes.png"); + "3strikes", "/gui/mode_3strikes.png"); } m_inited = true; diff --git a/src/states_screens/tracks_screen.cpp b/src/states_screens/tracks_screen.cpp index d8e9f4100..b7b97be80 100644 --- a/src/states_screens/tracks_screen.cpp +++ b/src/states_screens/tracks_screen.cpp @@ -79,24 +79,33 @@ void TracksScreen::init() w->clearItems(); const int trackAmount = track_manager->getNumberOfTracks(); - bool hasLockedTracks = false; + //bool hasLockedTracks = false; for (int n=0; ngetTrack(n); + /* if (unlock_manager->isLocked(curr->getIdent())) { hasLockedTracks = true; continue; } - w->addItem(curr->getName(), curr->getIdent(), curr->getScreenshotFile()); + */ + if (unlock_manager->isLocked(curr->getIdent())) + { + w->addItem( _("Locked : solve active challenges to gain access to more!"), "locked", curr->getScreenshotFile(), true ); + } + else + { + w->addItem( curr->getName(), curr->getIdent(), curr->getScreenshotFile(), false ); + } } - w->addItem(_("Random Track"), "random_track", file_manager->getGUIDir() + "/track_random.png"); - + w->addItem(_("Random Track"), "random_track", "/gui/track_random.png"); +/* if (hasLockedTracks) { w->addItem(_("Locked Tracks"), "Lock", "textures/gui_lock.png"); } - + */ w->updateItemDisplay(); }