Skip to content

Commit 1d40385

Browse files
TriBlade9Ekdohibs
TriBlade9
authored andcommittedMay 31, 2016
Colored chat working as expected for both freetype and non-freetype builds. @nerzhul improvements * Add unit tests * Fix coding style * move guiChatConsole.hpp to client/
1 parent 0e44af9 commit 1d40385

13 files changed

+998
-28
lines changed
 

‎builtin/game/chatcommands.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ core.register_chatcommand("help", {
102102
description = "Get help for commands or list privileges",
103103
func = function(name, param)
104104
local function format_help_line(cmd, def)
105-
local msg = "/"..cmd
105+
local msg = core.colorize("00ffff", "/"..cmd)
106106
if def.params and def.params ~= "" then
107107
msg = msg .. " " .. def.params
108108
end

‎builtin/game/misc.lua

+17
Original file line numberDiff line numberDiff line change
@@ -197,3 +197,20 @@ function core.http_add_fetch(httpenv)
197197

198198
return httpenv
199199
end
200+
201+
function core.get_color_escape_sequence(color)
202+
--if string.len(color) == 3 then
203+
-- local r = string.sub(color, 1, 1)
204+
-- local g = string.sub(color, 2, 2)
205+
-- local b = string.sub(color, 3, 3)
206+
-- color = r .. r .. g .. g .. b .. b
207+
--end
208+
209+
--assert(#color == 6, "Color must be six characters in length.")
210+
--return "\v" .. color
211+
return "\v(color;" .. color .. ")"
212+
end
213+
214+
function core.colorize(color, message)
215+
return core.get_color_escape_sequence(color) .. message .. core.get_color_escape_sequence("ffffff")
216+
end

‎src/chat.cpp

+13-16
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
1919

2020
#include "chat.h"
2121
#include "debug.h"
22+
#include "config.h"
2223
#include "util/strfnd.h"
2324
#include <cctype>
2425
#include <sstream>
@@ -251,8 +252,7 @@ u32 ChatBuffer::formatChatLine(const ChatLine& line, u32 cols,
251252
u32 hanging_indentation = 0;
252253

253254
// Format the sender name and produce fragments
254-
if (!line.name.empty())
255-
{
255+
if (!line.name.empty()) {
256256
temp_frag.text = L"<";
257257
temp_frag.column = 0;
258258
//temp_frag.bold = 0;
@@ -267,28 +267,28 @@ u32 ChatBuffer::formatChatLine(const ChatLine& line, u32 cols,
267267
next_frags.push_back(temp_frag);
268268
}
269269

270+
std::wstring name_sanitized = removeEscapes(line.name);
271+
270272
// Choose an indentation level
271-
if (line.name.empty())
272-
{
273+
if (line.name.empty()) {
273274
// Server messages
274275
hanging_indentation = 0;
275276
}
276-
else if (line.name.size() + 3 <= cols/2)
277-
{
277+
else if (name_sanitized.size() + 3 <= cols/2) {
278278
// Names shorter than about half the console width
279279
hanging_indentation = line.name.size() + 3;
280280
}
281-
else
282-
{
281+
else {
283282
// Very long names
284283
hanging_indentation = 2;
285284
}
285+
ColoredString line_text(line.text);
286286

287287
next_line.first = true;
288288
bool text_processing = false;
289289

290290
// Produce fragments and layout them into lines
291-
while (!next_frags.empty() || in_pos < line.text.size())
291+
while (!next_frags.empty() || in_pos < line_text.size())
292292
{
293293
// Layout fragments into lines
294294
while (!next_frags.empty())
@@ -326,9 +326,9 @@ u32 ChatBuffer::formatChatLine(const ChatLine& line, u32 cols,
326326
}
327327

328328
// Produce fragment
329-
if (in_pos < line.text.size())
329+
if (in_pos < line_text.size())
330330
{
331-
u32 remaining_in_input = line.text.size() - in_pos;
331+
u32 remaining_in_input = line_text.size() - in_pos;
332332
u32 remaining_in_output = cols - out_column;
333333

334334
// Determine a fragment length <= the minimum of
@@ -338,14 +338,14 @@ u32 ChatBuffer::formatChatLine(const ChatLine& line, u32 cols,
338338
while (frag_length < remaining_in_input &&
339339
frag_length < remaining_in_output)
340340
{
341-
if (isspace(line.text[in_pos + frag_length]))
341+
if (isspace(line_text[in_pos + frag_length]))
342342
space_pos = frag_length;
343343
++frag_length;
344344
}
345345
if (space_pos != 0 && frag_length < remaining_in_input)
346346
frag_length = space_pos + 1;
347347

348-
temp_frag.text = line.text.substr(in_pos, frag_length);
348+
temp_frag.text = line_text.substr(in_pos, frag_length);
349349
temp_frag.column = 0;
350350
//temp_frag.bold = 0;
351351
next_frags.push_back(temp_frag);
@@ -686,9 +686,6 @@ ChatBackend::~ChatBackend()
686686

687687
void ChatBackend::addMessage(std::wstring name, std::wstring text)
688688
{
689-
name = unescape_enriched(name);
690-
text = unescape_enriched(text);
691-
692689
// Note: A message may consist of multiple lines, for example the MOTD.
693690
WStrfnd fnd(text);
694691
while (!fnd.at_end())

‎src/chat.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
2020
#ifndef CHAT_HEADER
2121
#define CHAT_HEADER
2222

23-
#include "irrlichttypes.h"
2423
#include <string>
2524
#include <vector>
2625
#include <list>
2726

27+
#include "irrlichttypes.h"
28+
#include "util/coloredstring.h"
29+
2830
// Chat console related classes
2931

3032
struct ChatLine
@@ -34,7 +36,7 @@ struct ChatLine
3436
// name of sending player, or empty if sent by server
3537
std::wstring name;
3638
// message text
37-
std::wstring text;
39+
ColoredString text;
3840

3941
ChatLine(std::wstring a_name, std::wstring a_text):
4042
age(0.0),

‎src/client/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
set(client_SRCS
22
${CMAKE_CURRENT_SOURCE_DIR}/clientlauncher.cpp
3+
${CMAKE_CURRENT_SOURCE_DIR}/guiChatConsole.cpp
34
${CMAKE_CURRENT_SOURCE_DIR}/tile.cpp
45
PARENT_SCOPE
56
)

‎src/guiChatConsole.cpp ‎src/client/guiChatConsole.cpp

+23-8
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
3232
#include <string>
3333

3434
#if USE_FREETYPE
35-
#include "xCGUITTFont.h"
35+
#include "xCGUITTFont.h"
3636
#endif
3737

3838
inline u32 clamp_u8(s32 value)
@@ -340,13 +340,28 @@ void GUIChatConsole::drawText()
340340
s32 x = (fragment.column + 1) * m_fontsize.X;
341341
core::rect<s32> destrect(
342342
x, y, x + m_fontsize.X * fragment.text.size(), y + m_fontsize.Y);
343-
m_font->draw(
344-
fragment.text.c_str(),
345-
destrect,
346-
video::SColor(255, 255, 255, 255),
347-
false,
348-
false,
349-
&AbsoluteClippingRect);
343+
344+
345+
#if USE_FREETYPE
346+
// Draw colored text if FreeType is enabled
347+
irr::gui::CGUITTFont *tmp = static_cast<irr::gui::CGUITTFont*>(m_font);
348+
tmp->draw(
349+
fragment.text.c_str(),
350+
destrect,
351+
fragment.text.getColors(),
352+
false,
353+
false,
354+
&AbsoluteClippingRect);
355+
#else
356+
// Otherwise use standard text
357+
m_font->draw(
358+
fragment.text.c_str(),
359+
destrect,
360+
video::SColor(255, 255, 255, 255),
361+
false,
362+
false,
363+
&AbsoluteClippingRect);
364+
#endif
350365
}
351366
}
352367
}
File renamed without changes.

‎src/game.cpp

+13-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
3434
#include "log.h"
3535
#include "filesys.h"
3636
#include "gettext.h"
37-
#include "guiChatConsole.h"
37+
#include "client/guiChatConsole.h"
3838
#include "guiFormSpecMenu.h"
3939
#include "guiKeyChangeMenu.h"
4040
#include "guiPasswordChange.h"
@@ -59,6 +59,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
5959
#include "minimap.h"
6060
#include "mapblock_mesh.h"
6161

62+
#if USE_FREETYPE
63+
#include "util/statictext.h"
64+
#endif
65+
6266
#include "sound.h"
6367

6468
#if USE_SOUND
@@ -2239,12 +2243,20 @@ bool Game::initGui()
22392243
false, false, guiroot);
22402244
guitext_status->setVisible(false);
22412245

2246+
#if USE_FREETYPE
2247+
// Colored chat support when using FreeType
2248+
guitext_chat = new gui::StaticText(L"", false, guienv, guiroot, -1, core::rect<s32>(0, 0, 0, 0), false);
2249+
guitext_chat->setWordWrap(true);
2250+
guitext_chat->drop();
2251+
#else
2252+
// Standard chat when FreeType is disabled
22422253
// Chat text
22432254
guitext_chat = guienv->addStaticText(
22442255
L"",
22452256
core::rect<s32>(0, 0, 0, 0),
22462257
//false, false); // Disable word wrap as of now
22472258
false, true, guiroot);
2259+
#endif
22482260
// Remove stale "recent" chat messages from previous connections
22492261
chat_backend->clearRecentChat();
22502262

‎src/util/CMakeLists.txt

+10
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
1+
if(USE_FREETYPE)
2+
set(UTIL_FREETYPEDEP_SRCS
3+
${CMAKE_CURRENT_SOURCE_DIR}/statictext.cpp
4+
)
5+
else()
6+
set(UTIL_FREETYPEDEP_SRCS )
7+
endif(USE_FREETYPE)
8+
19
set(UTIL_SRCS
210
${CMAKE_CURRENT_SOURCE_DIR}/areastore.cpp
311
${CMAKE_CURRENT_SOURCE_DIR}/auth.cpp
412
${CMAKE_CURRENT_SOURCE_DIR}/base64.cpp
13+
${CMAKE_CURRENT_SOURCE_DIR}/coloredstring.cpp
514
${CMAKE_CURRENT_SOURCE_DIR}/directiontables.cpp
615
${CMAKE_CURRENT_SOURCE_DIR}/numeric.cpp
716
${CMAKE_CURRENT_SOURCE_DIR}/pointedthing.cpp
@@ -11,5 +20,6 @@ set(UTIL_SRCS
1120
${CMAKE_CURRENT_SOURCE_DIR}/string.cpp
1221
${CMAKE_CURRENT_SOURCE_DIR}/srp.cpp
1322
${CMAKE_CURRENT_SOURCE_DIR}/timetaker.cpp
23+
${UTIL_FREETYPEDEP_SRCS}
1424
PARENT_SCOPE)
1525

‎src/util/coloredstring.cpp

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
Copyright (C) 2013 xyz, Ilya Zhuravlev <whatever@xyz.is>
3+
4+
This program is free software; you can redistribute it and/or modify
5+
it under the terms of the GNU Lesser General Public License as published by
6+
the Free Software Foundation; either version 2.1 of the License, or
7+
(at your option) any later version.
8+
9+
This program is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU Lesser General Public License for more details.
13+
14+
You should have received a copy of the GNU Lesser General Public License along
15+
with this program; if not, write to the Free Software Foundation, Inc.,
16+
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17+
*/
18+
19+
#include "coloredstring.h"
20+
#include "util/string.h"
21+
22+
ColoredString::ColoredString()
23+
{}
24+
25+
ColoredString::ColoredString(const std::wstring &string, const std::vector<SColor> &colors):
26+
m_string(string),
27+
m_colors(colors)
28+
{}
29+
30+
ColoredString::ColoredString(const std::wstring &s) {
31+
m_string = colorizeText(s, m_colors, SColor(255, 255, 255, 255));
32+
}
33+
34+
void ColoredString::operator=(const wchar_t *str) {
35+
m_string = colorizeText(str, m_colors, SColor(255, 255, 255, 255));
36+
}
37+
38+
size_t ColoredString::size() const {
39+
return m_string.size();
40+
}
41+
42+
ColoredString ColoredString::substr(size_t pos, size_t len) const {
43+
if (pos == m_string.length())
44+
return ColoredString();
45+
if (len == std::string::npos || pos + len > m_string.length()) {
46+
return ColoredString(
47+
m_string.substr(pos, std::string::npos),
48+
std::vector<SColor>(m_colors.begin() + pos, m_colors.end())
49+
);
50+
} else {
51+
return ColoredString(
52+
m_string.substr(pos, len),
53+
std::vector<SColor>(m_colors.begin() + pos, m_colors.begin() + pos + len)
54+
);
55+
}
56+
}
57+
58+
const wchar_t *ColoredString::c_str() const {
59+
return m_string.c_str();
60+
}
61+
62+
const std::vector<SColor> &ColoredString::getColors() const {
63+
return m_colors;
64+
}
65+
66+
const std::wstring &ColoredString::getString() const {
67+
return m_string;
68+
}

‎src/util/coloredstring.h

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
Copyright (C) 2013 xyz, Ilya Zhuravlev <whatever@xyz.is>
3+
4+
This program is free software; you can redistribute it and/or modify
5+
it under the terms of the GNU Lesser General Public License as published by
6+
the Free Software Foundation; either version 2.1 of the License, or
7+
(at your option) any later version.
8+
9+
This program is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU Lesser General Public License for more details.
13+
14+
You should have received a copy of the GNU Lesser General Public License along
15+
with this program; if not, write to the Free Software Foundation, Inc.,
16+
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17+
*/
18+
19+
#ifndef COLOREDSTRING_HEADER
20+
#define COLOREDSTRING_HEADER
21+
22+
#include <string>
23+
#include <vector>
24+
#include <SColor.h>
25+
26+
using namespace irr::video;
27+
28+
class ColoredString {
29+
public:
30+
ColoredString();
31+
ColoredString(const std::wstring &s);
32+
ColoredString(const std::wstring &string, const std::vector<SColor> &colors);
33+
void operator=(const wchar_t *str);
34+
size_t size() const;
35+
ColoredString substr(size_t pos = 0, size_t len = std::string::npos) const;
36+
const wchar_t *c_str() const;
37+
const std::vector<SColor> &getColors() const;
38+
const std::wstring &getString() const;
39+
private:
40+
std::wstring m_string;
41+
std::vector<SColor> m_colors;
42+
};
43+
44+
#endif

‎src/util/statictext.cpp

+654
Large diffs are not rendered by default.

‎src/util/statictext.h

+150
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
// Copyright (C) 2002-2012 Nikolaus Gebhardt
2+
// This file is part of the "Irrlicht Engine".
3+
// For conditions of distribution and use, see copyright notice in irrlicht.h
4+
5+
#ifndef __C_GUI_STATIC_TEXT_H_INCLUDED__
6+
#define __C_GUI_STATIC_TEXT_H_INCLUDED__
7+
8+
#include "IrrCompileConfig.h"
9+
#ifdef _IRR_COMPILE_WITH_GUI_
10+
11+
#include "IGUIStaticText.h"
12+
#include "irrArray.h"
13+
14+
#include <vector>
15+
16+
namespace irr
17+
{
18+
namespace gui
19+
{
20+
class StaticText : public IGUIStaticText
21+
{
22+
public:
23+
24+
//! constructor
25+
StaticText(const wchar_t* text, bool border, IGUIEnvironment* environment,
26+
IGUIElement* parent, s32 id, const core::rect<s32>& rectangle,
27+
bool background = false);
28+
29+
//! destructor
30+
virtual ~StaticText();
31+
32+
//! draws the element and its children
33+
virtual void draw();
34+
35+
//! Sets another skin independent font.
36+
virtual void setOverrideFont(IGUIFont* font=0);
37+
38+
//! Gets the override font (if any)
39+
virtual IGUIFont* getOverrideFont() const;
40+
41+
//! Get the font which is used right now for drawing
42+
virtual IGUIFont* getActiveFont() const;
43+
44+
//! Sets another color for the text.
45+
virtual void setOverrideColor(video::SColor color);
46+
47+
//! Sets another color for the background.
48+
virtual void setBackgroundColor(video::SColor color);
49+
50+
//! Sets whether to draw the background
51+
virtual void setDrawBackground(bool draw);
52+
53+
//! Gets the background color
54+
virtual video::SColor getBackgroundColor() const;
55+
56+
//! Checks if background drawing is enabled
57+
virtual bool isDrawBackgroundEnabled() const;
58+
59+
//! Sets whether to draw the border
60+
virtual void setDrawBorder(bool draw);
61+
62+
//! Checks if border drawing is enabled
63+
virtual bool isDrawBorderEnabled() const;
64+
65+
//! Sets alignment mode for text
66+
virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical);
67+
68+
//! Gets the override color
69+
#if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR <= 7
70+
virtual const video::SColor& getOverrideColor() const;
71+
#else
72+
virtual video::SColor getOverrideColor() const;
73+
#endif
74+
75+
//! Sets if the static text should use the overide color or the
76+
//! color in the gui skin.
77+
virtual void enableOverrideColor(bool enable);
78+
79+
//! Checks if an override color is enabled
80+
virtual bool isOverrideColorEnabled() const;
81+
82+
//! Set whether the text in this label should be clipped if it goes outside bounds
83+
virtual void setTextRestrainedInside(bool restrainedInside);
84+
85+
//! Checks if the text in this label should be clipped if it goes outside bounds
86+
virtual bool isTextRestrainedInside() const;
87+
88+
//! Enables or disables word wrap for using the static text as
89+
//! multiline text control.
90+
virtual void setWordWrap(bool enable);
91+
92+
//! Checks if word wrap is enabled
93+
virtual bool isWordWrapEnabled() const;
94+
95+
//! Sets the new caption of this element.
96+
virtual void setText(const wchar_t* text);
97+
98+
//! Returns the height of the text in pixels when it is drawn.
99+
virtual s32 getTextHeight() const;
100+
101+
//! Returns the width of the current text, in the current font
102+
virtual s32 getTextWidth() const;
103+
104+
//! Updates the absolute position, splits text if word wrap is enabled
105+
virtual void updateAbsolutePosition();
106+
107+
//! Set whether the string should be interpreted as right-to-left (RTL) text
108+
/** \note This component does not implement the Unicode bidi standard, the
109+
text of the component should be already RTL if you call this. The
110+
main difference when RTL is enabled is that the linebreaks for multiline
111+
elements are performed starting from the end.
112+
*/
113+
virtual void setRightToLeft(bool rtl);
114+
115+
//! Checks if the text should be interpreted as right-to-left text
116+
virtual bool isRightToLeft() const;
117+
118+
//! Writes attributes of the element.
119+
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const;
120+
121+
//! Reads attributes of the element
122+
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options);
123+
124+
private:
125+
126+
//! Breaks the single text line.
127+
void breakText();
128+
129+
EGUI_ALIGNMENT HAlign, VAlign;
130+
bool Border;
131+
bool OverrideColorEnabled;
132+
bool OverrideBGColorEnabled;
133+
bool WordWrap;
134+
bool Background;
135+
bool RestrainTextInside;
136+
bool RightToLeft;
137+
138+
video::SColor OverrideColor, BGColor;
139+
gui::IGUIFont* OverrideFont;
140+
gui::IGUIFont* LastBreakFont; // stored because: if skin changes, line break must be recalculated.
141+
142+
core::array< core::stringw > BrokenText;
143+
};
144+
145+
} // end namespace gui
146+
} // end namespace irr
147+
148+
#endif // _IRR_COMPILE_WITH_GUI_
149+
150+
#endif // C_GUI_STATIC_TEXT_H_INCLUDED

0 commit comments

Comments
 (0)
Please sign in to comment.