Dissapearing sf::Text after transform applying

Viewed 34

I'm trying to apply a transformation matrix to sf::Text class, and when I change its size, the sf::Text just disappears. I had the same problem with a sf::Sprite, but there I'd solved it by rewriting the whole class. Furthermore, I know where's the problem. It is in the sf::Transformable part and the scale SFML politic that the size elements in a transform matrix have to be scale coefficients. I don't like it because I want to work with my objects using math.

Anyway, like in the sf::Sprite, this problem is in the vertex array generating inside sf::Text class, but I cannot reimplement it because our sf::Text class is a friend for a sf::Texture class

Someone... Help...

P.S. If you need more information about this problem, please, continue to read.



So. Here's a detailed problem description.

I have some system, which read JSON like that and make some scene stuff:

"title": {
    "type": "node",
    "enabled": true,
    "components": {
        "color": "magenta",
        "layout": {
            "priority": 1,
            "anchor": { "x": 0.5, "y": 0.05 },
            "pivot": { "x": 0.5, "y": 0 },
            "size": { "x": "80%", "y": "20%" },
            "draw_rect": true
        },
        "text": {
            "priority": 2,
            "settings": {
                "data": "Some Lode Runner",
                "size": 40,
                "letter_spacing": 1.0,
                "line_spacing": 1.0,
                "style": "regular"
            },
            "outline": {
                "color": "white",
                "thickness": 1.0
            },
            "font": {
                "path": "res/fonts/win_cmd.ttf",
                "smooth": true
            }
        }
    }
}

And, as you can notice, the priority says which component will be used first. And it works perfectly with my rewrote sprite, because the SFML sprite has the following implementation:

void Sprite::updatePositions()
{
    FloatRect bounds = getLocalBounds();

    m_vertices[0].position = Vector2f(0, 0);
    m_vertices[1].position = Vector2f(0, bounds.height);
    m_vertices[2].position = Vector2f(bounds.width, 0);
    m_vertices[3].position = Vector2f(bounds.width, bounds.height);
}

void Sprite::updateTexCoords()
{
    FloatRect convertedTextureRect(m_textureRect);

    float left   = convertedTextureRect.left;
    float right  = left + convertedTextureRect.width;
    float top    = convertedTextureRect.top;
    float bottom = top + convertedTextureRect.height;

    m_vertices[0].texCoords = Vector2f(left, top);
    m_vertices[1].texCoords = Vector2f(left, bottom);
    m_vertices[2].texCoords = Vector2f(right, top);
    m_vertices[3].texCoords = Vector2f(right, bottom);
}

If you know the OpenGL a little, you have to know that the vertex and the texture coordinates can be implemented as [-1, 1] for the first one, and [0, 1] for the second one.

And to fix it, I rewrote the SFML sprite class like that:

void Sprite::updateVertices() {
    mVertices[asID(Corner::LeftDown)].position  = { 0.0f , 0.0f };
    mVertices[asID(Corner::LeftUp)].position    = { 0.0f , 1.0f };
    mVertices[asID(Corner::RightUp)].position   = { 1.0f , 0.0f };
    mVertices[asID(Corner::RightDown)].position = { 1.0f , 1.0f };
}

void Sprite::updateTextureCoords() {
    const auto &[width, height]{ mTexture.mData->getSize() };
    const float left   = mTextureCoords.left * width;
    const float right  = left + mTextureCoords.width * width;
    const float top    = mTextureCoords.top * height;
    const float bottom = top + mTextureCoords.height * height;

    mVertices[asID(Corner::LeftDown)].texCoords  = { left , top };
    mVertices[asID(Corner::LeftUp)].texCoords    = { left , bottom };
    mVertices[asID(Corner::RightUp)].texCoords   = { right, top };
    mVertices[asID(Corner::RightDown)].texCoords = { right, bottom };
}

And it works perfectly. Now I can apply to my sprite transform like that:

render->pushTransform(transform);
render->draw(mySprite);
render->popTransform();

So, I understand that the sf::Text class has the same problem because when I put set my transform component size like 2 and 1 pixel, the text size become so large:

The result using [1, 1] size: My text with the size {1, 1}

The result using [2, 1] size: After changing size to {2, 1}

But I need to set size in a normal things like [1024, 720] or, as you can notice, by percents.

So, I have to change the vertex position and textures inside the sf::Text sprite, but I cannot rewrite it like a sprite because of this 431 line in <SFML/Graphics/Text.cpp> file:

    // Save the current fonts texture id
    m_fontTextureId = m_font->getTexture(m_characterSize).m_cacheId;

The m_cacheId is a sf::Texture's private member, and if we look up inside texture class, we find those lines:

private:
    friend class Text;
    friend class RenderTexture;
    friend class RenderTarget;

It means that I cannot reimplement my own Text class without touching SFML sources :c

But in the SFML original site I found this information about rewriting sf::Text stuff, but I don't really want to spend a lot of time for making bicycle with glyphs

0 Answers
Related