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; } } }