Skip to content

Commit

Permalink
Colored chat working as expected for both freetype and non-freetype b…
Browse files Browse the repository at this point in the history
…uilds. @nerzhul improvements * Add unit tests * Fix coding style * move guiChatConsole.hpp to client/
  • Loading branch information
TriBlade9 authored and Ekdohibs committed May 31, 2016
1 parent 0e44af9 commit 1d40385
Show file tree
Hide file tree
Showing 13 changed files with 998 additions and 28 deletions.
2 changes: 1 addition & 1 deletion builtin/game/chatcommands.lua
Expand Up @@ -102,7 +102,7 @@ core.register_chatcommand("help", {
description = "Get help for commands or list privileges", description = "Get help for commands or list privileges",
func = function(name, param) func = function(name, param)
local function format_help_line(cmd, def) local function format_help_line(cmd, def)
local msg = "/"..cmd local msg = core.colorize("00ffff", "/"..cmd)
if def.params and def.params ~= "" then if def.params and def.params ~= "" then
msg = msg .. " " .. def.params msg = msg .. " " .. def.params
end end
Expand Down
17 changes: 17 additions & 0 deletions builtin/game/misc.lua
Expand Up @@ -197,3 +197,20 @@ function core.http_add_fetch(httpenv)


return httpenv return httpenv
end end

function core.get_color_escape_sequence(color)
--if string.len(color) == 3 then
-- local r = string.sub(color, 1, 1)
-- local g = string.sub(color, 2, 2)
-- local b = string.sub(color, 3, 3)
-- color = r .. r .. g .. g .. b .. b
--end

--assert(#color == 6, "Color must be six characters in length.")
--return "\v" .. color
return "\v(color;" .. color .. ")"
end

function core.colorize(color, message)
return core.get_color_escape_sequence(color) .. message .. core.get_color_escape_sequence("ffffff")
end
29 changes: 13 additions & 16 deletions src/chat.cpp
Expand Up @@ -19,6 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,


#include "chat.h" #include "chat.h"
#include "debug.h" #include "debug.h"
#include "config.h"
#include "util/strfnd.h" #include "util/strfnd.h"
#include <cctype> #include <cctype>
#include <sstream> #include <sstream>
Expand Down Expand Up @@ -251,8 +252,7 @@ u32 ChatBuffer::formatChatLine(const ChatLine& line, u32 cols,
u32 hanging_indentation = 0; u32 hanging_indentation = 0;


// Format the sender name and produce fragments // Format the sender name and produce fragments
if (!line.name.empty()) if (!line.name.empty()) {
{
temp_frag.text = L"<"; temp_frag.text = L"<";
temp_frag.column = 0; temp_frag.column = 0;
//temp_frag.bold = 0; //temp_frag.bold = 0;
Expand All @@ -267,28 +267,28 @@ u32 ChatBuffer::formatChatLine(const ChatLine& line, u32 cols,
next_frags.push_back(temp_frag); next_frags.push_back(temp_frag);
} }


std::wstring name_sanitized = removeEscapes(line.name);

// Choose an indentation level // Choose an indentation level
if (line.name.empty()) if (line.name.empty()) {
{
// Server messages // Server messages
hanging_indentation = 0; hanging_indentation = 0;
} }
else if (line.name.size() + 3 <= cols/2) else if (name_sanitized.size() + 3 <= cols/2) {
{
// Names shorter than about half the console width // Names shorter than about half the console width
hanging_indentation = line.name.size() + 3; hanging_indentation = line.name.size() + 3;
} }
else else {
{
// Very long names // Very long names
hanging_indentation = 2; hanging_indentation = 2;
} }
ColoredString line_text(line.text);


next_line.first = true; next_line.first = true;
bool text_processing = false; bool text_processing = false;


// Produce fragments and layout them into lines // Produce fragments and layout them into lines
while (!next_frags.empty() || in_pos < line.text.size()) while (!next_frags.empty() || in_pos < line_text.size())
{ {
// Layout fragments into lines // Layout fragments into lines
while (!next_frags.empty()) while (!next_frags.empty())
Expand Down Expand Up @@ -326,9 +326,9 @@ u32 ChatBuffer::formatChatLine(const ChatLine& line, u32 cols,
} }


// Produce fragment // Produce fragment
if (in_pos < line.text.size()) if (in_pos < line_text.size())
{ {
u32 remaining_in_input = line.text.size() - in_pos; u32 remaining_in_input = line_text.size() - in_pos;
u32 remaining_in_output = cols - out_column; u32 remaining_in_output = cols - out_column;


// Determine a fragment length <= the minimum of // Determine a fragment length <= the minimum of
Expand All @@ -338,14 +338,14 @@ u32 ChatBuffer::formatChatLine(const ChatLine& line, u32 cols,
while (frag_length < remaining_in_input && while (frag_length < remaining_in_input &&
frag_length < remaining_in_output) frag_length < remaining_in_output)
{ {
if (isspace(line.text[in_pos + frag_length])) if (isspace(line_text[in_pos + frag_length]))
space_pos = frag_length; space_pos = frag_length;
++frag_length; ++frag_length;
} }
if (space_pos != 0 && frag_length < remaining_in_input) if (space_pos != 0 && frag_length < remaining_in_input)
frag_length = space_pos + 1; frag_length = space_pos + 1;


temp_frag.text = line.text.substr(in_pos, frag_length); temp_frag.text = line_text.substr(in_pos, frag_length);
temp_frag.column = 0; temp_frag.column = 0;
//temp_frag.bold = 0; //temp_frag.bold = 0;
next_frags.push_back(temp_frag); next_frags.push_back(temp_frag);
Expand Down Expand Up @@ -686,9 +686,6 @@ ChatBackend::~ChatBackend()


void ChatBackend::addMessage(std::wstring name, std::wstring text) void ChatBackend::addMessage(std::wstring name, std::wstring text)
{ {
name = unescape_enriched(name);
text = unescape_enriched(text);

// Note: A message may consist of multiple lines, for example the MOTD. // Note: A message may consist of multiple lines, for example the MOTD.
WStrfnd fnd(text); WStrfnd fnd(text);
while (!fnd.at_end()) while (!fnd.at_end())
Expand Down
6 changes: 4 additions & 2 deletions src/chat.h
Expand Up @@ -20,11 +20,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#ifndef CHAT_HEADER #ifndef CHAT_HEADER
#define CHAT_HEADER #define CHAT_HEADER


#include "irrlichttypes.h"
#include <string> #include <string>
#include <vector> #include <vector>
#include <list> #include <list>


#include "irrlichttypes.h"
#include "util/coloredstring.h"

// Chat console related classes // Chat console related classes


struct ChatLine struct ChatLine
Expand All @@ -34,7 +36,7 @@ struct ChatLine
// name of sending player, or empty if sent by server // name of sending player, or empty if sent by server
std::wstring name; std::wstring name;
// message text // message text
std::wstring text; ColoredString text;


ChatLine(std::wstring a_name, std::wstring a_text): ChatLine(std::wstring a_name, std::wstring a_text):
age(0.0), age(0.0),
Expand Down
1 change: 1 addition & 0 deletions src/client/CMakeLists.txt
@@ -1,5 +1,6 @@
set(client_SRCS set(client_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/clientlauncher.cpp ${CMAKE_CURRENT_SOURCE_DIR}/clientlauncher.cpp
${CMAKE_CURRENT_SOURCE_DIR}/guiChatConsole.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile.cpp
PARENT_SCOPE PARENT_SCOPE
) )
Expand Down
31 changes: 23 additions & 8 deletions src/guiChatConsole.cpp → src/client/guiChatConsole.cpp
Expand Up @@ -32,7 +32,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <string> #include <string>


#if USE_FREETYPE #if USE_FREETYPE
#include "xCGUITTFont.h" #include "xCGUITTFont.h"
#endif #endif


inline u32 clamp_u8(s32 value) inline u32 clamp_u8(s32 value)
Expand Down Expand Up @@ -340,13 +340,28 @@ void GUIChatConsole::drawText()
s32 x = (fragment.column + 1) * m_fontsize.X; s32 x = (fragment.column + 1) * m_fontsize.X;
core::rect<s32> destrect( core::rect<s32> destrect(
x, y, x + m_fontsize.X * fragment.text.size(), y + m_fontsize.Y); x, y, x + m_fontsize.X * fragment.text.size(), y + m_fontsize.Y);
m_font->draw(
fragment.text.c_str(),
destrect, #if USE_FREETYPE
video::SColor(255, 255, 255, 255), // Draw colored text if FreeType is enabled
false, irr::gui::CGUITTFont *tmp = static_cast<irr::gui::CGUITTFont*>(m_font);
false, tmp->draw(
&AbsoluteClippingRect); fragment.text.c_str(),
destrect,
fragment.text.getColors(),
false,
false,
&AbsoluteClippingRect);
#else
// Otherwise use standard text
m_font->draw(
fragment.text.c_str(),
destrect,
video::SColor(255, 255, 255, 255),
false,
false,
&AbsoluteClippingRect);
#endif
} }
} }
} }
Expand Down
File renamed without changes.
14 changes: 13 additions & 1 deletion src/game.cpp
Expand Up @@ -34,7 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "log.h" #include "log.h"
#include "filesys.h" #include "filesys.h"
#include "gettext.h" #include "gettext.h"
#include "guiChatConsole.h" #include "client/guiChatConsole.h"
#include "guiFormSpecMenu.h" #include "guiFormSpecMenu.h"
#include "guiKeyChangeMenu.h" #include "guiKeyChangeMenu.h"
#include "guiPasswordChange.h" #include "guiPasswordChange.h"
Expand All @@ -59,6 +59,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "minimap.h" #include "minimap.h"
#include "mapblock_mesh.h" #include "mapblock_mesh.h"


#if USE_FREETYPE
#include "util/statictext.h"
#endif

#include "sound.h" #include "sound.h"


#if USE_SOUND #if USE_SOUND
Expand Down Expand Up @@ -2239,12 +2243,20 @@ bool Game::initGui()
false, false, guiroot); false, false, guiroot);
guitext_status->setVisible(false); guitext_status->setVisible(false);


#if USE_FREETYPE
// Colored chat support when using FreeType
guitext_chat = new gui::StaticText(L"", false, guienv, guiroot, -1, core::rect<s32>(0, 0, 0, 0), false);
guitext_chat->setWordWrap(true);
guitext_chat->drop();
#else
// Standard chat when FreeType is disabled
// Chat text // Chat text
guitext_chat = guienv->addStaticText( guitext_chat = guienv->addStaticText(
L"", L"",
core::rect<s32>(0, 0, 0, 0), core::rect<s32>(0, 0, 0, 0),
//false, false); // Disable word wrap as of now //false, false); // Disable word wrap as of now
false, true, guiroot); false, true, guiroot);
#endif
// Remove stale "recent" chat messages from previous connections // Remove stale "recent" chat messages from previous connections
chat_backend->clearRecentChat(); chat_backend->clearRecentChat();


Expand Down
10 changes: 10 additions & 0 deletions src/util/CMakeLists.txt
@@ -1,7 +1,16 @@
if(USE_FREETYPE)
set(UTIL_FREETYPEDEP_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/statictext.cpp
)
else()
set(UTIL_FREETYPEDEP_SRCS )
endif(USE_FREETYPE)

set(UTIL_SRCS set(UTIL_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/areastore.cpp ${CMAKE_CURRENT_SOURCE_DIR}/areastore.cpp
${CMAKE_CURRENT_SOURCE_DIR}/auth.cpp ${CMAKE_CURRENT_SOURCE_DIR}/auth.cpp
${CMAKE_CURRENT_SOURCE_DIR}/base64.cpp ${CMAKE_CURRENT_SOURCE_DIR}/base64.cpp
${CMAKE_CURRENT_SOURCE_DIR}/coloredstring.cpp
${CMAKE_CURRENT_SOURCE_DIR}/directiontables.cpp ${CMAKE_CURRENT_SOURCE_DIR}/directiontables.cpp
${CMAKE_CURRENT_SOURCE_DIR}/numeric.cpp ${CMAKE_CURRENT_SOURCE_DIR}/numeric.cpp
${CMAKE_CURRENT_SOURCE_DIR}/pointedthing.cpp ${CMAKE_CURRENT_SOURCE_DIR}/pointedthing.cpp
Expand All @@ -11,5 +20,6 @@ set(UTIL_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/string.cpp ${CMAKE_CURRENT_SOURCE_DIR}/string.cpp
${CMAKE_CURRENT_SOURCE_DIR}/srp.cpp ${CMAKE_CURRENT_SOURCE_DIR}/srp.cpp
${CMAKE_CURRENT_SOURCE_DIR}/timetaker.cpp ${CMAKE_CURRENT_SOURCE_DIR}/timetaker.cpp
${UTIL_FREETYPEDEP_SRCS}
PARENT_SCOPE) PARENT_SCOPE)


68 changes: 68 additions & 0 deletions src/util/coloredstring.cpp
@@ -0,0 +1,68 @@
/*
Copyright (C) 2013 xyz, Ilya Zhuravlev <whatever@xyz.is>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "coloredstring.h"
#include "util/string.h"

ColoredString::ColoredString()
{}

ColoredString::ColoredString(const std::wstring &string, const std::vector<SColor> &colors):
m_string(string),
m_colors(colors)
{}

ColoredString::ColoredString(const std::wstring &s) {
m_string = colorizeText(s, m_colors, SColor(255, 255, 255, 255));
}

void ColoredString::operator=(const wchar_t *str) {
m_string = colorizeText(str, m_colors, SColor(255, 255, 255, 255));
}

size_t ColoredString::size() const {
return m_string.size();
}

ColoredString ColoredString::substr(size_t pos, size_t len) const {
if (pos == m_string.length())
return ColoredString();
if (len == std::string::npos || pos + len > m_string.length()) {
return ColoredString(
m_string.substr(pos, std::string::npos),
std::vector<SColor>(m_colors.begin() + pos, m_colors.end())
);
} else {
return ColoredString(
m_string.substr(pos, len),
std::vector<SColor>(m_colors.begin() + pos, m_colors.begin() + pos + len)
);
}
}

const wchar_t *ColoredString::c_str() const {
return m_string.c_str();
}

const std::vector<SColor> &ColoredString::getColors() const {
return m_colors;
}

const std::wstring &ColoredString::getString() const {
return m_string;
}
44 changes: 44 additions & 0 deletions src/util/coloredstring.h
@@ -0,0 +1,44 @@
/*
Copyright (C) 2013 xyz, Ilya Zhuravlev <whatever@xyz.is>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#ifndef COLOREDSTRING_HEADER
#define COLOREDSTRING_HEADER

#include <string>
#include <vector>
#include <SColor.h>

using namespace irr::video;

class ColoredString {
public:
ColoredString();
ColoredString(const std::wstring &s);
ColoredString(const std::wstring &string, const std::vector<SColor> &colors);
void operator=(const wchar_t *str);
size_t size() const;
ColoredString substr(size_t pos = 0, size_t len = std::string::npos) const;
const wchar_t *c_str() const;
const std::vector<SColor> &getColors() const;
const std::wstring &getString() const;
private:
std::wstring m_string;
std::vector<SColor> m_colors;
};

#endif

0 comments on commit 1d40385

Please sign in to comment.