summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEkaitz Zarraga <ekaitz@elenq.tech>2022-12-13 19:35:48 +0100
committerEkaitz Zarraga <ekaitz@elenq.tech>2022-12-13 19:35:48 +0100
commite45e92e0ff294e6a1899b01b8cfdd8ab25d8dcdc (patch)
tree6021345d94502db896ca0174abf270b51e89e306
parent70c0be5b2cfb3b9cfe86d5a6e6624e28fb845453 (diff)
Make a better text rendering system and a simple example in titlestate
-rw-r--r--src/graphics/text.cpp79
-rw-r--r--src/graphics/text.h48
-rw-r--r--src/graphics/textureFont.cpp48
-rw-r--r--src/graphics/textureFont.h10
-rw-r--r--src/states/titleState.cpp26
-rw-r--r--src/ui.cpp21
-rw-r--r--src/ui.h5
7 files changed, 156 insertions, 81 deletions
diff --git a/src/graphics/text.cpp b/src/graphics/text.cpp
index 82b8811..43e8be1 100644
--- a/src/graphics/text.cpp
+++ b/src/graphics/text.cpp
@@ -2,36 +2,61 @@
using namespace Graphics;
-Text::Text(TextureFont &font, const std::string &text)
- : font_(font)
- , text_(text)
- , vertices_(sf::Quads, text.size()*4)
-{
- unsigned int length = vertices_.getVertexCount();
- sf::Vector2f glyphSize = font_.getGlyphSize();
- // TODO: this is the simplest rendering way: everything in one line
- // we should improve this to make it handle newlines or max witdths
- for(unsigned int i=0; i < length; i=i+4){
- vertices_[i+0].position = sf::Vector2f(glyphSize.x * i/4, 0);
- vertices_[i+1].position = sf::Vector2f(glyphSize.x * (i/4 + 1), 0);
- vertices_[i+2].position = sf::Vector2f(glyphSize.x * (i/4 + 1), glyphSize.y);
- vertices_[i+3].position = sf::Vector2f(glyphSize.x * i/4, glyphSize.y);
+template <>
+void Text<TextureFont>::arrange(TextureFont &font){
+ // TODO: this is really awful rendering but works a little bit
+ unsigned int filledX = 0;
+ unsigned int row = 0;
+ unsigned int col = 0;
- std::array<sf::Vector2f, 4> glyph = font_.getGlyphMapping(text_[i/4]);
+ for(unsigned int i=0; i < text_.length(); i++){
+ sf::Glyph glyph = font.getGlyph( text_[i] );
+ filledX += glyph.advance;
+ if (maxWidth_ != 0 && ( text_[i] == '\n' || filledX > maxWidth_)){
+ row++;
+ filledX = 0;
+ col = 0;
+ if(text_[i] == '\n') continue;
+ }
- vertices_[i+0].texCoords = glyph[0];
- vertices_[i+1].texCoords = glyph[1];
- vertices_[i+2].texCoords = glyph[2];
- vertices_[i+3].texCoords = glyph[3];
+ vertices_[4*i+0].position = sf::Vector2f(
+ col*glyph.advance + glyph.bounds.left,
+ (glyph.bounds.top) + row * glyph.bounds.height
+ );
+ vertices_[4*i+1].position = sf::Vector2f(
+ col*glyph.advance + glyph.bounds.left+glyph.bounds.width,
+ (glyph.bounds.top) + row * glyph.bounds.height
+ );
+ vertices_[4*i+2].position = sf::Vector2f(
+ col*glyph.advance + glyph.bounds.left+glyph.bounds.width,
+ (glyph.bounds.top+glyph.bounds.height) + row * glyph.bounds.height
+ );
+ vertices_[4*i+3].position = sf::Vector2f(
+ col*glyph.advance + glyph.bounds.left,
+ (glyph.bounds.top+glyph.bounds.height) + row * glyph.bounds.height
+ );
+ col++;
+
+ vertices_[4*i+0].texCoords = sf::Vector2f(
+ glyph.textureRect.left,
+ glyph.textureRect.top
+ );
+ vertices_[4*i+1].texCoords = sf::Vector2f(
+ glyph.textureRect.left+glyph.textureRect.width,
+ glyph.textureRect.top
+ );
+ vertices_[4*i+2].texCoords = sf::Vector2f(
+ glyph.textureRect.left+glyph.textureRect.width,
+ glyph.textureRect.top+glyph.textureRect.height
+ );
+ vertices_[4*i+3].texCoords = sf::Vector2f(
+ glyph.textureRect.left,
+ glyph.textureRect.top+glyph.textureRect.height
+ );
}
}
-void Text::draw(sf::RenderTarget& target, sf::RenderStates states) const
-{
- // TODO: only repaint if needed: when repainting is needed
- // vertices_.clear() and fun
- states.transform *= getTransform();
- states.texture = font_.getTexture();
- // you may also override states.shader or states.blendMode if you want
- target.draw(vertices_, states);
+template <>
+void Text<sf::Font>::arrange(sf::Font &font){
+ // TODO: Implement this function for a generic sf::Font
}
diff --git a/src/graphics/text.h b/src/graphics/text.h
index 22179f5..f60980c 100644
--- a/src/graphics/text.h
+++ b/src/graphics/text.h
@@ -3,15 +3,59 @@
#include"textureFont.h"
namespace Graphics {
+
+ template<typename Font>
class Text : public sf::Drawable, public sf::Transformable {
private:
- TextureFont &font_;
+ Font &font_;
const std::string text_;
sf::VertexArray vertices_;
+ unsigned int size_, maxWidth_, maxHeight_;
+
+ void arrange(Font &font); // Specialize for sf::Font and TextureFont
+
public:
- Text(TextureFont &font, const std::string &text);
+ Text(Font &font, const std::string &text, unsigned int maxWidth=0,
+ unsigned int maxHeight=0);
+
+ void setFont(Font &font);
+ void setText(const std::string &text);
+
virtual void draw(sf::RenderTarget& target,
sf::RenderStates states) const override;
};
+
+ template <typename Font>
+ Text<Font>::Text(Font &font, const std::string &text,
+ unsigned int maxWidth, unsigned int maxHeight)
+ : font_(font)
+ , text_(text)
+ , vertices_(sf::Quads, text.size()*4)
+ , size_(0)
+ , maxWidth_(maxWidth)
+ , maxHeight_(maxHeight)
+ {
+ arrange(font);
+ }
+
+
+ template <typename Font>
+ void Text<Font>::draw(sf::RenderTarget& target, sf::RenderStates states) const
+ {
+ // TODO: only repaint if needed: when repainting is needed
+ // vertices_.clear() and fun
+ states.transform *= getTransform();
+ states.texture = font_.getTexture(size_);
+ // you may also override states.shader or states.blendMode if you want
+ target.draw(vertices_, states);
+ }
+
+ template <typename Font>
+ void Text<Font>::setFont(Font &font){
+ font_ = font;
+ arrange(font);
+ }
}
+
+
#endif // GRAPHICS_TEXT_H
diff --git a/src/graphics/textureFont.cpp b/src/graphics/textureFont.cpp
index 29f9c71..3be2444 100644
--- a/src/graphics/textureFont.cpp
+++ b/src/graphics/textureFont.cpp
@@ -8,37 +8,35 @@ TextureFont::TextureFont(const sf::Texture &texture,
, description_(description)
{
sf::Vector2u totalSize = tex_.getSize();
- sf::Vector2f totalSize_f (totalSize.x, totalSize.y);
- glyphSize_ = sf::Vector2f( totalSize.x / description_.numcols,
+ glyphSize_ = sf::Vector2i( totalSize.x / description_.numcols,
totalSize.y / description_.numrows );
-}
-std::array<sf::Vector2f, 4> TextureFont::getGlyphMapping(const char ch){
- unsigned int pos = static_cast<unsigned int>( description_.mapping.find_first_of(ch));
- if (pos == std::string::npos){
- // TODO: Error handling!
- pos = 0;
+ for(unsigned int i=0; i<description.mapping.size(); i++){
+ sf::Glyph glyph;
+ glyph.advance = glyphSize_.x;
+
+ unsigned int x = i % description_.numcols;
+ unsigned int y = (i - x) / description_.numcols;
+
+ glyph.textureRect = sf::IntRect(x*glyphSize_.x,
+ y*glyphSize_.y,
+ glyphSize_.x,
+ glyphSize_.y);
+
+ glyph.bounds = sf::FloatRect(0,
+ 0,
+ glyphSize_.x,
+ glyphSize_.y);
+
+ glyphTable_.insert(std::make_pair(description.mapping[i], glyph));
}
- unsigned int x = pos % description_.numcols;
- unsigned int y = (pos - x) / description_.numcols;
-
- sf::Vector2f basePos(x*glyphSize_.x, y*glyphSize_.y);
-
- // 1 --- 2
- // | |
- // 4 --- 3
- return std::array<sf::Vector2f,4> {
- basePos,
- basePos + sf::Vector2f( glyphSize_.x, 0 ),
- basePos + glyphSize_,
- basePos + sf::Vector2f( 0, glyphSize_.y ),
- };
}
-sf::Vector2f TextureFont::getGlyphSize(){
- return glyphSize_;
+const sf::Glyph & TextureFont::getGlyph(char ch) const{
+ auto pair = glyphTable_.find(ch);
+ return pair->second;
}
-const sf::Texture * TextureFont::getTexture(){
+const sf::Texture * TextureFont::getTexture(unsigned int _){
return &tex_;
}
diff --git a/src/graphics/textureFont.h b/src/graphics/textureFont.h
index 5e78f9e..f3f194a 100644
--- a/src/graphics/textureFont.h
+++ b/src/graphics/textureFont.h
@@ -13,14 +13,16 @@ namespace Graphics {
unsigned int numrows, numcols;
};
private:
+ using GlyphTable = std::map<char, sf::Glyph>;
+ GlyphTable glyphTable_;
+
const sf::Texture &tex_;
const Descr description_;
- sf::Vector2f glyphSize_;
+ sf::Vector2i glyphSize_;
public:
TextureFont(const sf::Texture &texture, Descr desc);
- std::array<sf::Vector2f,4> getGlyphMapping(const char ch);
- sf::Vector2f getGlyphSize();
- const sf::Texture *getTexture();
+ const sf::Glyph &getGlyph(char ch) const;
+ const sf::Texture *getTexture(unsigned int _);
};
}
diff --git a/src/states/titleState.cpp b/src/states/titleState.cpp
index d96c840..fe78d45 100644
--- a/src/states/titleState.cpp
+++ b/src/states/titleState.cpp
@@ -8,7 +8,11 @@ TitleState::TitleState(StateStack &stack, State::Context context)
// TODO: Initialize UI properly to zeros
//, ui(0,0,false,false,0,0)
{
-
+ context.textures->load(Textures::Id::Base_Font, "assets/img/Font/Font.png");
+ auto &fontTexture = context.textures->get(Textures::Id::Base_Font);
+ Graphics::TextureFont::Descr fontDescr {"abcdefghijklmnopqrstuvwxyz1234567890!?.,$ ", 6,7};
+ auto font = new Graphics::TextureFont(fontTexture, fontDescr);
+ context.textureFonts->manage(Fonts::Id::Base_Font, font);
}
void TitleState::update(sf::Time dt){
@@ -20,22 +24,16 @@ void TitleState::render(){
ui.initImUI();
- if (ui.button(context_.window, 17, "Button 1", sf::Vector2i(0,0), sf::Vector2i(200,100)) ){
- printf("Button 1 pressed!!\n");
- }
- if (ui.button(context_.window, 18, "Button 2", sf::Vector2i(0,200), sf::Vector2i(200,100)) ){
- printf("Button 2 pressed!!\n");
- }
- if (ui.button(context_.window, 19, "Button 3", sf::Vector2i(0,400), sf::Vector2i(200,100)) ){
- printf("Button 3 pressed!!\n");
- }
-
+ Graphics::TextureFont &font = context_.textureFonts->get(Fonts::Id::Base_Font);
- radioState = ui.radioButton(context_.window, 21, "Radio", radioState,
- sf::Vector2i(0,800), sf::Vector2i(200,100));
+ radioState = ui.radioButton(context_.window,
+ font, 21,
+ "this is\nthe whole thing or maybe is just another bullshit code it doesn't work",
+ radioState,
+ sf::Vector2i(0,100), sf::Vector2i(200,50));
if (radioState){
- ui.button(context_.window, 20, "Hidden button", sf::Vector2i(0,600), sf::Vector2i(200,100));
+ ui.button(context_.window, 20, "Hidden button", sf::Vector2i(0,200), sf::Vector2i(200,100));
}
ui.finishImUI();
diff --git a/src/ui.cpp b/src/ui.cpp
index 7f4c1ea..722eb1b 100644
--- a/src/ui.cpp
+++ b/src/ui.cpp
@@ -148,8 +148,9 @@ bool UI::button(sf::RenderWindow *win, int id, const std::string &text,
return result;
}
-bool UI::radioButton(sf::RenderWindow *win, int id, const std::string &text,
- bool state, sf::Vector2i pos, sf::Vector2i size){
+bool UI::radioButton(sf::RenderWindow *win, Graphics::TextureFont font,
+ int id, const std::string &text, bool state, sf::Vector2i pos,
+ sf::Vector2i size){
sf::IntRect rect {pos, size};
if( rect.contains( mousePosition() ) ){
@@ -170,18 +171,24 @@ bool UI::radioButton(sf::RenderWindow *win, int id, const std::string &text,
}
// Rendering:
- sf::CircleShape radio{ 50 };
- radio.setPosition( sf::Vector2f(pos) );
- radio.setOutlineColor( sf::Color::Blue );
- radio.setOutlineThickness( 5 );
+ sf::RectangleShape rectangle { sf::Vector2f(size) };
+ rectangle.setPosition( sf::Vector2f(pos) );
+ win->draw(rectangle);
+ sf::CircleShape radio{ 4 };
+ radio.setPosition( sf::Vector2f(pos) + sf::Vector2f(10, size.y/2) );
+ radio.setOutlineColor( sf::Color::Red );
+ radio.setOutlineThickness( 1 );
if(state){
radio.setFillColor( sf::Color::Blue );
} else {
}
-
win->draw(radio);
+ Graphics::Text textGraph {font, text, size.x - 30, size.y};
+ textGraph.setPosition(sf::Vector2f(pos) + sf::Vector2f{30, size.y/2});
+ win->draw(textGraph);
+
return state;
}
diff --git a/src/ui.h b/src/ui.h
index 16027ae..34127fe 100644
--- a/src/ui.h
+++ b/src/ui.h
@@ -2,6 +2,7 @@
#define UI_H
#include<SFML/Graphics.hpp>
+#include"graphics/text.h"
enum class MouseButton{
Left,
@@ -37,8 +38,8 @@ class UI{
void finishImUI();
bool button(sf::RenderWindow *win, int id, const std::string &text,
sf::Vector2i pos, sf::Vector2i size);
- bool radioButton(sf::RenderWindow *win, int id,
- const std::string &text, bool state, sf::Vector2i pos,
+ bool radioButton(sf::RenderWindow *win, Graphics::TextureFont font,
+ int id, const std::string &text, bool state, sf::Vector2i pos,
sf::Vector2i size);
};