These are a collection of classes I have written that provide Irrlicht the ability to handle/read/write/draw unicode text. Everything here is based off the abilities of the ustring class. The ustring class, CGUITTFont class, and the CStringTable class are all licensed under the zlib license, the same license that Irrlicht uses.
ustring
Download: irrUString.h
ustring is a UTF-16 string class. It can convert to/from UTF-8 and UTF-32. Using an iterator, one can gain access to each unicode character in the string. This is the base class used by everything else. It is heavily documented in doxygen format. It also supports C++0x move semantics for users of Visual C++ 2010 and GCC (when using -std=c++0x). This provides a performance improvement when dealing with a lot of temporary copies (ie, chaining multiple strings together with +).
To use everything else in this post, you must place this file in Irrlicht's include directory and add to irrlicht.h:
#include "irrUString.h"
XML reading/writing
Download: CXMLWriterUTF8.zip
Download: xml_io.patch
-- svn trunk
-- 1.7.2
These are tweaks to the XML reading/writing system. It enables Irrlicht to correctly read any type of UTF encoded XML file and write UTF-8 encoded files. As reading files is built into Irrlicht, a patch for CXMLReaderImpl.h is required. As Irrlicht uses CXMLWriter when serializing elements, a patch for CFileSystem.cpp is required to use the new CXMLWriterUTF8 class.
Add CXMLWriterUTF8.h and CXMLWriterUTF8.cpp to Irrlicht's source directory, add the files to the Irrlicht project, and apply the patch to gain access to this feature.
Multi-byte font rendering
Download: CGUITTFont.zip
-- svn trunk
-- 1.7.2
Requires: FreeType 2
To render multi-byte unicode, CGUITTFont was created. This requires FreeType 2 to work and a font that contains the glyphs you wish to render. The class will return a gui::IGUIFont that you can then bind to Irrlicht's GUI for rendering. The class has full doxygen documentation built-in.
Add CGUITTFont.h and CGUITTFont.cpp to your project to gain access to this ability. Remember, you must be using FreeType 2 in order to draw TrueType fonts.
Multi-language string tables
Download: CStringTable.zip
To help facilitate internationalization, the string table class allows you to change the language of your application just by loading in a specially designed XML file.
Add CStringTable.h and CStringTable.cpp to your project to gain access to this ability.
How does this all work?
Irrlicht makes heavy use of wchar_t, which is a data type that varies in size depending on your platform (16 bits on Windows, 32 bits on Linux, etc.) ustring has the ability to convert to/from a stringw holding its proper, platform specific unicode string (UTF-16 in Windows, UTF-32 in Linux, etc.) You read your data into a ustring and convert it to a stringw when you need to pass it through Irrlicht (like, for example, drawing it on the screen), converting it back to a ustring when it reaches its destination. CGUITTFont will convert the stringw back into a ustring before it draws the text. This allows us to have basic internationalization support without gutting Irrlicht.
How do I convert my ustring to other strings?
Code: Select all
ustring test("This is a test \xEF\xBF\xBD");
stringc test_char = test.toUTF8_s();
stringw test_wchar = test.toWCHAR_s();
io::path test_path = test.toPATH_s();
Code: Select all
ustring test("This is a test \xEF\xBF\xBD");
test += (uchar32_t)0x10400;
std::cout << "test.size(): " << test.size() << std::endl;
std::cout << "test.size_raw(): " << test.size_raw() << std::endl;
ustring::iterator end = test.end();
for (ustring::iterator i = test.begin(); i != end; ++i)
{
uchar32_t character = *i;
std::cout << "character: " << character << std::endl;
}
// Yes, we can directly output our ustring to std::cout.
std::cout << test << std::endl;
// The iterator is STL compatible, so we can use C++0x and the STL to increment each character by 1.
std::for_each(test.begin(), test.end(), [](ustring::access& c) { ++c; });
// And we can output to std::wcout too.
std::wcout << test << std::wendl;
Code: Select all
// Get a 14 pixel high code2001 font.
gui::CGUITTFont* tt_font = gui::CGUITTFont::createTTFont(device->getGUIEnvironment(), "code2001.ttf", 14);
// Set the font.
gui::IGUIEnvironment* env = device->getGUIEnvironment();
gui::IGUISkin* skin = env->getSkin();
skin->setFont(tt_font);
...
tt_font->drop();
A string table will hold all the translated strings for a given language. Your project should have a string table for each language you want to support.
Code: Select all
// A string table can be loaded using the loadStringTable() function in the irr::st namespace.
st::CStringTable* stringtable = st::loadStringTable("example.irrst", device->getFileSystem());
// Then we can set it to be the active string table.
st::setActiveStringTable(st);
Code: Select all
// Alternatively, you can use the CStringTableManager class.
CStringTableManager mgr;
// The CStringTableManager class can load all .irrst files in a directory.
mgr.loadDirectory("translations", device->getFileSystem());
// We can then set the active table by the language of the string table.
mgr.setActiveStringTable("English");
Code: Select all
// We can get a string directly from a string table.
st::CStringTable* english = st::loadStringTable("english.irrst", device->getFileSystem());
// Both getTranslation and _T will return the string associated with the given ID.
core::ustring username = english->getTranslation("Username");
core::ustring password = english->_T("Password");
// Or, we can set it as the active string table...
st::setActiveStringTable(english);
// ...and use the st::_T() function to grab a string from it.
core::ustring nickname = st::_T("Nickname");
Code: Select all
// The same thing works with the CStringTableManager.
CStringTableManager mgr;
mgr.loadDirectory("translations");
mgr.setActiveStringTable("Español");
core::ustring nickname = st::_T("Nickname");
...
gui::IGUIStaticText* passtext = env->addStaticText(st::_T("Password").toWCHAR_s().c_str(), core::recti(200, 180, 200 + 200, 180 + 20), false, false, window, GUI_LOGIN_PASSWORD, false);
Code: Select all
// We can also manipulate parameters in the strings.
// We will be using this string:
// Hello, {{%1}}! How are you?
// In our Spanish language file, it is translated as this:
// ¡Hola, {{%1}}! ¿Cómo estás?
// Assume that the currently active string table is the Spanish table.
const core::ustring nick_name("Bob");
...
// This will return:
// ¡Hola, Bob! ¿Cómo estás?
core::ustring greeting = st::_T("Hello, {{%1}}! How are you?").param(nick_name);
...
// By default, parameters are in the format:
// {{%1}}, {{%2}}, ...
// But that can be changed:
st::CStringTable* english = st::loadStringTable("english.irrst", device->getFileSystem());
// This sets the parameter format to the following:
// [#1], [#2], ...
english->setParameterFormat("[#", "]");
Code: Select all
<?xml version="1.0"?>
<irr_stringtable>
<language value="Español" />
<entry>
<id>Nickname</id>
<translation>Apodo</translation>
</entry>
<entry id="Username"><![CDATA[<Nombre de usuario>]]></entry>
<entry id="Password">Contraseña</entry>
<s id="Language">Idioma</s>
</irr_stringtable>
I'm not sure. Care to suggest something?
---
I have a keyboard that has non-ASCII characters. When I type into a text box in Irrlicht, it doesn't show the proper character! Why? (ALSO: Why can't a paste unicode text into Irrlicht?)
These patches don't solve this issue. If you want to be able to input unicode characters into Irrlicht, please take a look at MadHyde's patches:
http://irrlicht.sourceforge.net/phpBB2/ ... 810#220810
Please note that as of the time of this post edit, Linux support in MadHyde's patches is incomplete.
---
Reported issues:
Incompatible with acki's irrExtensions.
---
Since new post notification e-mails don't work, and I don't always check this thread, I may not realize that you have posted something for a while. If you need help, you may want to consider sending me an e-mail:
john@suckerfreegames.removethis.com