0

I'm trying to stick toolbar buttons to the top-right of my screen, but whenever I resize the window, the buttons stay in the same absolute position (relative to the bottom-left).

Before resize: before resize

After resize: after resize

This is the method that generates the UI button (Which is currently only called in the Screen's constructor):

private void generateUiToolbar(){
    // Toolbar Table
    Table table = new Table();
    table.setFillParent(true);
    table.top();
    table.right();

    // Menu button
    table.row();
    Texture myTexture = new Texture(Gdx.files.internal("ui/stamp.png"));
    TextureRegion myTextureRegion = new TextureRegion(myTexture);
    TextureRegionDrawable myTexRegionDrawable = new TextureRegionDrawable(myTextureRegion);
    ImageButton menuButton = new ImageButton(myTexRegionDrawable);
    menuButton.addListener( new ClickListener() {
        @Override
        public void clicked(InputEvent event, float x, float y) {
            stage.clear();
            generateUiMenu();
        }
    });
    table.add(menuButton).size(60,60).padTop(10).padRight(10);

    stage.addActor(table);
}

This is the resize() method:

public void resize(int width, int height) {
    stage.getViewport().update(width, height, true);
    stage.getCamera().viewportWidth = width;
    stage.getCamera().viewportHeight = height;
    stage.getCamera().position.set(stage.getCamera().viewportWidth / 2, stage.getCamera().viewportHeight / 2, 0);
    stage.getCamera().update();
}

The variable stage is initiated in the constructor with stage = new Stage();

For some reason stage.getViewport().update(width, height, true); doesn't do anything. When I print stage.getWidth() after resizing, it will return the same number. What's a good way to update the location of the button or Actors in general? Simply clearing the stage and generating the UI again won't work for me, because sometimes when you resize, there are different actors currently displayed. If I missed any information, please let me know.

EDIT 1: Added table.setFillParent(true); as mentioned in an answer, but that didn't fix it either.

EDIT 2: After reading the answers and comments, I deleted the stage.getCamera() manipulation, but I'm still not getting the correct result. This is what happens when I resize with just the line of code stage.getViewport().update(width, height, true);: after resize with just viewport manipulation

Tipsi
  • 404
  • 4
  • 12

2 Answers2

1

The Viewport object is a camera frustum manager. When you start modifying the camera's parameters (other than position), you are undoing what you did by calling viewport.update().

If you want the table to automatically fill the screen so stuff in the top right corner stays there after a resize, don't set a width and height on the table. Instead, call table.setFillParent(true) so it will automatically update its size to match the viewport size.

Tenfour04
  • 83,111
  • 11
  • 94
  • 154
  • Thanks for the explanation. So are you saying I should just delete `viewport.update()`? Or should I do something differently. The changes to camera are there so the actors don't start stretching when I start resizing. When I do `table.setFillParent(true)` it doesn't automatically update when resizing either... Am I missing something? I assume it's because the viewport isn't updating? – Tipsi Jul 21 '19 at 00:53
  • Usually you would use the viewport that matches the behavior you want (which IMO should be ExtendViewport for 95% of cases), or write a custom Viewport class and manage your camera size from there. The table might not be resizing correctly because of your camera manipulation, but also make sure you remove the `setSize()` call. – Tenfour04 Jul 21 '19 at 01:20
  • Yeah I've removed the `setSize()`. I need the camera manipulation for thee before mentioned reasons, though. I will try to use an ExtendViewport when I'm at my PC again tomorrowmorning and see if that changes anything. – Tipsi Jul 21 '19 at 01:28
  • ExtendViewport doesn't change anything, sadly. Is there no way to manipulate the camera and also update the viewport to the screen's size? – Tipsi Jul 21 '19 at 13:25
  • You can manipulate the camera viewports, but the correct place to do that is inside a subclass of Viewport. But I would be surprised if there isn't a viewport already that does what you need. If it doesn't do anything then you might have missed removing code where you modify camera.viewportWidth or Height somewhere. – Tenfour04 Jul 21 '19 at 13:30
1

I think you misunderstand the usage of Viewport. In your resize method you do:

stage.getViewport().update(width, height, true);
stage.getCamera().viewportWidth = width;
stage.getCamera().viewportHeight = height;
stage.getCamera().position.set(stage.getCamera().viewportWidth / 2, stage.getCamera().viewportHeight / 2, 0);
stage.getCamera().update();

But stage.getViewport().update(width, height, true); already does what you do in the next four lines.

viewport.update(width, height) set the new width and height to the camera and updates the camera. So:

viewport.update(width, height)

is equal to

camera.viewportWidth = width;
camera.viewportHeight = height;
camera.update();

The only difference is that the viewport looks to the aspect ratio depending on which Viewport you use.

And the third parameter: stage.getViewport().update(width, height, true); is a boolean value which says should the camera be centered. So if the third parameter is true the viewport will do:

camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0);

In your resize method you override the work of the viewport because with viewport.update(width, height, true) you already have done all of the resize and you don't need the four other lines.

In the resize method this is enough:

public void resize(int width, int height) {
    stage.getViewport().update(width, height, true);
}

You can read this for a better understanding of Viewport: How Camera works in Libgdx and together with Viewport

Morchul
  • 1,987
  • 1
  • 7
  • 21
  • Thanks for clearing that up. The one difference you mentioned is probably what causes the mixed results for me. But neither of the 2 options solve my problem, so this isn't a solution yet. `stage.getViewport().update(width, height, true);` makes it so that the button sticks to the top-right corner, but it stretches with the screen (Check question, I'll add a screenshot for that). The camera manipulation solution makes it so it doesn't stretch, but it doesn't stick to the top-right either. It stays in the same spot like in the screenshot I added. – Tipsi Jul 22 '19 at 13:20
  • Is it because I'm not using the correct viewport? I didn't specify a viewport when initiating the stage. Which means it automatically uses a ScalingViewport. Using an ExtendViewport doesn't work either. Do you happen to know what viewport I should be using? – Tipsi Jul 22 '19 at 13:25
  • @Tipsi to take care of the Aspect ratio you should use a FitViewport or an ExtendViewport. By a FitViewport or ExtendViewport, you must define your World width and World height. This will help you to understand what world units are: https://stackoverflow.com/questions/51993577/libgdxs-world-units/52072708#52072708 – Morchul Jul 22 '19 at 13:38
  • @Tipsi A FitViewport will add BlackBars to the side. If the Screen size doesn't match the aspect ratio so your game will fit the longer side. ExtendViewport makes the opposite and will fit the shorter side. You won't have BlackBars on the side but you will see less of your world if the aspect ratio is not the same as declared – Morchul Jul 22 '19 at 13:47
  • Ah, ExtendViewport DOES work. I guess it didn't work before because I used the camera manipulation methods instead of `viewport.update()`. However, now the menu button doesn't stay the same size when resizing, which is what I wanted. But I guess your answer did solve my question. – Tipsi Jul 22 '19 at 13:50
  • I don't seem to have that issue. I'm using a different camera for the hud etc. Maybe that's why it doesn't mess up like that? But I do notice it when I open the in-game menu. It should be centered in the middle, but once I start resizing, it starts moving very strangely. It didn't behave like that before. – Tipsi Jul 22 '19 at 14:09
  • @Tipsi Sry I got it wrong. With ExtendViewport you will see more of your world if you extend your screen in one Direction instead of seeing less. But if it works for you all is fine :) – Morchul Jul 22 '19 at 14:13
  • Np, yeah I set up a zoom level for my game. So when you go past a certain resolution, the game is zoomed in by 4, then by 6, then by 8 etc. Maybe that's why it works fine. – Tipsi Jul 22 '19 at 14:17