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;
}