diff --git a/src/guiengine/message_queue.cpp b/src/guiengine/message_queue.cpp index a6b2f402c..64173b1da 100644 --- a/src/guiengine/message_queue.cpp +++ b/src/guiengine/message_queue.cpp @@ -27,10 +27,7 @@ #include "modes/profile_world.hpp" #include "utils/synchronised.hpp" -#include "IGUIElement.h" -#include "IGUIEnvironment.h" -#include "IGUIStaticText.h" - +#include "GlyphLayout.h" #include using namespace GUIEngine; @@ -96,16 +93,17 @@ private: * or friend-message::neutral. */ std::string m_render_type; - /** The text label, can do linebreak if needed. */ - gui::IGUIStaticText* m_text; + /** The text layout, can do linebreak if needed. */ + std::vector m_gls; + /** Drawing rectangle of text layout. */ + core::recti m_text_rect; public: TextMessage(MessageQueue::MessageType mt, const core::stringw &message) : Message(5.0f) { m_message_type = mt; m_message = message; - m_text = NULL; assert(mt != MessageQueue::MT_PROGRESS); if (mt == MessageQueue::MT_ACHIEVEMENT) m_render_type = "achievement-message::neutral"; @@ -119,8 +117,6 @@ public: // ------------------------------------------------------------------------ ~TextMessage() { - assert(m_text != NULL); - m_text->drop(); } // ------------------------------------------------------------------------ /** Returns the type of the message.*/ @@ -130,39 +126,75 @@ public: /** Init the message text, do linebreak as required. */ virtual void init() { - if (m_text) - m_text->drop(); const GUIEngine::BoxRenderParams &brp = GUIEngine::getSkin()->getBoxRenderParams(m_render_type); const unsigned width = irr_driver->getActualScreenSize().Width; const unsigned height = irr_driver->getActualScreenSize().Height; - const unsigned max_width = width - (brp.m_left_border + - brp.m_right_border); - m_text = - GUIEngine::getGUIEnv()->addStaticText(m_message.c_str(), - core::recti(0, 0, max_width, height)); - core::dimension2du dim(m_text->getTextWidth(), - m_text->getTextHeight()); - dim.Width += brp.m_left_border + brp.m_right_border; + gui::IGUIFont* font = GUIEngine::getFont(); + font->initGlyphLayouts(m_message, m_gls); + // Reserve space for 5 lines of text, it will occupy the circle + const int max_width = width - (brp.m_left_border + + brp.m_right_border) - (font->getHeightPerLine() * 5); + if (max_width < 0) + { + m_display_timer = -1; + return; + } - int leftIconSize = dim.Height + 10; - int x = (width - dim.Width) / 2; - int y = height - int(1.5f * dim.Height); - m_area = irr::core::recti(x, y, x + dim.Width, y + dim.Height); - m_text->setRelativePosition(irr::core::recti(x + leftIconSize, y, - x + dim.Width - 10, y + dim.Height)); - m_text->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER); - m_text->grab(); - m_text->remove(); + gui::breakGlyphLayouts(m_gls, max_width, font->getInverseShaping(), + font->getScale()); + core::dimension2du dim = gui::getGlyphLayoutsDimension(m_gls, + font->getHeightPerLine(), font->getInverseShaping(), + font->getScale()); + + if ((int)dim.Height > font->getHeightPerLine() * 5) + { + // Max 5 lines to prevent too long message from network chat + int newline_count = 0; + for (unsigned i = 0; i < m_gls.size(); i++) + { + if (m_gls[i].flags & gui::GLF_NEWLINE) + { + if (++newline_count >= 5) + { + m_gls.erase(m_gls.begin() + i, m_gls.end()); + dim.Height = font->getHeightPerLine() * 5; + break; + } + } + } + } + + int left_icon_size = dim.Height; + int total_width = dim.Width + brp.m_left_border + brp.m_right_border + + left_icon_size; + int x = (width - total_width) / 2; + int y = height - int(dim.Height) - font->getHeightPerLine() / 2; + + if (x < 0 || y < 0) + { + m_gls.clear(); + m_display_timer = -1; + return; + } + + m_area = irr::core::recti(x, y, x + total_width, y + dim.Height); + m_text_rect = core::recti(x, y, x + left_icon_size + total_width, + y + dim.Height); } // ------------------------------------------------------------------------ /** Draw the message. */ virtual void draw(float dt) { + if (m_gls.empty()) + { + Message::draw(dt); + return; + } Message::draw(dt); GUIEngine::getSkin()->drawMessage(g_container, m_area, m_render_type); - assert(m_text != NULL); - m_text->draw(); + GUIEngine::getFont()->draw(m_gls, m_text_rect, + GUIEngine::getSkin()->getColor("text::neutral"), true/*hcenter*/); } // ------------------------------------------------------------------------ virtual void remove() { delete this; }