diff --git a/lib/irrlicht/include/IGUIStaticText.h b/lib/irrlicht/include/IGUIStaticText.h index 5c9e10386..f69441fea 100644 --- a/lib/irrlicht/include/IGUIStaticText.h +++ b/lib/irrlicht/include/IGUIStaticText.h @@ -9,6 +9,7 @@ #include "SColor.h" #include +#include #include namespace irr @@ -125,6 +126,7 @@ namespace gui virtual void setUseGlyphLayoutsOnly(bool gls_only) = 0; virtual bool useGlyphLayoutsOnly() const = 0; virtual void setMouseCallback(std::function cb) {} + virtual s32 getCluster(int x, int y, std::shared_ptr* out_orig_str) { return -1; } }; diff --git a/lib/irrlicht/source/Irrlicht/CGUIStaticText.cpp b/lib/irrlicht/source/Irrlicht/CGUIStaticText.cpp index ade17cf19..be34b4f25 100644 --- a/lib/irrlicht/source/Irrlicht/CGUIStaticText.cpp +++ b/lib/irrlicht/source/Irrlicht/CGUIStaticText.cpp @@ -393,6 +393,89 @@ bool CGUIStaticText::OnEvent(const SEvent& event) return IGUIElement::OnEvent(event); } + +s32 CGUIStaticText::getCluster(int x, int y, std::shared_ptr* out_orig_str) +{ + core::position2di p; + p.X = x; + p.Y = y; + if (p.X < 0 || p.Y < 0) + return -1; + + if (m_glyph_layouts.empty()) + return -1; + + IGUIFont* font = getActiveFont(); + std::vector width_per_line = gui::getGlyphLayoutsWidthPerLine( + m_glyph_layouts, font->getInverseShaping(), font->getScale()); + if (width_per_line.empty()) + return -1; + + // Check if the line is RTL + core::rect position = getAbsolutePosition(); + bool rtl = (m_glyph_layouts[0].flags & gui::GLF_RTL_LINE) != 0; + int offset = 0; + int cur_line = 0; + if (rtl) + offset = (s32)(position.getWidth() - width_per_line[cur_line]); + + float next_line_height = font->getHeightPerLine(); + if (width_per_line.size() > 1 && + width_per_line.size() * next_line_height > position.getHeight()) + { + next_line_height = (float)position.getHeight() / + (float)width_per_line.size(); + } + + int idx = -1; + core::recti r; + r.UpperLeftCorner.X = r.LowerRightCorner.X = offset; + r.LowerRightCorner.Y = (int)next_line_height; + bool line_changed = false; + for (unsigned i = 0; i < m_glyph_layouts.size(); i++) + { + const GlyphLayout& glyph_layout = m_glyph_layouts[i]; + if ((glyph_layout.flags & GLF_NEWLINE) != 0) + { + r.UpperLeftCorner.Y += (int)next_line_height; + r.LowerRightCorner.Y += (int)next_line_height; + cur_line++; + line_changed = true; + continue; + } + if (line_changed) + { + line_changed = false; + rtl = (glyph_layout.flags & gui::GLF_RTL_LINE) != 0; + offset = 0; + if (rtl) + { + offset = (s32) + (position.getWidth() - width_per_line[cur_line]); + } + r.UpperLeftCorner.X = r.LowerRightCorner.X = offset; + } + r.LowerRightCorner.X += int( + (float)glyph_layout.x_advance * font->getInverseShaping() * + font->getScale()); + if (r.isPointInside(p)) + { + idx = i; + break; + } + } + if (idx == -1) + return -1; + + std::shared_ptr s = m_glyph_layouts[idx].orig_string; + unsigned cluster = m_glyph_layouts[idx].cluster.front(); + if (cluster > s->size()) + return -1; + *out_orig_str = s; + return cluster; +} + + } // end namespace gui } // end namespace irr diff --git a/lib/irrlicht/source/Irrlicht/CGUIStaticText.h b/lib/irrlicht/source/Irrlicht/CGUIStaticText.h index c1d3ee837..9b7facc98 100644 --- a/lib/irrlicht/source/Irrlicht/CGUIStaticText.h +++ b/lib/irrlicht/source/Irrlicht/CGUIStaticText.h @@ -113,6 +113,7 @@ namespace gui //! called if an event happened. virtual bool OnEvent(const SEvent& event); virtual void setMouseCallback(std::function cb) { m_callback = cb; } + virtual s32 getCluster(int x, int y, std::shared_ptr* out_orig_str); private: //! Breaks the single text line. diff --git a/src/states_screens/online/networking_lobby.cpp b/src/states_screens/online/networking_lobby.cpp index 2aded25a5..eb0d9706e 100644 --- a/src/states_screens/online/networking_lobby.cpp +++ b/src/states_screens/online/networking_lobby.cpp @@ -264,81 +264,11 @@ void NetworkingLobby::init() { if (mouse.Event == EMIE_LMOUSE_PRESSED_DOWN) { - core::position2di p; - p.X = mouse.X - text->getAbsolutePosition().UpperLeftCorner.X; - p.Y = mouse.Y - text->getAbsolutePosition().UpperLeftCorner.Y; - if (p.X < 0 || p.Y < 0) - return false; - - const std::vector& gls = text->getGlyphLayouts(); - if (gls.empty()) - return false; - - gui::IGUIFont* font = GUIEngine::getFont(); - auto width_per_line = gui::getGlyphLayoutsWidthPerLine(gls, - font->getInverseShaping(), font->getScale()); - if (width_per_line.empty()) - return false; - - // Check if the line is RTL - auto position = text->getAbsolutePosition(); - bool rtl = (gls[0].flags & gui::GLF_RTL_LINE) != 0; - int offset = 0; - int cur_line = 0; - if (rtl) - offset = (s32)(position.getWidth() - width_per_line[cur_line]); - - float next_line_height = font->getHeightPerLine(); - if (width_per_line.size() > 1 && - width_per_line.size() * next_line_height > position.getHeight()) - { - next_line_height = (float)position.getHeight() / - (float)width_per_line.size(); - } - - int idx = -1; - core::recti r; - r.UpperLeftCorner.X = r.LowerRightCorner.X = offset; - r.LowerRightCorner.Y = (int)next_line_height; - bool line_changed = false; - for (unsigned i = 0; i < gls.size(); i++) - { - const GlyphLayout& glyph_layout = gls[i]; - if ((glyph_layout.flags & GLF_NEWLINE) != 0) - { - r.UpperLeftCorner.Y += (int)next_line_height; - r.LowerRightCorner.Y += (int)next_line_height; - cur_line++; - line_changed = true; - continue; - } - if (line_changed) - { - line_changed = false; - rtl = (glyph_layout.flags & gui::GLF_RTL_LINE) != 0; - offset = 0; - if (rtl) - { - offset = (s32) - (position.getWidth() - width_per_line[cur_line]); - } - r.UpperLeftCorner.X = r.LowerRightCorner.X = offset; - } - r.LowerRightCorner.X += int( - (float)glyph_layout.x_advance * font->getInverseShaping() * - font->getScale()); - if (r.isPointInside(p)) - { - idx = i; - break; - } - } - if (idx == -1) - return false; - - auto s = gls[idx].orig_string; - unsigned cluster = gls[idx].cluster.front(); - if (cluster > s->size()) + std::shared_ptr s; + int cluster = text->getCluster( + mouse.X - text->getAbsolutePosition().UpperLeftCorner.X, + mouse.Y - text->getAbsolutePosition().UpperLeftCorner.Y, &s); + if (cluster == -1 || (unsigned)cluster > s->size()) return false; size_t start = s->substr(0, cluster).rfind(U'\n'); @@ -351,10 +281,9 @@ void NetworkingLobby::init() end = s->size(); else end += cluster - start; - if (idx == -1) - return false; + std::u32string substr = s->substr(start, end); - int local_pos = (int)cluster - (int)start; + int local_pos = cluster - (int)start; if ((size_t)local_pos > substr.size()) return false;