-
+
diff --git a/data/gui/title_font.png b/data/gui/title_font.png
new file mode 100644
index 000000000..a102f7289
Binary files /dev/null and b/data/gui/title_font.png differ
diff --git a/data/gui/title_font.xml b/data/gui/title_font.xml
new file mode 100644
index 000000000..b9b332535
--- /dev/null
+++ b/data/gui/title_font.xml
@@ -0,0 +1,968 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/gui/tracks.stkgui b/data/gui/tracks.stkgui
index 67747b7d6..9d087a6ce 100644
--- a/data/gui/tracks.stkgui
+++ b/data/gui/tracks.stkgui
@@ -2,7 +2,7 @@
-
@@ -12,7 +12,7 @@
-
diff --git a/src/guiengine/CGUIFont.cpp b/src/guiengine/CGUIFont.cpp
new file mode 100644
index 000000000..2f92e1192
--- /dev/null
+++ b/src/guiengine/CGUIFont.cpp
@@ -0,0 +1,627 @@
+// Copyright (C) 2002-2009 Nikolaus Gebhardt
+// This file is part of the "Irrlicht Engine".
+// For conditions of distribution and use, see copyright notice in irrlicht.h
+
+#include "CGUIFont.h"
+
+#include "IGUIEnvironment.h"
+#include "IXMLReader.h"
+#include "IReadFile.h"
+#include "IVideoDriver.h"
+#include "IGUISpriteBank.h"
+#include
+#include "guiengine/engine.hpp"
+#include "io/file_manager.hpp"
+
+namespace irr
+{
+namespace gui
+{
+
+//! constructor
+ScalableFont::ScalableFont(IGUIEnvironment *env, const io::path& filename)
+: Driver(0), SpriteBank(0), Environment(env), WrongCharacter(0),
+ MaxHeight(0), GlobalKerningWidth(0), GlobalKerningHeight(0)
+{
+ #ifdef _DEBUG
+ setDebugName("ScalableFont");
+ #endif
+
+ m_scale = 1.0f;
+
+ if (Environment)
+ {
+ // don't grab environment, to avoid circular references
+ Driver = Environment->getVideoDriver();
+
+ SpriteBank = Environment->addEmptySpriteBank(filename);
+ if (SpriteBank)
+ SpriteBank->grab();
+ }
+
+ if (Driver)
+ Driver->grab();
+
+ setInvisibleCharacters ( L" " );
+
+ load( file_manager->createXMLReader(filename.c_str()) );
+}
+
+
+//! destructor
+ScalableFont::~ScalableFont()
+{
+ if (Driver)
+ Driver->drop();
+
+ if (SpriteBank)
+ SpriteBank->drop();
+}
+
+
+//! loads a font file from xml
+bool ScalableFont::load(io::IXMLReader* xml)
+{
+ if (!SpriteBank)
+ return false;
+
+ while (xml->read())
+ {
+ if (io::EXN_ELEMENT == xml->getNodeType())
+ {
+ if (core::stringw(L"Texture") == xml->getNodeName())
+ {
+ // add a texture
+ core::stringc fn = core::stringc((file_manager->getGUIDir() + "/").c_str()) + xml->getAttributeValue(L"filename");
+ u32 i = (u32)xml->getAttributeValueAsInt(L"index");
+ core::stringw alpha = xml->getAttributeValue(L"hasAlpha");
+
+ std::cout << "---- Adding font texture " << fn.c_str() << "; alpha=" << alpha.c_str() << std::endl;
+
+
+ while (i+1 > SpriteBank->getTextureCount())
+ SpriteBank->addTexture(0);
+
+ // disable mipmaps+filtering
+ //bool mipmap = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
+ //Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);
+
+ // load texture
+ SpriteBank->setTexture(i, Driver->getTexture(fn));
+
+ // set previous mip-map+filter state
+ //Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, mipmap);
+
+ // couldn't load texture, abort.
+ if (!SpriteBank->getTexture(i))
+ {
+ std::cerr << "!!!!! Unable to load all textures in the font, aborting" << std::endl;
+ _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
+ return false;
+ }
+ else
+ {
+ // colorkey texture rather than alpha channel?
+ if (alpha == core::stringw("false"))
+ Driver->makeColorKeyTexture(SpriteBank->getTexture(i), core::position2di(0,0));
+ }
+ }
+ else if (core::stringw(L"c") == xml->getNodeName())
+ {
+ // adding a character to this font
+ SFontArea a;
+ SGUISpriteFrame f;
+ SGUISprite s;
+ core::rect rectangle;
+
+ a.underhang = xml->getAttributeValueAsInt(L"u");
+ a.overhang = xml->getAttributeValueAsInt(L"o");
+ a.spriteno = SpriteBank->getSprites().size();
+ s32 texno = xml->getAttributeValueAsInt(L"i");
+
+ // parse rectangle
+ core::stringc rectstr = xml->getAttributeValue(L"r");
+ wchar_t ch = xml->getAttributeValue(L"c")[0];
+
+ const c8 *c = rectstr.c_str();
+ s32 val;
+ val = 0;
+ while (*c >= '0' && *c <= '9')
+ {
+ val *= 10;
+ val += *c - '0';
+ c++;
+ }
+ rectangle.UpperLeftCorner.X = val;
+ while (*c == L' ' || *c == L',') c++;
+
+ val = 0;
+ while (*c >= '0' && *c <= '9')
+ {
+ val *= 10;
+ val += *c - '0';
+ c++;
+ }
+ rectangle.UpperLeftCorner.Y = val;
+ while (*c == L' ' || *c == L',') c++;
+
+ val = 0;
+ while (*c >= '0' && *c <= '9')
+ {
+ val *= 10;
+ val += *c - '0';
+ c++;
+ }
+ rectangle.LowerRightCorner.X = val;
+ while (*c == L' ' || *c == L',') c++;
+
+ val = 0;
+ while (*c >= '0' && *c <= '9')
+ {
+ val *= 10;
+ val += *c - '0';
+ c++;
+ }
+ rectangle.LowerRightCorner.Y = val;
+
+ CharacterMap.insert(ch,Areas.size());
+ //std::cout << "Inserting character '" << ch << "' with area " << Areas.size() << std::endl;
+
+ // make frame
+ f.rectNumber = SpriteBank->getPositions().size();
+ f.textureNumber = texno;
+
+ // add frame to sprite
+ s.Frames.push_back(f);
+ s.frameTime = 0;
+
+ // add rectangle to sprite bank
+ SpriteBank->getPositions().push_back(rectangle);
+ a.width = rectangle.getWidth();
+
+ // add sprite to sprite bank
+ SpriteBank->getSprites().push_back(s);
+
+ // add character to font
+ Areas.push_back(a);
+ }
+ }
+ }
+
+ // set bad character
+ WrongCharacter = getAreaFromCharacter(L' ');
+
+ setMaxHeight();
+
+ return true;
+}
+void ScalableFont::setScale(const float scale)
+{
+ m_scale = scale;
+}
+
+void ScalableFont::setMaxHeight()
+{
+ MaxHeight = 0;
+ s32 t;
+
+ core::array< core::rect >& p = SpriteBank->getPositions();
+
+ for (u32 i=0; iMaxHeight)
+ MaxHeight = t;
+ }
+
+
+}
+
+
+//! loads a font file, native file needed, for texture parsing
+bool ScalableFont::load(io::IReadFile* file)
+{
+ if (!Driver)
+ return false;
+
+ return loadTexture(Driver->createImageFromFile(file),
+ file->getFileName());
+}
+
+
+//! loads a font file, native file needed, for texture parsing
+bool ScalableFont::load(const io::path& filename)
+{
+ if (!Driver)
+ return false;
+
+ return loadTexture(Driver->createImageFromFile( filename ),
+ filename);
+}
+
+
+//! load & prepare font from ITexture
+bool ScalableFont::loadTexture(video::IImage* image, const io::path& name)
+{
+ if (!image)
+ return false;
+
+ s32 lowerRightPositions = 0;
+
+ video::IImage* tmpImage=image;
+ /*
+ bool deleteTmpImage=false;
+ switch(image->getColorFormat())
+ {
+ case video::ECF_R5G6B5:
+ tmpImage = new video::CImage(video::ECF_A1R5G5B5,image);
+ deleteTmpImage=true;
+ break;
+ case video::ECF_A1R5G5B5:
+ case video::ECF_A8R8G8B8:
+ break;
+ case video::ECF_R8G8B8:
+ tmpImage = new video::CImage(video::ECF_A8R8G8B8,image);
+ deleteTmpImage=true;
+ break;
+ }*/
+ readPositions(tmpImage, lowerRightPositions);
+
+ WrongCharacter = getAreaFromCharacter(L' ');
+
+ // output warnings
+ if (!lowerRightPositions || !SpriteBank->getSprites().size())
+ std::cerr << "Either no upper or lower corner pixels in the font file. If this font was made using the new font tool, please load the XML file instead. If not, the font may be corrupted.\n";
+ else
+ if (lowerRightPositions != (s32)SpriteBank->getPositions().size())
+ std::cerr << "The amount of upper corner pixels and the lower corner pixels is not equal, font file may be corrupted.\n";
+
+ bool ret = ( !SpriteBank->getSprites().empty() && lowerRightPositions );
+
+ if ( ret )
+ {
+ bool flag[2];
+ flag[0] = Driver->getTextureCreationFlag ( video::ETCF_ALLOW_NON_POWER_2 );
+ flag[1] = Driver->getTextureCreationFlag ( video::ETCF_CREATE_MIP_MAPS );
+
+ Driver->setTextureCreationFlag(video::ETCF_ALLOW_NON_POWER_2, true);
+ Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false );
+
+ SpriteBank->addTexture(Driver->addTexture(name, tmpImage));
+
+ Driver->setTextureCreationFlag(video::ETCF_ALLOW_NON_POWER_2, flag[0] );
+ Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, flag[1] );
+ }
+ //if (deleteTmpImage)
+ // tmpImage->drop();
+ image->drop();
+
+ setMaxHeight();
+
+ return ret;
+}
+
+
+void ScalableFont::readPositions(video::IImage* image, s32& lowerRightPositions)
+{
+ const core::dimension2d size = image->getDimension();
+
+ video::SColor colorTopLeft = image->getPixel(0,0);
+ colorTopLeft.setAlpha(255);
+ image->setPixel(0,0,colorTopLeft);
+ video::SColor colorLowerRight = image->getPixel(1,0);
+ video::SColor colorBackGround = image->getPixel(2,0);
+ video::SColor colorBackGroundTransparent = 0;
+
+ image->setPixel(1,0,colorBackGround);
+
+ // start parsing
+
+ core::position2d pos(0,0);
+ for (pos.Y=0; pos.Y<(s32)size.Height; ++pos.Y)
+ {
+ for (pos.X=0; pos.X<(s32)size.Width; ++pos.X)
+ {
+ const video::SColor c = image->getPixel(pos.X, pos.Y);
+ if (c == colorTopLeft)
+ {
+ image->setPixel(pos.X, pos.Y, colorBackGroundTransparent);
+ SpriteBank->getPositions().push_back(core::rect(pos, pos));
+ }
+ else
+ if (c == colorLowerRight)
+ {
+ // too many lower right points
+ if (SpriteBank->getPositions().size()<=(u32)lowerRightPositions)
+ {
+ lowerRightPositions = 0;
+ return;
+ }
+
+ image->setPixel(pos.X, pos.Y, colorBackGroundTransparent);
+ SpriteBank->getPositions()[lowerRightPositions].LowerRightCorner = pos;
+ // add frame to sprite bank
+ SGUISpriteFrame f;
+ f.rectNumber = lowerRightPositions;
+ f.textureNumber = 0;
+ SGUISprite s;
+ s.Frames.push_back(f);
+ s.frameTime = 0;
+ SpriteBank->getSprites().push_back(s);
+ // add character to font
+ SFontArea a;
+ a.overhang = 0;
+ a.underhang = 0;
+ a.spriteno = lowerRightPositions;
+ a.width = SpriteBank->getPositions()[lowerRightPositions].getWidth();
+ Areas.push_back(a);
+ // map letter to character
+ wchar_t ch = (wchar_t)(lowerRightPositions + 32);
+ CharacterMap.set(ch, lowerRightPositions);
+
+ ++lowerRightPositions;
+ }
+ else
+ if (c == colorBackGround)
+ image->setPixel(pos.X, pos.Y, colorBackGroundTransparent);
+ }
+ }
+}
+
+
+//! set an Pixel Offset on Drawing ( scale position on width )
+void ScalableFont::setKerningWidth(s32 kerning)
+{
+ GlobalKerningWidth = kerning;
+}
+
+
+//! set an Pixel Offset on Drawing ( scale position on width )
+s32 ScalableFont::getKerningWidth(const wchar_t* thisLetter, const wchar_t* previousLetter) const
+{
+ s32 ret = GlobalKerningWidth;
+
+ if (thisLetter)
+ {
+ ret += Areas[getAreaFromCharacter(*thisLetter)].overhang;
+
+ if (previousLetter)
+ {
+ ret += Areas[getAreaFromCharacter(*previousLetter)].underhang;
+ }
+ }
+
+ return ret;
+}
+
+
+//! set an Pixel Offset on Drawing ( scale position on height )
+void ScalableFont::setKerningHeight(s32 kerning)
+{
+ GlobalKerningHeight = kerning;
+}
+
+
+//! set an Pixel Offset on Drawing ( scale position on height )
+s32 ScalableFont::getKerningHeight () const
+{
+ return GlobalKerningHeight;
+}
+
+
+//! returns the sprite number from a given character
+u32 ScalableFont::getSpriteNoFromChar(const wchar_t *c) const
+{
+ return Areas[getAreaFromCharacter(*c)].spriteno;
+}
+
+
+s32 ScalableFont::getAreaFromCharacter(const wchar_t c) const
+{
+ core::map::Node* n = CharacterMap.find(c);
+ if (n)
+ return n->getValue();
+ else
+ return WrongCharacter;
+}
+
+void ScalableFont::setInvisibleCharacters( const wchar_t *s )
+{
+ Invisible = s;
+}
+
+
+//! returns the dimension of text
+core::dimension2d ScalableFont::getDimension(const wchar_t* text) const
+{
+ core::dimension2d dim(0, 0);
+ core::dimension2d thisLine(0, MaxHeight);
+
+ for (const wchar_t* p = text; *p; ++p)
+ {
+ bool lineBreak=false;
+ if (*p == L'\r') // Windows breaks
+ {
+ lineBreak = true;
+ if (p[1] == L'\n') // Windows breaks
+ ++p;
+ }
+ else if (*p == L'\n') // Unix breaks
+ {
+ lineBreak = true;
+ }
+ if (lineBreak)
+ {
+ dim.Height += thisLine.Height;
+ if (dim.Width < thisLine.Width)
+ dim.Width = thisLine.Width;
+ thisLine.Width = 0;
+ continue;
+ }
+
+ const int areaID = getAreaFromCharacter(*p);
+ const SFontArea &area = Areas[areaID];
+
+ thisLine.Width += area.underhang;
+ thisLine.Width += area.width + area.overhang + GlobalKerningWidth;
+ }
+
+ dim.Height += thisLine.Height;
+ if (dim.Width < thisLine.Width)
+ dim.Width = thisLine.Width;
+
+ // std::cout << "ScalableFont::getDimension returns : " << dim.Width << ", " << dim.Height << " --> ";
+
+ dim.Width = (int)(dim.Width * m_scale);
+ dim.Height = (int)(dim.Height * m_scale);
+
+ //std::cout << dim.Width << ", " << dim.Height << std::endl;
+
+ return dim;
+}
+
+//! draws some text and clips it to the specified rectangle if wanted
+void ScalableFont::draw(const core::stringw& text, const core::rect& position,
+ video::SColor color, bool hcenter, bool vcenter, const core::rect* clip)
+{
+ if (!Driver)
+ return;
+
+ //color = video::SColor(255,255,255,255);
+
+ core::dimension2d textDimension;
+ core::position2d offset = position.UpperLeftCorner;
+
+ if (hcenter || vcenter || clip)
+ textDimension = getDimension(text.c_str());
+
+ if (hcenter)
+ {
+ offset.X += (position.getWidth() - textDimension.Width) >> 1;
+ }
+
+ if (vcenter)
+ offset.Y += (position.getHeight() - textDimension.Height) >> 1;
+
+ if (clip)
+ {
+ core::rect clippedRect(offset, textDimension);
+ clippedRect.clipAgainst(*clip);
+ if (!clippedRect.isValid())
+ return;
+ }
+
+ core::array indices(text.size());
+ core::array offsets(text.size());
+
+ for(u32 i = 0;i < text.size();i++)
+ {
+ wchar_t c = text[i];
+
+ bool lineBreak=false;
+ if ( c == L'\r') // Windows breaks
+ {
+ lineBreak = true;
+ if ( text[i + 1] == L'\n') // Windows breaks
+ c = text[++i];
+ }
+ else if ( c == L'\n') // Unix breaks
+ {
+ lineBreak = true;
+ }
+
+ if (lineBreak)
+ {
+ offset.Y += MaxHeight;
+ offset.X = position.UpperLeftCorner.X;
+
+ if ( hcenter )
+ {
+ core::dimension2d lineDim = getDimension(text.c_str());
+ offset.X += (position.getWidth() - lineDim.Width) >> 1;
+ }
+ continue;
+ }
+
+ const int areaID = getAreaFromCharacter(c);
+ //std::cout << "Char " << c << " has area " << areaID << std::endl;
+ SFontArea& area = Areas[areaID];
+
+ offset.X += area.underhang;
+ if ( Invisible.findFirst ( c ) < 0 )
+ {
+ indices.push_back(area.spriteno);
+ offsets.push_back(offset);
+ }
+
+ offset.X += (area.width + area.overhang + GlobalKerningWidth) * m_scale;
+ }
+
+ //SpriteBank->draw2DSpriteBatch(indices, offsets, clip, color);
+
+ const int indiceAmount = indices.size();
+ core::array< SGUISprite >& sprites = SpriteBank->getSprites();
+ core::array< core::rect >& positions = SpriteBank->getPositions();
+ video::IVideoDriver* driver = GUIEngine::getDriver();
+ const int spriteAmount = sprites.size();
+ for (int n=0; n= spriteAmount) continue;
+
+ assert(sprites[spriteID].Frames.size() > 0);
+ const int texID = sprites[spriteID].Frames[0].textureNumber;
+ core::rect source = positions[sprites[spriteID].Frames[0].rectNumber];
+
+ //std::cout << "Rendering " << source.UpperLeftCorner.X << ", " << source.UpperLeftCorner.Y << " to " <<
+ // offsets[n].X << ", " << offsets[n].Y << "; size = " << source.getWidth() << ", " << source.getHeight() << std::endl;
+
+ core::dimension2d size = source.getSize();
+ size.Width = (int)(size.Width * m_scale);
+ size.Height = (int)(size.Height * m_scale);
+ core::rect dest(offsets[n], size);
+ //std::cout << "source size = " << source.getWidth() << ", " << source.getHeight() << ", dest size = " << dest.getWidth() << ", " << dest.getHeight() << "; m_scale=" << m_scale << std::endl;
+
+ video::SColor colors[] = {color, color, color, color};
+
+ video::ITexture* texture = SpriteBank->getTexture(texID);
+ driver->draw2DImage(texture,
+ dest,
+ source,
+ clip,
+ colors, true);
+ }
+}
+
+
+//! Calculates the index of the character in the text which is on a specific position.
+s32 ScalableFont::getCharacterFromPos(const wchar_t* text, s32 pixel_x) const
+{
+ s32 x = 0;
+ s32 idx = 0;
+
+ while (text[idx])
+ {
+ const SFontArea& a = Areas[getAreaFromCharacter(text[idx])];
+
+ x += a.width + a.overhang + a.underhang + GlobalKerningWidth;
+
+ if (x >= pixel_x)
+ return idx;
+
+ ++idx;
+ }
+
+ return -1;
+}
+
+
+IGUISpriteBank* ScalableFont::getSpriteBank() const
+{
+ return SpriteBank;
+}
+
+} // end namespace gui
+} // end namespace irr
+
+
diff --git a/src/guiengine/CGUIFont.h b/src/guiengine/CGUIFont.h
new file mode 100644
index 000000000..27274412e
--- /dev/null
+++ b/src/guiengine/CGUIFont.h
@@ -0,0 +1,120 @@
+// Copyright (C) 2002-2009 Nikolaus Gebhardt
+// This file is part of the "Irrlicht Engine".
+// For conditions of distribution and use, see copyright notice in irrlicht.h
+
+#ifndef __C_GUI_FONT_H_INCLUDED__
+#define __C_GUI_FONT_H_INCLUDED__
+
+#include "IrrCompileConfig.h"
+
+#include "IGUIFontBitmap.h"
+#include "irrString.h"
+#include "irrMap.h"
+#include "IXMLReader.h"
+#include "IReadFile.h"
+#include "irrArray.h"
+
+namespace irr
+{
+
+namespace video
+{
+ class IVideoDriver;
+ class IImage;
+}
+
+namespace gui
+{
+
+ class IGUIEnvironment;
+
+class ScalableFont : public IGUIFontBitmap
+{
+ float m_scale;
+public:
+
+ //! constructor
+ ScalableFont(IGUIEnvironment* env, const io::path& filename);
+
+ //! destructor
+ virtual ~ScalableFont();
+
+ //! loads a font from a texture file
+ bool load(const io::path& filename);
+
+ //! loads a font from a texture file
+ bool load(io::IReadFile* file);
+
+ //! loads a font from an XML file
+ bool load(io::IXMLReader* xml);
+
+ //! draws an text and clips it to the specified rectangle if wanted
+ virtual void draw(const core::stringw& text, const core::rect& position,
+ video::SColor color, bool hcenter=false,
+ bool vcenter=false, const core::rect* clip=0);
+
+ //! returns the dimension of a text
+ virtual core::dimension2d getDimension(const wchar_t* text) const;
+
+ //! Calculates the index of the character in the text which is on a specific position.
+ virtual s32 getCharacterFromPos(const wchar_t* text, s32 pixel_x) const;
+
+ //! Returns the type of this font
+ virtual EGUI_FONT_TYPE getType() const { return EGFT_BITMAP; }
+
+ //! set an Pixel Offset on Drawing ( scale position on width )
+ virtual void setKerningWidth (s32 kerning);
+ virtual void setKerningHeight (s32 kerning);
+
+ //! set an Pixel Offset on Drawing ( scale position on width )
+ virtual s32 getKerningWidth(const wchar_t* thisLetter=0, const wchar_t* previousLetter=0) const;
+ virtual s32 getKerningHeight() const;
+
+ //! gets the sprite bank
+ virtual IGUISpriteBank* getSpriteBank() const;
+
+ //! returns the sprite number from a given character
+ virtual u32 getSpriteNoFromChar(const wchar_t *c) const;
+
+ virtual void setInvisibleCharacters( const wchar_t *s );
+
+ void setScale(const float scale);
+ float getScale() const { return m_scale; }
+
+private:
+
+ struct SFontArea
+ {
+ SFontArea() : underhang(0), overhang(0), width(0), spriteno(0) {}
+ s32 underhang;
+ s32 overhang;
+ s32 width;
+ u32 spriteno;
+ };
+
+ //! load & prepare font from ITexture
+ bool loadTexture(video::IImage * image, const io::path& name);
+
+ void readPositions(video::IImage* texture, s32& lowerRightPositions);
+
+ s32 getAreaFromCharacter (const wchar_t c) const;
+ void setMaxHeight();
+
+ core::array Areas;
+ core::map CharacterMap;
+ video::IVideoDriver* Driver;
+ IGUISpriteBank* SpriteBank;
+ IGUIEnvironment* Environment;
+ u32 WrongCharacter;
+ s32 MaxHeight;
+ s32 GlobalKerningWidth, GlobalKerningHeight;
+
+ core::stringw Invisible;
+};
+
+} // end namespace gui
+} // end namespace irr
+
+
+#endif // __C_GUI_FONT_H_INCLUDED__
+
diff --git a/src/guiengine/engine.cpp b/src/guiengine/engine.cpp
index e9017ea77..34934b7e1 100644
--- a/src/guiengine/engine.cpp
+++ b/src/guiengine/engine.cpp
@@ -23,6 +23,7 @@
#include "io/file_manager.hpp"
#include "input/input_manager.hpp"
+#include "guiengine/CGUIFont.h"
#include "guiengine/event_handler.hpp"
#include "guiengine/modaldialog.hpp"
#include "guiengine/screen.hpp"
@@ -41,6 +42,8 @@ namespace GUIEngine
IGUIEnvironment* g_env;
Skin* g_skin = NULL;
IGUIFont* g_font;
+ IGUIFont* g_title_font;
+
IrrlichtDevice* g_device;
IVideoDriver* g_driver;
Screen* g_current_screen = NULL;
@@ -185,8 +188,19 @@ void init(IrrlichtDevice* device_a, IVideoDriver* driver_a, AbstractStateManager
g_skin = new Skin(g_env->getSkin());
g_env->setSkin(g_skin);
//g_skin = g_env->getSkin();
- g_font = g_env->getFont( (file_manager->getGUIDir() + "/okolaks.xml").c_str() );
- if (g_font) g_skin->setFont(g_font);
+
+ // TODO: adapt font size depending on resolution
+ ScalableFont* sfont = new ScalableFont(g_env, (file_manager->getGUIDir() + "/okolaks.xml").c_str());
+ g_font = sfont;
+ //g_font = g_env->getFont( (file_manager->getGUIDir() + "/okolaks.xml").c_str() );
+
+ ScalableFont* sfont2 = new ScalableFont(g_env, (file_manager->getGUIDir() + "/title_font.xml").c_str());
+ sfont2->setScale(0.3f);
+ sfont2->setKerningWidth(-18);
+ g_title_font = sfont2;
+
+
+ if (g_font != NULL) g_skin->setFont(g_font);
//g_skin->setFont(g_env->getBuiltInFont(), EGDF_TOOLTIP);
diff --git a/src/guiengine/engine.hpp b/src/guiengine/engine.hpp
index e63b396f8..8e69b3e8a 100644
--- a/src/guiengine/engine.hpp
+++ b/src/guiengine/engine.hpp
@@ -59,8 +59,9 @@ be clickable. PROP_ICON is mandatory for this component.
WTYPE_CHECKBOX "checkbox"
A checkbox. Not used at the moment.
-WTYPE_LABEL "label"
+WTYPE_LABEL "label" "header"
A plain label. Supports properties PROP_WORD_WRAP and PROP_TEXT_ALIGN.
+The "Header" variant uses a bigger and more colourful font.
WTYPE_SPACER "spacer"
Some blank space; not visible on screen.
@@ -235,6 +236,8 @@ namespace GUIEngine
extern irr::gui::IGUIEnvironment* g_env;
extern Skin* g_skin;
extern irr::gui::IGUIFont* g_font;
+ extern irr::gui::IGUIFont* g_title_font;
+
extern IrrlichtDevice* g_device;
extern irr::video::IVideoDriver* g_driver;
extern Screen* g_current_screen;
@@ -246,6 +249,7 @@ namespace GUIEngine
inline irr::gui::IGUIEnvironment* getGUIEnv() { return Private::g_env; }
inline irr::video::IVideoDriver* getDriver() { return Private::g_driver; }
inline irr::gui::IGUIFont* getFont() { return Private::g_font; }
+ inline irr::gui::IGUIFont* getTitleFont() { return Private::g_title_font; }
inline Screen* getCurrentScreen() { return Private::g_current_screen; }
inline AbstractStateManager* getStateManager() { return Private::g_state_manager; }
diff --git a/src/guiengine/screen_loader.cpp b/src/guiengine/screen_loader.cpp
index 4c798e8b5..bf83dd478 100644
--- a/src/guiengine/screen_loader.cpp
+++ b/src/guiengine/screen_loader.cpp
@@ -119,6 +119,10 @@ void parseScreenFileDiv(irr::io::IrrXMLReader* xml, ptr_vector& append_t
{
append_to.push_back(new LabelWidget());
}
+ else if (!strcmp("header", xml->getNodeName()))
+ {
+ append_to.push_back(new LabelWidget(true));
+ }
else if (!strcmp("spacer", xml->getNodeName()))
{
append_to.push_back(new Widget());
diff --git a/src/guiengine/widget.cpp b/src/guiengine/widget.cpp
index 03e556463..cb892a394 100644
--- a/src/guiengine/widget.cpp
+++ b/src/guiengine/widget.cpp
@@ -62,6 +62,7 @@ Widget::Widget(bool reserve_id)
h = -1;
id = -1;
m_element = NULL;
+ m_title_font = false;
m_type = WTYPE_NONE;
m_event_handler = NULL;
@@ -283,12 +284,12 @@ void Widget::readCoords(Widget* parent)
texture_h = texture->getSize().Height;
}
}
-
- // ---- if this widget has a label, get text length. this can helpful determine its optimal size
+
+ // ---- if this widget has a label, get text size. this can helpful determine its optimal size
int label_w = -1, label_h = -1;
if (m_text.size() > 0)
{
- IGUIFont* font = GUIEngine::getFont();
+ IGUIFont* font = (m_title_font ? GUIEngine::getTitleFont() : GUIEngine::getFont());
core::dimension2d< u32 > dim = font->getDimension( m_text.c_str() );
label_w = dim.Width;
// FIXME - won't work with multiline labels. thus, for now, when multiple
@@ -317,7 +318,7 @@ void Widget::readCoords(Widget* parent)
if(abs_h > -1) this->h = abs_h;
else if(percent_h > -1) this->h = parent_h*percent_h/100;
}
- else if(texture_h > -1 && label_h > -1) this->h = texture_h + label_h;
+ else if(texture_h > -1 && label_h > -1) this->h = texture_h + label_h; // label + icon
else if(texture_h > -1) this->h = texture_h;
else if(label_h > -1) this->h = label_h;
}
@@ -349,8 +350,7 @@ void Widget::readCoords(Widget* parent)
{
const int max_height = atoi( this->m_properties[PROP_MAX_HEIGHT].c_str() );
if(this->h > max_height) this->h = max_height;
- }
-
+ }
}
void Widget::setParent(IGUIElement* parent)
diff --git a/src/guiengine/widget.hpp b/src/guiengine/widget.hpp
index 8888f16dd..af02c9fe4 100644
--- a/src/guiengine/widget.hpp
+++ b/src/guiengine/widget.hpp
@@ -100,7 +100,9 @@ namespace GUIEngine
friend class Skin;
friend class DynamicRibbonWidget;
-
+ /** When true, this widget shall use a bigger and more colourful font */
+ bool m_title_font;
+
/**
* Can be used in children to indicate whether a widget is selected or not
* - in widgets where it makes sense (e.g. ribbon children) and where the
diff --git a/src/guiengine/widgets/label_widget.cpp b/src/guiengine/widgets/label_widget.cpp
index 85b51db7c..d610afae6 100644
--- a/src/guiengine/widgets/label_widget.cpp
+++ b/src/guiengine/widgets/label_widget.cpp
@@ -21,9 +21,10 @@ using namespace GUIEngine;
using namespace irr::core;
using namespace irr::gui;
-LabelWidget::LabelWidget()
+LabelWidget::LabelWidget(bool title)
{
m_type = WTYPE_LABEL;
+ m_title_font = title;
}
// -----------------------------------------------------------------------------
void LabelWidget::add()
@@ -41,6 +42,12 @@ void LabelWidget::add()
m_element = irrwidget;
irrwidget->setTextAlignment( align, valign );
+ if (m_title_font)
+ {
+ irrwidget->setOverrideColor( video::SColor(255,255,255,255) );
+ irrwidget->setOverrideFont( GUIEngine::getTitleFont() );
+ }
+
id = m_element->getID();
//m_element->setTabOrder(id);
m_element->setTabStop(false);
diff --git a/src/guiengine/widgets/label_widget.hpp b/src/guiengine/widgets/label_widget.hpp
index f5a2fd48d..bb8c4066f 100644
--- a/src/guiengine/widgets/label_widget.hpp
+++ b/src/guiengine/widgets/label_widget.hpp
@@ -31,7 +31,7 @@ namespace GUIEngine
class LabelWidget : public Widget
{
public:
- LabelWidget();
+ LabelWidget(bool title=false);
virtual ~LabelWidget() {}
void add();
diff --git a/src/ide/Xcode/STK_XCode.xcodeproj/project.pbxproj b/src/ide/Xcode/STK_XCode.xcodeproj/project.pbxproj
index 2386f1513..c9a785940 100644
--- a/src/ide/Xcode/STK_XCode.xcodeproj/project.pbxproj
+++ b/src/ide/Xcode/STK_XCode.xcodeproj/project.pbxproj
@@ -54,6 +54,7 @@
952A1554103F68D000B1895D /* profile_world.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 952A1552103F68D000B1895D /* profile_world.cpp */; };
953789730FC7829100DD1F8E /* graph_node.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 953789720FC7829100DD1F8E /* graph_node.cpp */; };
953789820FC7831400DD1F8E /* quad.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 953789810FC7831400DD1F8E /* quad.cpp */; };
+ 953C3CCA10CAF3EE0025F78A /* CGUIFont.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 953C3CC910CAF3EE0025F78A /* CGUIFont.cpp */; };
954E4C2D0FF98B6F0047FE3E /* animation_base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 954E4C250FF98B6E0047FE3E /* animation_base.cpp */; };
954E4C2E0FF98B6F0047FE3E /* animation_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 954E4C270FF98B6E0047FE3E /* animation_manager.cpp */; };
954E4C2F0FF98B6F0047FE3E /* billboard_animation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 954E4C290FF98B6E0047FE3E /* billboard_animation.cpp */; };
@@ -399,6 +400,8 @@
953789720FC7829100DD1F8E /* graph_node.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = graph_node.cpp; path = ../../tracks/graph_node.cpp; sourceTree = SOURCE_ROOT; };
953789800FC7831400DD1F8E /* quad.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = quad.hpp; path = ../../tracks/quad.hpp; sourceTree = SOURCE_ROOT; };
953789810FC7831400DD1F8E /* quad.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = quad.cpp; path = ../../tracks/quad.cpp; sourceTree = SOURCE_ROOT; };
+ 953C3CC910CAF3EE0025F78A /* CGUIFont.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CGUIFont.cpp; path = ../../guiengine/CGUIFont.cpp; sourceTree = SOURCE_ROOT; };
+ 953C3CCD10CAF4150025F78A /* CGUIFont.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CGUIFont.h; path = ../../guiengine/CGUIFont.h; sourceTree = SOURCE_ROOT; };
953EAAAD0F30A4220000D57D /* terrain_info.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = terrain_info.hpp; path = ../../tracks/terrain_info.hpp; sourceTree = SOURCE_ROOT; };
953EAAAE0F30A4220000D57D /* terrain_info.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = terrain_info.cpp; path = ../../tracks/terrain_info.cpp; sourceTree = SOURCE_ROOT; };
953EAAB00F30A4410000D57D /* triangle_mesh.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = triangle_mesh.hpp; path = ../../physics/triangle_mesh.hpp; sourceTree = SOURCE_ROOT; };
@@ -1230,6 +1233,8 @@
958330B110122B4A00C5137E /* guiengine */ = {
isa = PBXGroup;
children = (
+ 953C3CC910CAF3EE0025F78A /* CGUIFont.cpp */,
+ 953C3CCD10CAF4150025F78A /* CGUIFont.h */,
9583319810123B0200C5137E /* abstract_state_manager.cpp */,
9583319710123B0200C5137E /* abstract_state_manager.hpp */,
958330B210122B4A00C5137E /* engine.cpp */,
@@ -2558,6 +2563,7 @@
9522F1F1107961560067ECF5 /* options_screen_players.cpp in Sources */,
951B7D19108E52C900BC03AE /* challenges.cpp in Sources */,
95FB16DB10A7796800645974 /* new_ai.cpp in Sources */,
+ 953C3CCA10CAF3EE0025F78A /* CGUIFont.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/src/states_screens/credits.cpp b/src/states_screens/credits.cpp
index 800fedd4f..b4dba7055 100644
--- a/src/states_screens/credits.cpp
+++ b/src/states_screens/credits.cpp
@@ -148,14 +148,15 @@ namespace GUIEngine
// ---- section name
video::SColor color( 255 /* a */, 0 /* r */, 0 /* g */ , 75 /* b */ );
-
+ video::SColor white_color( 255, 255, 255, 255 );
+
// manage fade-in
if (before_first_elem)
{
int alpha = 255 - (int)(time_before_next_step/TIME_SECTION_FADE * 255);
if(alpha < 0) alpha = 0;
else if(alpha > 255) alpha = 255;
- color.setAlpha( alpha );
+ white_color.setAlpha( alpha );
}
// manage fade-out
else if (after_last_elem)
@@ -163,10 +164,10 @@ namespace GUIEngine
int alpha = (int)(time_before_next_step/TIME_SECTION_FADE * 255);
if(alpha < 0) alpha = 0;
else if(alpha > 255) alpha = 255;
- color.setAlpha( alpha );
+ white_color.setAlpha( alpha );
}
- GUIEngine::getFont()->draw(m_sections[m_curr_section].m_name.c_str(), m_section_rect, color,
+ GUIEngine::getTitleFont()->draw(m_sections[m_curr_section].m_name.c_str(), m_section_rect, white_color,
true /* center h */, true /* center v */ );
// draw entries