sf::RichText is an expansion I've just made. The point is to have something like sf::Text but with the power of having differente styles in it.

Be careful, '\n' characters are not supported. You can use it, but you will see visual errors! (try it)

Example.cpp

#include "RichText.hpp"
#include <Sfml/Graphics.hpp>
 
int main()
{
	sf::RichText text;
	text << sf::Text::Bold << sf::Color::Cyan << "This"
		<< sf::Text::Italic << sf::Color::White << " is cool "
		<< sf::Text::Regular << sf::Color::Green << "mate"
		<< sf::Color::White << ". "
		<< sf::Text::Underlined << "I wish I could lick it!";
 
	text.SetCharacterSize(25);
	text.SetOrigin(text.GetWidth()/2.f, text.GetHeight()/2.f);
 
	sf::RenderWindow window;
	window.Create(sf::VideoMode(800, 600), "Rich text");
 
	while(window.IsOpened())
	{
		sf::Event event;
		while(window.GetEvent(event)
		{
			if(event.Type == sf::Event::Closed) window.Close();
		}
 
		window.Clear();
		window.Draw(text);
		window.Display();
	}
}

RichText.hpp

#pragma once
 
//////////////////////////////////////////////////////////////////////////
// Headers
//////////////////////////////////////////////////////////////////////////
#include <Sfml/Graphics/Drawable.hpp>
#include <Sfml/Graphics/Color.hpp>
#include <Sfml/Graphics/Text.hpp>
#include <Sfml/System/String.hpp>
#include <list>
 
namespace sf
{
	class RichText : public sf::Drawable
	{
	public:
		//////////////////////////////////////////////////////////////////////////
		// Constructor
		//////////////////////////////////////////////////////////////////////////
		RichText();
 
		//////////////////////////////////////////////////////////////////////////
		// Operators
		//////////////////////////////////////////////////////////////////////////
		RichText & operator << (const sf::Color &color);
		RichText & operator << (sf::Text::Style style);
		RichText & operator << (const sf::String &string);
 
		//////////////////////////////////////////////////////////////////////////
		// Set character size
		//////////////////////////////////////////////////////////////////////////
		void SetCharacterSize(unsigned int size);
 
		//////////////////////////////////////////////////////////////////////////
		// Set font
		//////////////////////////////////////////////////////////////////////////
		void SetFont(const sf::Font &font);
 
		//////////////////////////////////////////////////////////////////////////
		// Clear
		//////////////////////////////////////////////////////////////////////////
		void Clear();
 
		//////////////////////////////////////////////////////////////////////////
		// Get text list
		//////////////////////////////////////////////////////////////////////////
		const std::list<sf::Text> &GetTextList() const;
 
		//////////////////////////////////////////////////////////////////////////
		// Get character size
		//////////////////////////////////////////////////////////////////////////
		unsigned int GetCharacterSize() const;
 
		//////////////////////////////////////////////////////////////////////////
		// Get font
		//////////////////////////////////////////////////////////////////////////
		const sf::Font & GetFont() const;
 
		//////////////////////////////////////////////////////////////////////////
		// Get width
		//////////////////////////////////////////////////////////////////////////
		float GetWidth() const;
 
		//////////////////////////////////////////////////////////////////////////
		// Get height
		//////////////////////////////////////////////////////////////////////////
		float GetHeight() const;
 
	private:
		//////////////////////////////////////////////////////////////////////////
		// Update size
		//////////////////////////////////////////////////////////////////////////
		void UpdateSize() const;
 
		//////////////////////////////////////////////////////////////////////////
		// Update position
		//////////////////////////////////////////////////////////////////////////
		void UpdatePosition() const;
 
		//////////////////////////////////////////////////////////////////////////
		// Render
		//////////////////////////////////////////////////////////////////////////
		void Render(RenderTarget& target, Renderer& renderer) const;
 
		//////////////////////////////////////////////////////////////////////////
		// Member data
		//////////////////////////////////////////////////////////////////////////
		mutable std::list<sf::Text> myTexts;	///< List of texts
		sf::Color myCurrentColor;				///< Last used color
		sf::Text::Style myCurrentStyle;			///< Last style used
		mutable sf::Vector2f mySize;			///< Size of the text
		mutable bool mySizeUpdated;				///< Do we need to recompute the size ?
		mutable bool myPositionUpdated;			///< Do we need to recompute the position ?
	};
}

RichText.cpp

//////////////////////////////////////////////////////////////////////////
// Headers
//////////////////////////////////////////////////////////////////////////
#include "RichText.hpp"
#include <Sfml/Graphics/RenderTarget.hpp>
#include <iostream>
 
namespace sf
{
	RichText::RichText()
		: myCurrentColor(sf::Color::White), myCurrentStyle(sf::Text::Regular), mySizeUpdated(false), myPositionUpdated(false)
	{
 
	}
 
	//////////////////////////////////////////////////////////////////////////
	// Operator << sf::Color
	//////////////////////////////////////////////////////////////////////////
	RichText & RichText::operator << (const sf::Color &color)
	{
		myCurrentColor = color;
		return *this;
	}
 
	//////////////////////////////////////////////////////////////////////////
	// Operator << sf::Text::Style
	//////////////////////////////////////////////////////////////////////////
	RichText & RichText::operator << (sf::Text::Style style)
	{
		myCurrentStyle = style;
		return *this;
	}
 
	//////////////////////////////////////////////////////////////////////////
	// Operator << sf::String
	//////////////////////////////////////////////////////////////////////////
	/*
	**	Must parse the strings to look for '\n' characters. If found, we break
	**	the string into two pieces.
	*/
	RichText & RichText::operator << (const sf::String &string)
	{
		// It is not updated
		mySizeUpdated = false;
		myPositionUpdated = false;
 
		// Find \n characters (assert)
		//assert(string.Find('\n') == std::string::npos);
		if(string.Find('\n') != std::string::npos) std::cerr << "sf::RichtText: Oops, character \\n found. You will get visual errors." << std::endl;
 
		// Add string
		myTexts.resize(myTexts.size()+1);
 
		// Setup string
		sf::Text &text = *(--myTexts.end());
		text.SetColor(myCurrentColor);
		text.SetStyle(myCurrentStyle);
		text.SetString(string);
 
		// Return
		return *this;
	}
 
	//////////////////////////////////////////////////////////////////////////
	// Set size
	//////////////////////////////////////////////////////////////////////////
	void RichText::SetCharacterSize(unsigned int size)
	{
		// Set character size
		for(std::list<sf::Text>::iterator it = myTexts.begin(); it != myTexts.end(); ++it)
		{
			it->SetCharacterSize(size);
		}
 
		// It is not updated
		mySizeUpdated = false;
		myPositionUpdated = false;
	}
 
	//////////////////////////////////////////////////////////////////////////
	// Set font
	//////////////////////////////////////////////////////////////////////////
	void RichText::SetFont(const sf::Font &font)
	{
		// Set character size
		for(std::list<sf::Text>::iterator it = myTexts.begin(); it != myTexts.end(); ++it)
		{
			it->SetFont(font);
		}
 
		// It is not updated
		mySizeUpdated = false;
		myPositionUpdated = false;
	}
 
	//////////////////////////////////////////////////////////////////////////
	// Clear
	//////////////////////////////////////////////////////////////////////////
	void RichText::Clear()
	{
		// Clear text list
		myTexts.clear();
 
		// Reset size
		mySize = sf::Vector2f(0.f, 0.f);
 
		// It is updated
		mySizeUpdated = true;
		myPositionUpdated = true;
	}
 
	//////////////////////////////////////////////////////////////////////////
	// Get text list
	//////////////////////////////////////////////////////////////////////////
	const std::list<sf::Text> & RichText::GetTextList() const
	{
		return myTexts;
	}
 
	//////////////////////////////////////////////////////////////////////////
	// Get character size
	//////////////////////////////////////////////////////////////////////////
	unsigned int RichText::GetCharacterSize() const
	{
		if(myTexts.size()) return myTexts.begin()->GetCharacterSize();
		return 0;
	}
 
	//////////////////////////////////////////////////////////////////////////
	// Get font
	//////////////////////////////////////////////////////////////////////////
	const sf::Font & RichText::GetFont() const
	{
		if(myTexts.size()) return myTexts.begin()->GetFont();
		return sf::Font::GetDefaultFont();
	}
 
	//////////////////////////////////////////////////////////////////////////
	// Get width
	//////////////////////////////////////////////////////////////////////////
	float RichText::GetWidth() const
	{
		UpdateSize();
		return mySize.x;
	}
 
	//////////////////////////////////////////////////////////////////////////
	// Get height
	//////////////////////////////////////////////////////////////////////////
	float RichText::GetHeight() const
	{
		UpdateSize();
		return mySize.y;
	}
 
	//////////////////////////////////////////////////////////////////////////
	// Render
	//////////////////////////////////////////////////////////////////////////
	void RichText::Render(RenderTarget& target, Renderer& renderer) const
	{
		// Update position
		UpdatePosition();
 
		// Draw
		for(std::list<sf::Text>::const_iterator it = myTexts.begin(); it != myTexts.end(); ++it)
		{
			// Draw text
			target.Draw(*it);
		}
	}
 
	//////////////////////////////////////////////////////////////////////////
	// Update size
	//////////////////////////////////////////////////////////////////////////
	void RichText::UpdateSize() const
	{
		// Return if updated
		if(mySizeUpdated) return;
 
		// Return if empty
		if(myTexts.begin() == myTexts.end()) return;
 
		// It is updated
		mySizeUpdated = true;
 
		// Sum all sizes (height not implemented)
		mySize.x = 0.f;
		mySize.y = myTexts.begin()->GetRect().Height;
		for(std::list<sf::Text>::const_iterator it = myTexts.begin(); it != myTexts.end(); ++it)
		{
			// Update width
			mySize.x += it->GetRect().Width;
		}
	}
 
	//////////////////////////////////////////////////////////////////////////
	// Update position
	//////////////////////////////////////////////////////////////////////////
	void RichText::UpdatePosition() const
	{
		// Return if updated
		if(myPositionUpdated) return;
 
		// Return if empty
		if(myTexts.begin() == myTexts.end()) return;
 
		// It is updated
		myPositionUpdated = true;
 
		// Get starting position
		sf::Vector2f offset;
 
		// Draw
		for(std::list<sf::Text>::iterator it = myTexts.begin(); it != myTexts.end(); ++it)
		{
			// Set all the origins to the first one
			it->SetOrigin(it->GetPosition() - myTexts.begin()->GetPosition() - offset);
 
			// Set offset
			const sf::FloatRect rect = it->GetRect();
			offset.x += rect.Width;
		}
	}
}
 
en/sources/richtext.txt · Last modified: 2010/08/10 20:58 by panithadrum
 
Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki