SFML community forums

Help => Window => Topic started by: user31182 on December 25, 2018, 11:41:47 pm

Title: Window (not resizable) - resizeing without create() & close()
Post by: user31182 on December 25, 2018, 11:41:47 pm
Hi,

Currently writing an app in SFML which loads an image from file and displays it.

I know I'm not doing something quite right as I get strange results. Allow me to explain the problem...

I open an SFML window, with a "default" videomode of 800x600.

The reason is that the user chooses the image to display so the VM resolution (size) is not known at start time and it is not constant during the runtime of the app.

... You can probably see where this is going, and guess what the problem is?

At some point during the app runtime the user chooses an image to display. If the image is smaller than 800 x 600, I want the (non-resizable) window to change size such that it crops itself to fit the image. To clarify, I have set sf::Style::Titlebar and sf::Style::Close to make the window "non-resizable".

First I tried to:

1: Load the image into a texture
2: Create sprite and set texture
3: Change window size to match the size given by the texture
4: Draw the sprite

I "cout" the texture size, the sprite global bounds, the sprite scale and the window size. They all agree except sprite scale which is 1.0.

However the image does not fill the window. It is smaller than the window.

My code is simple and I can provide it, but without an image to test it on (perhaps I can find one online which we can agree to all use?) it won't give the same results for everyone who runs the code...

Since this didn't work, my suspicions were that the video mode (which is larger than the texture size) was causing the issue.

In other words, the VM is 800 x 600, and the BMP image is 640 x 480... Therefore when I call window.resize(640, 480) a 800 x 600 VM is "mapped" onto a display area of 640 x 480... So obviously the bitmap will be scaled down by the same factor and it will appear smaller than 640 x 480.

This appears to be what is happening.

So the second thing I tried was:

1: Calling window.close()
2: Calling window.create() with a new VM which is the correct size (same size as sprite)

Since I was doing this in a loop it creates a flickering effect as the window is destroyed and re-made over and over.

I can sort of resolve this issue by checking to see if the window needs to be created again, rather than doing it each time... However this still causes a flickering when the "user image choice" is changed between different size images.

Is there a solution to this in SFML or would changing the VM without destroying the window require a new patch to SFML?

I assume the videomode has something to do with allocating memory for OpenGL somewhere? Is it possible for me to resize the "opengl surface" while also resizing the window?

Alternatively is this a bug in SFML?
Title: Re: Window (not resizable) - resizeing without create() & close()
Post by: user31182 on December 26, 2018, 12:07:25 am
Ok I seem to have actually found an acceptable solution:

I do:

1: window.setView(....)
2: window.setSize(...)

I assume this is an "approved solution" (ie; It's ok to do this?)

Cheers
Title: Re: Window (not resizable) - resizeing without create() & close()
Post by: G. on December 26, 2018, 12:23:23 am
Yes.
https://www.sfml-dev.org/tutorials/2.5/graphics-view.php#showing-more-when-the-window-is-resized
Title: Re: Window (not resizable) - resizeing without create() & close()
Post by: Hapax on December 30, 2018, 12:16:28 pm
That is an acceptable solution and probably the most intuitive.

However, there is another that could be simpler with a little more knowledge of how the view works.

Set the view to always be the same. In this case, a simple view that goes from (0, 0) to (1, 1) would be fine.
This view then never needs to change.

Scale the sprite so that it fits into a 1x1 space.
You can simply divide 1 by its sizes.
You could also use a rectangle of 1x1 size or a vertex array but remember to get the correct texture co-ordinates.

This should do it whatever the size of window as long as the window isn't "re-created" ;D



During creation of the window:
window.setView(sf::View({ 0.f, 0.f, 1.f, 1.f }));

After loading the texture (presuming that the entire texture is being used):
sprite.setScale({ 1.f / static_cast<float>(texture.getSize().x), 1.f / static_cast<float>(texture.getSize().y) });