SFML community forums

Help => Window => Topic started by: Ekzee on May 08, 2019, 09:35:03 pm

Title: window.getDefaultView not updated after resize
Post by: Ekzee on May 08, 2019, 09:35:03 pm
Hello!

I'm probably doing something wrong, because I just started learning SFML and graphics, but here is the code to reproduce the issuse:

int main() {
        auto window = sf::RenderWindow(sf::VideoMode(1280, 540), "My window");
        window.setVerticalSyncEnabled(true);
        const float worldWidth = 960;
        const float worldHeight = 540;
        updateView(window, worldWidth, worldHeight, window.getSize().x, window.getSize().y);

        while (window.isOpen()) {

                sf::Event event{};
                while (window.pollEvent(event)) {
                        if (event.type == sf::Event::Closed) {
                                window.close();
                        }
                        if (event.type == sf::Event::Resized) {
                                updateView(window, worldWidth, worldHeight, event.size.width, event.size.height);
                        }
                }

                window.clear(sf::Color::Black);

                sf::RectangleShape viewArea(sf::Vector2f(worldWidth, worldHeight));
                viewArea.setPosition(0, 0);
                viewArea.setFillColor(sf::Color::Red);
                window.draw(viewArea);

                sf::Vector2i zeroPoint = window.mapCoordsToPixel(sf::Vector2f(0, 0));
                sf::RectangleShape viewAreaStart(sf::Vector2f(50.f, 50.f));
                viewAreaStart.setPosition(sf::Vector2f(zeroPoint.x, zeroPoint.y));
                viewAreaStart.setFillColor(sf::Color::White);

                sf::View view = window.getView();
                window.setView(window.getDefaultView());
                window.draw(viewAreaStart);
                window.setView(view);

                window.display();
        }
        return 0;
}
 

And here is updateView function, which should add spaces on the screen, to keep world aspect ratio:
void updateView(
        sf::RenderTarget& renderTarget,
        const float worldWidth,
        const float worldHeight,
        const float targetWidth,
        const float targetHeight
) {
        float worldAspectRatio = worldWidth / worldHeight;
        float screenAspectRatio = targetWidth / targetHeight;
        sf::FloatRect viewPort = sf::FloatRect(0, 0, 1.f, 1.f);
        if (screenAspectRatio < worldAspectRatio) {
                float widthRatio = targetWidth / worldWidth;
                float scaledWorldHeight = widthRatio * worldHeight;
                float heightDiff = targetHeight - scaledWorldHeight;
                float viewPortHeightOffset = heightDiff / 2 / targetHeight;
                viewPort.top = viewPortHeightOffset;
                viewPort.height = 1.f - viewPortHeightOffset * 2;
        } else {
                float heightRatio = targetHeight / worldHeight;
                float scaledWorldWidth = heightRatio * worldWidth;
                float widthDiff = targetWidth - scaledWorldWidth;
                float viewPortWidthOffset = widthDiff / 2 / targetWidth;
                viewPort.left = viewPortWidthOffset;
                viewPort.width = 1.f - viewPortWidthOffset * 2;
        }
        sf::View view(sf::FloatRect(0.f, 0.f, worldWidth, worldHeight));
        view.setViewport(viewPort);
        renderTarget.setView(view);
}
 

So in the beginning the white ractangle is located at the top left corner of the red rectangle. When I resize the window by adjusting it's width, the white rectangle starts shifting away from the corner, and if im not mistaken, the rectangle should stay in it`s place.

I can "fix" this behaviour by calculating default view myself, like this:
int main() {
        auto window = sf::RenderWindow(sf::VideoMode(1280, 540), "My window");
        sf::View defaultView(sf::FloatRect(0, 0, window.getSize().x, window.getSize().y));
        const float worldWidth = 960;
        const float worldHeight = 540;
        updateView(window, worldWidth, worldHeight, window.getSize().x, window.getSize().y);
        window.setVerticalSyncEnabled(true);

        while (window.isOpen()) {

                sf::Event event{};
                while (window.pollEvent(event)) {
                        if (event.type == sf::Event::Closed) {
                                window.close();
                        }
                        if (event.type == sf::Event::Resized) {
                                updateView(window, worldWidth, worldHeight, event.size.width, event.size.height);
                                defaultView.setSize(event.size.width, event.size.height);
                                defaultView.setCenter((float) event.size.width / 2, (float) event.size.height / 2);
                        }
                }

                window.clear(sf::Color::Black);

                sf::RectangleShape viewArea(sf::Vector2f(worldWidth, worldHeight));
                viewArea.setPosition(0, 0);
                viewArea.setFillColor(sf::Color::Red);
                window.draw(viewArea);

                sf::Vector2i zeroPoint = window.mapCoordsToPixel(sf::Vector2f(0, 0));
                sf::RectangleShape viewAreaStart(sf::Vector2f(100, 100));
                viewAreaStart.setPosition(sf::Vector2f(zeroPoint.x, zeroPoint.y));
                viewAreaStart.setFillColor(sf::Color::White);

                sf::View view = window.getView();
                window.setView(defaultView);
                window.draw(viewAreaStart);
                window.setView(view);

                window.display();
        }
        return 0;
}
 
Title: Re: window.getDefaultView not updated after resize
Post by: FRex on May 09, 2019, 01:23:47 am
Default view never changes: https://www.sfml-dev.org/documentation/2.5.1/classsf_1_1RenderWindow.php#ad3b533c3f899d7044d981ed607aef9be
Title: Re: window.getDefaultView not updated after resize
Post by: Ekzee on May 09, 2019, 06:49:26 am
Hmmm, isn't it making it kinda useless?
Title: Re: window.getDefaultView not updated after resize
Post by: Laurent on May 09, 2019, 07:59:35 am
Please have a look at the documentation and tutorial (https://www.sfml-dev.org/tutorials/2.5/graphics-view.php) before making assumptions and asking here ;)

It's not useless. If you build view of size 1000x1000, then you'll see 1000x1000 units of your scene on screen no matter what the size of the window is. If it was adjusted automatically, as you suggest, then it would be useless to give a size to the view in the first place.
Title: Re: window.getDefaultView not updated after resize
Post by: Ekzee on May 09, 2019, 03:03:04 pm
Damn, I'm somehow managed to miss the "Showing more when the window is resized" section  :o
Title: Re: window.getDefaultView not updated after resize
Post by: Elias Daler on May 13, 2019, 02:26:52 pm
This is a thing that confused me a lot recently. Maybe the naming is a bit unfortunate... Because "default" for me meant (0, 0, currentWidth, currentHeight).
If only there was a function which actually returned the view like this.

"default" here is "how SFML will draw it unless you react to resize", right?