Widget clipping when resizing the viewport

Started by Dnake, 10 April 2014, 22:24:24

Dnake

I've a little issue when I resize my viewport. I explain: I allow the player of my game to resize the window, and my view should keep a 16:9 ratio. So I write a little fonction who resize the viewport when a window resizing event is thrown, and allow the view to be always in 16:9. The fonction return the float rect to assign to the viewport, and here is its code:

FloatRect handleResize(Event::SizeEvent size)
{
    unsigned int iw = size.width;
    unsigned int ih = size.height;
    float fh(ih), fw(iw);//If size is in a 16:9 ratio, it won't change.
    if(iw/16 < ih/9)//Taller than a 16:9 ratio
        fh = iw * (9.0/16.0);
    else if(iw/16 > ih/9)//Larger than a 16:9 ratio
        fw = ih * (16.0/9.0);
    float scalex = fw/iw;
    float scaley = fh/ih;
    return FloatRect((1-scalex)/2.0f, (1-scaley)/2.0f, scalex, scaley);
}

But that make a litlle problem, the widget are strangely resized, like you can see inn the attached file, and that clip the content, here a label. The background of the label is grey in the picture. The proportions in the picture between the two windows are preserved. How can I fix that? Should I handle the resize in another way, or disable the resizing?
(Texus: I speak french at first, and I can see you're belgian, so can I speak with you in french?)

texus

#1
This is most likely a bug in tgui. The viewort isn't used in calculations.

But I can't immediately reproduce it, could you send a small example code the produces the error?

Quote(Texus: I speak french at first, and I can see you're belgian, so can I speak with you in french?)
Nope, I speak dutch. I know a little french, but not enough to really communicate with it.

Edit: I've been able to reproduce it. I'm looking into it.
Edit2: I can only reproduce a similar bug, not yet the exact same thing. So I can still use an example so that I can test whether my fix holds in your situation as well (which I doubt).

Dnake

Okay, I linked an exemple and the font I use.
I see that this is caused by the line with the comment HERE, and when I remove the "*0.5f", the label get a good behavior...
(And I heard that my computer emit a noize when my exemple run, and the noize become more high-pitched when I decrease the size of the window... ^^')

texus

Ok, I can reproduce it but I'll look into this in more detail tomorrow.

The only thing you can do now is comment out line 378 in Label.cpp (the one with glScissor) and compile the changed tgui version. That will disable the clipping in Label, which is not really needed in 99.9% of the cases anyway.

But some other widgets are going to have the same problem, so I'll try to fix this as soon as possible.

Dnake

#4
Yes, I suspected that this line was involved in my bug, thank you for your answer!

EDIT: Your proposal change nothing, as I can see in my case, the label have exactly the same behavior.
And I seen that the amplitude of the clipping depends on the TextSize, beyond 250 in my exemple the clipping is negligible, but under this value it's very annoying. Anyway, there is a bug ^^

texus

I didn't notice that the Label was inside a Panel at first. The Panel is also doing some clipping.

The changes that have to be made are in the calculation of topLeftPosition and bottomLeftPosition. These calculations did not take the viewport into account. When I wrotes these formulas once I hoped that I would never have to touch them again, but it seems that they weren't perfect after all.

The code in Label.cpp has to be
sf::Vector2f topLeftPosition
    = states.transform.transformPoint(((getPosition().x - target.getView().getCenter().x + (target.getView().getSize().x / 2.f)) * target.getView().getViewport().width) + (target.getView().getSize().x * target.getView().getViewport().left),
                                      ((getPosition().y - target.getView().getCenter().y + (target.getView().getSize().y / 2.f)) * target.getView().getViewport().height) + (target.getView().getSize().y * target.getView().getViewport().top));
sf::Vector2f bottomRightPosition
    = states.transform.transformPoint((getPosition().x + m_background.getSize().x - target.getView().getCenter().x + (target.getView().getSize().x / 2.f)) * target.getView().getViewport().width + (target.getView().getSize().x * target.getView().getViewport().left),
                                      (getPosition().y + m_background.getSize().y - target.getView().getCenter().y + (target.getView().getSize().y / 2.f)) * target.getView().getViewport().height + (target.getView().getSize().y * target.getView().getViewport().top));


And in Panel.cpp
sf::Vector2f topLeftPosition
    = states.transform.transformPoint(((getPosition().x - target.getView().getCenter().x + (target.getView().getSize().x / 2.f)) * target.getView().getViewport().width) + (target.getView().getSize().x * target.getView().getViewport().left),
                                      ((getPosition().y - target.getView().getCenter().y + (target.getView().getSize().y / 2.f)) * target.getView().getViewport().height) + (target.getView().getSize().y * target.getView().getViewport().top));
sf::Vector2f bottomRightPosition
    = states.transform.transformPoint((getPosition().x + m_size.x - target.getView().getCenter().x + (target.getView().getSize().x / 2.f)) * target.getView().getViewport().width + (target.getView().getSize().x * target.getView().getViewport().left),
                                      (getPosition().y + m_size.y - target.getView().getCenter().y + (target.getView().getSize().y / 2.f)) * target.getView().getViewport().height + (target.getView().getSize().y * target.getView().getViewport().top));


I'm going to sleep now, but I'll continue this tomorrow. Other widgets will need the same fix, and I somehow feel that there is also something wrong when changing the view size.

I'm surprised that a bug as big is this one hasn't been noticed before. I guess nobody needed to change the viewport in his program until now.

Dnake

I don't totally understand your code, but that work pretty good! Thank for your motivation and your reactivity.
(You just wrote m_background and m_size in place of m_Background and m_Size :p)

texus

The fix has been made on the master branch on github (https://github.com/texus/TGUI), which will be released as v0.6.3 later this weekend.

QuoteI don't totally understand your code
That piece of code isn't meant to be understood. Its meant to be written once and hope that you never have to change it again :).
The reason why it is so complex is because I need the coordinate on the sceen with the bottom left corner being the origin. To find that point I have to take into account that sfml has its origin in the top left corner, the view size can be different than the window and I also have to watch the viewport apparently.
Maybe if SFML issue #1 gets added one day it would become a lot easier.

Quote(You just wrote m_background and m_size in place of m_Background and m_Size :p)
Thats because I was developing on the v0.7 branch, I made a small naming convention change there. Luckily you could see the mistake yourself here, in other widgets there were differences like m_LeftBorder vs m_borders.left.

ANDO1

I had the same problem with Labels and other widgets (e.g., Combobox) and was just about to post.  Just downloaded and tested the new code.  Works a treat.  Thanks again for your quick work.  :)

Dnake

Thanks for the update, I downloaded it from Github. But another issue pop up, my texts where clipped in the underline. So I downloaded the last SFML release on Github and I compiled it, like you said in another topic on this forum.
But now I have to manually set the autoSize to true on my Labels to display them, otherwise the labels have a null size, problem that I hasn't with my previous version of SFML. So I don't understand where my issue come from.
And that's not dependant from my project, the bug pop up too in the Full Example.

texus

Strange. I just tested creating a Label like this and I could not reproduce it.
tgui::Label::Ptr label(gui);
label->setText("Hello");


After compiling SFML, did you compile TGUI again with the new SFML libraries?
Depending on your compiler you could also just use the precompiled libraries.

Dnake

Yes, that was that, after recompiling TGUI that work fine, thanks!  8)

ANDO1

It appears that the problem with clipping of widgets when using Viewports may still exist for widgets inside Panels if the the Panel is positioned anywhere other than the origin?  Please see minimum code.

#include <SFML/Graphics.hpp>
#include <TGUI/TGUI.hpp>
#include <windows.h>

int WINAPI WinMain(HINSTANCE instance, HINSTANCE, LPSTR, INT)
{
// Create Render Window
sf::RenderWindow window(sf::VideoMode(1280,1024), "Test", sf::Style::Fullscreen);

// Set view
sf::View SView;
SView.reset(sf::FloatRect(0, 0, 1280, 1024));   
SView.setViewport(sf::FloatRect(0.25f, 0.25f, 0.5f, 0.5f));
window.setView(SView);   

// Create GUI
tgui::Gui gui(window);

if (gui.setGlobalFont("Fonts/DejaVuSans.ttf") == false)
return(0);

// Create an empyt/transparent panel to hold a Label
tgui::Panel::Ptr dpanel(gui);
        dpanel->setSize(800.0f, 600.0f);
dpanel->setTransparency(0);
dpanel->setBackgroundColor(sf::Color(255,255,255,0));

// Setting Position of Panel at origin works fine
//     dpanel->setPosition(0, 0);
// Setting Position of Panel to location other than origin causes clipping of Label within Panel
        dpanel->setPosition(200, 200);

       // Create Label within panel
tgui::Label::Ptr label(*dpanel);
label->setText("Test Label");
label->setPosition(100,100);

while (window.isOpen())
{
sf::Event event;

        while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
{
                window.close();
            }
else if (event.type == sf::Event::KeyPressed)
{
switch (event.key.code)
{
case sf::Keyboard::Escape:
window.close();
break;
}
}

gui.handleEvent(event,false);
}


tgui::Callback callback;
while (gui.pollCallback(callback))
{
// Do event handler for gui here
}

window.clear();
gui.draw(false);
window.display();
}
return(0);
}

texus

#13
Damn. I'll make sure to look for a different way to do the clipping in v0.7.

The Label has to know its absolute position on the screen, but it currently only knows its relative position.
I'll see if I can fix it this evening.

Edit: the bug seems to be a little trickier than I thought. I'll try to have it fixed tonight or tomorrow though.

texus

I've made a commit on github that should hopefully fix your problems.

The change is not finished yet (Tab widget hasn't been changed yet, and I still have to actually test the code), but I hope that it will work for what you need so that you don't have any problems with this anymore.

After I finish the change (hopefully tomorrow) I'll make sure to fully test it with different viewports, view sizes and view centers to make sure that my code finally supports every combination.