Use a better way to erase top text

This commit is contained in:
Benau 2019-06-11 15:05:46 +08:00
parent 0fdbe5d34f
commit 44796bc8c0
5 changed files with 89 additions and 171 deletions

View File

@ -59,6 +59,38 @@ namespace Private
f32 inverse_shaping, f32 scale, std::vector<std::vector<GlyphLayout> >& result);
}
inline void eraseTopLargerThan(std::vector<GlyphLayout>& gls,
f32 height_per_line, f32 max_height)
{
if (max_height < height_per_line * 2.0f)
return;
std::vector<u32> newline_positions;
for (unsigned i = 0; i < gls.size(); i++)
{
const GlyphLayout& glyph = gls[i];
if ((glyph.flags & GLF_NEWLINE) != 0)
{
newline_positions.push_back(i);
continue;
}
}
// Handle the first line
f32 total_height = height_per_line +
(f32)newline_positions.size() * height_per_line;
if (total_height > max_height)
{
u32 idx = (u32)((total_height - max_height) / height_per_line);
if (idx < newline_positions.size())
{
auto end_it = gls.begin() + newline_positions[idx] + 1;
if (end_it != gls.end())
gls.erase(gls.begin(), end_it);
}
}
}
inline core::dimension2d<u32> getGlyphLayoutsDimension(
const std::vector<GlyphLayout>& gls, s32 height_per_line, f32 inverse_shaping,
f32 scale, s32 cluster = -1)

View File

@ -1,113 +0,0 @@
// Copyright (C) 2015 Ben Au
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
namespace irr
{
namespace gui
{
//Here a list of characters that don't start or end a line for chinese/japanese/korean
//Only commonly use and full width characters are included
//You should use full width characters when writing CJK, like using "。"instead of a "."
//You can add more characters if needed
//For full list please visit http://webapp.docx4java.org/OnlineDemo/ecma376/WordML/kinsoku.html
inline bool UtfNoStarting (wchar_t c)
{
switch (c)
{
case 8217: //
return true;
case 8221: //”
return true;
case 12293: //々
return true;
case 12297: //〉
return true;
case 12299: //》
return true;
case 12301: //」
return true;
case 65373: //
return true;
case 12309: //
return true;
case 65289: //
return true;
case 12303: //』
return true;
case 12305: //】
return true;
case 12311: //〗
return true;
case 65281: //
return true;
case 65285: //
return true;
case 65311: //
return true;
case 65344: //
return true;
case 65292: //
return true;
case 65306: //
return true;
case 65307: //
return true;
case 65294: //
return true;
case 12290: //。
return true;
case 12289: //、
return true;
default:
return false;
}
}
inline bool UtfNoEnding (wchar_t c)
{
switch (c)
{
case 8216: //
return true;
case 8220: //“
return true;
case 12296: //〈
return true;
case 12298: //《
return true;
case 12300: //「
return true;
case 65371: //
return true;
case 12308: //
return true;
case 65288: //
return true;
case 12302: //『
return true;
case 12304: //【
return true;
case 12310: //〖
return true;
default:
return false;
}
}
//Helper function
inline bool breakable (wchar_t c)
{
if ((c > 12287 && c < 40960) || //Common CJK words
(c > 44031 && c < 55204) || //Hangul
(c > 63743 && c < 64256) || //More Chinese
c == 173 || c == L' ' || //Soft hyphen and white space
c == 47 || c == 92) //Slash and blackslash
return true;
return false;
}
} // end namespace gui
} // end namespace irr

View File

@ -633,35 +633,35 @@ void ClientLobby::handleServerInfo(Event* event)
// At least 6 bytes should remain now
if (!checkDataSize(event, 6)) return;
core::stringw str, total_lines;
if (!m_first_connect)
{
NetworkingLobby::getInstance()
->addMoreServerInfo(L"--------------------");
total_lines = L"--------------------";
total_lines += L"\n";
}
m_first_connect = false;
NetworkString &data = event->data();
// Add server info
core::stringw str, each_line;
uint8_t u_data;
data.decodeStringW(&str);
//I18N: In the networking lobby
each_line = _("Server name: %s", str);
NetworkingLobby::getInstance()->addMoreServerInfo(each_line);
total_lines += _("Server name: %s", str);
total_lines += L"\n";
u_data = data.getUInt8();
const core::stringw& difficulty_name =
race_manager->getDifficultyName((RaceManager::Difficulty)u_data);
race_manager->setDifficulty((RaceManager::Difficulty)u_data);
//I18N: In the networking lobby
each_line = _("Difficulty: %s", difficulty_name);
NetworkingLobby::getInstance()->addMoreServerInfo(each_line);
total_lines += _("Difficulty: %s", difficulty_name);
total_lines += L"\n";
unsigned max_player = data.getUInt8();
//I18N: In the networking lobby
each_line = _("Max players: %d", (int)max_player);
NetworkingLobby::getInstance()->addMoreServerInfo(each_line);
total_lines += _("Max players: %d", (int)max_player);
total_lines += L"\n";
// Reserved for extra spectators
u_data = data.getUInt8();
@ -673,8 +673,8 @@ void ClientLobby::handleServerInfo(Event* event)
//I18N: In the networking lobby
core::stringw mode_name = ServerConfig::getModeName(u_data);
each_line = _("Game mode: %s", mode_name);
NetworkingLobby::getInstance()->addMoreServerInfo(each_line);
total_lines += _("Game mode: %s", mode_name);
total_lines += L"\n";
uint8_t extra_server_info = data.getUInt8();
bool grand_prix_started = false;
@ -691,8 +691,8 @@ void ClientLobby::handleServerInfo(Event* event)
core::stringw sgt = u_data == 0 ? tl : gl;
m_game_setup->setSoccerGoalTarget(u_data != 0);
//I18N: In the networking lobby
each_line = _("Soccer game type: %s", sgt);
NetworkingLobby::getInstance()->addMoreServerInfo(each_line);
total_lines += _("Soccer game type: %s", sgt);
total_lines += L"\n";
break;
}
case 2:
@ -701,9 +701,9 @@ void ClientLobby::handleServerInfo(Event* event)
grand_prix_started = cur_gp_track != 0;
unsigned total_gp_track = data.getUInt8();
m_game_setup->setGrandPrixTrack(total_gp_track);
each_line = _("Grand prix progress: %d / %d", cur_gp_track,
total_lines += _("Grand prix progress: %d / %d", cur_gp_track,
total_gp_track);
NetworkingLobby::getInstance()->addMoreServerInfo(each_line);
total_lines += L"\n";
break;
}
}
@ -716,13 +716,16 @@ void ClientLobby::handleServerInfo(Event* event)
// MOTD
core::stringw motd;
data.decodeString16(&motd);
const std::vector<core::stringw>& motd_line = StringUtils::split(motd,
'\n');
if (!motd_line.empty())
{
for (const core::stringw& motd : motd_line)
NetworkingLobby::getInstance()->addMoreServerInfo(motd);
}
if (!motd.empty())
total_lines += motd;
// Remove last newline added, network lobby will add it back later after
// removing old server info (with chat)
if (total_lines[total_lines.size() - 1] == L'\n')
total_lines.erase(total_lines.size() - 1);
NetworkingLobby::getInstance()->addMoreServerInfo(total_lines);
bool server_config = data.getUInt8() == 1;
NetworkingLobby::getInstance()->toggleServerConfigButton(server_config);
m_server_live_joinable = data.getUInt8() == 1;

View File

@ -23,6 +23,7 @@
#include "config/user_config.hpp"
#include "config/player_manager.hpp"
#include "font/font_manager.hpp"
#include "graphics/irr_driver.hpp"
#include "guiengine/CGUISpriteBank.hpp"
#include "guiengine/scalable_font.hpp"
@ -51,8 +52,6 @@
#include "tracks/track.hpp"
#include "utils/translation.hpp"
#include <utfwrapping.h>
using namespace Online;
using namespace GUIEngine;
@ -234,41 +233,33 @@ void NetworkingLobby::init()
void NetworkingLobby::addMoreServerInfo(core::stringw info)
{
const unsigned box_width = m_text_bubble->getDimension().Width;
while (GUIEngine::getFont()->getDimension(info.c_str()).Width > box_width)
{
core::stringw brokentext = info;
while (brokentext.size() > 0)
{
brokentext.erase(brokentext.size() - 1);
if (GUIEngine::getFont()->getDimension(brokentext.c_str()).Width <
box_width && gui::breakable(brokentext.lastChar()))
break;
}
if (brokentext.size() == 0)
break;
m_server_info.push_back(brokentext);
info =
info.subString(brokentext.size(), info.size() - brokentext.size());
}
if (info.size() > 0)
{
m_server_info.push_back(info);
}
while ((int)m_server_info.size() * m_server_info_height >
m_text_bubble->getDimension().Height)
{
m_server_info.erase(m_server_info.begin());
}
const float box_height = m_text_bubble->getDimension().Height;
// For future copy text from lobby chat
std::vector<std::u32string> text_line;
std::vector<GlyphLayout> cur_info;
font_manager->initGlyphLayouts(info, cur_info, &text_line);
gui::IGUIFont* font = GUIEngine::getFont();
gui::breakGlyphLayouts(cur_info, box_width,
font->getInverseShaping(), font->getScale());
m_server_info.insert(m_server_info.end(), cur_info.begin(),
cur_info.end());
gui::eraseTopLargerThan(m_server_info, font->getHeightPerLine(),
box_height);
// Don't take the newly added newline marker int layouts for linebreaking
// height calculation
gui::GlyphLayout new_line = { 0 };
new_line.flags = gui::GLF_NEWLINE;
m_server_info.push_back(new_line);
if (GUIEngine::getCurrentScreen() != this)
return;
core::stringw total_msg;
for (auto& string : m_server_info)
{
total_msg += string;
total_msg += L"\n";
}
m_text_bubble->setText(total_msg, true);
gui::IGUIStaticText* st =
m_text_bubble->getIrrlichtElement<gui::IGUIStaticText>();
st->setUseGlyphLayoutsOnly(true);
st->setGlyphLayouts(m_server_info);
} // addMoreServerInfo
// ----------------------------------------------------------------------------
@ -451,6 +442,8 @@ void NetworkingLobby::onUpdate(float delta)
if (m_state == LS_ADD_PLAYERS)
{
m_text_bubble->getIrrlichtElement<gui::IGUIStaticText>()
->setUseGlyphLayoutsOnly(false);
m_text_bubble->setText(_("Everyone:\nPress the 'Select' button to "
"join the game"), false);
m_start_button->setVisible(false);
@ -465,6 +458,8 @@ void NetworkingLobby::onUpdate(float delta)
m_start_button->setVisible(false);
if (!cl || !cl->isLobbyReady())
{
m_text_bubble->getIrrlichtElement<gui::IGUIStaticText>()
->setUseGlyphLayoutsOnly(false);
core::stringw connect_msg;
if (m_joined_server)
{

View File

@ -20,9 +20,9 @@
#include "guiengine/screen.hpp"
#include "guiengine/widgets/text_box_widget.hpp"
#include "GlyphLayout.h"
#include <map>
#include <memory>
#include <tuple>
#include <utility>
class InputDevice;
@ -69,7 +69,8 @@ private:
uint64_t m_ping_update_timer;
std::map<std::string, LobbyPlayer> m_player_names;
std::shared_ptr<Server> m_joined_server;
std::vector<core::stringw> m_server_info;
std::vector<gui::GlyphLayout> m_server_info;
int m_server_info_height;
core::stringw m_start_text, m_ready_text, m_live_join_text,