rafaskb / typing-label

A libGDX Label that appears as if it was being typed in real time.
MIT License
151 stars 20 forks source link

Aligning label issue #19

Closed Mewel closed 4 years ago

Mewel commented 4 years ago

The returned size of getWidth and getPrefWidth does not just return the width of the plain text, but additionally includes the width of each token. This leads to way to big widths and makes it imposible to center a typing label for example.

rafaskb commented 4 years ago

I tested the getWidth() method in my testing app and the width reported is the correct one, 620 pixels. It does report a wrong value of 4300 pixels during the first frame before the label is adjusted in the table though, which is normal and should be corrected by the table where the label is put in.

getPrefWidth returns 0 if the label is wrapping, see https://libgdx.badlogicgames.com/ci/nightlies/docs/api/com/badlogic/gdx/scenes/scene2d/ui/Label.html#setWrap-boolean-

Maybe your issue is something else though, can you share an example of the bug so I can take a look?

Mewel commented 4 years ago

I wasn't using a table cause I wanted to layout the text myself. So I used getPrefWidth() for that. A normal Label returns the "real" width and a Typing Label not. And my label is just one line, no wrapping there.

I know that in most use cases a table is the best option for layouting and then the Typing Label will work accordingly. But in my opinion getPrefWidth() should do what the method implies, returning the "best" width for a widget.

As a workaround I can try to wrap the Typing Label in a table and then layout the table instead. Would still be great if you can fix this :).

rafaskb commented 4 years ago

@Mewel would you have some code to share that reproduces this behavior?

Mewel commented 4 years ago

I have to say Im a bit confused now, because the test I wrote is working as it should be. I will post it first:

public class TypingLabelTestGame extends Game {

    private SimpleScreen screen;

    @Override
    public void create() {
        // load my custom assets
        PMD2Assets assets = new PMD2Assets();
        assets.load();

        // set screen
        setScreen(this.screen = new SimpleScreen());

        // create label and container
        TypingLabel label = new TypingLabel("{SPEED=0.5}{FADE}Hello World", assets.getLabelStyle(PMD2Assets.Font.font_large));
        LabelCenterContainer container = new LabelCenterContainer(label);
        container.setFillParent(true);

        // add container to stage
        this.screen.getStage().addActor(container);

        container.setDebug(true);
    }

    /**
     * Custom container to center one widget.
     */
    public static class LabelCenterContainer extends WidgetGroup {

        private Label label;

        public LabelCenterContainer(Label label) {
            this.label = label;
            this.addActor(label);
        }

        @Override
        public void layout() {
            // set preferred size of the widget first
            this.label.setSize(this.label.getPrefWidth(), this.label.getPrefHeight());
            // center the widget in the container
            this.label.setPosition(this.getWidth() / 2 - this.label.getWidth() / 2,
                    this.getHeight() / 2 - this.label.getHeight() / 2);
        }

    }

    public static class SimpleScreen extends ScreenAdapter {

        private Stage stage;

        private ExtendViewport viewport;

        private Camera camera;

        public SimpleScreen() {
            stage = new Stage();
            camera = new OrthographicCamera();
            viewport = new ExtendViewport(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), camera);
            viewport.apply();
            camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0);
            camera.update();
        }

        @Override
        public void render(float delta) {
            Gdx.gl.glClear(GL30.GL_COLOR_BUFFER_BIT);
            Gdx.gl.glBlendFunc(GL30.GL_SRC_ALPHA, GL30.GL_ONE_MINUS_SRC_ALPHA);

            stage.act(delta);
            stage.draw();
        }

        @Override
        public void resize(int width, int height) {
            updateViewportAndCamera(width, height);
            stage.getViewport().update(width, height);
            stage.getRoot().setBounds(0, 0, width, height);
        }

        public void updateViewportAndCamera(int width, int height) {
            viewport.update(width, height);
            camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0);
            camera.update();
        }

        public Stage getStage() {
            return stage;
        }

    }

}

Its still very strange to mee cause I was a 100% sure I tested it like this and it didn't work... Anyway, whats not working is using the Align I guess. But not sure. Just replace the LabelCenterContainer with the following one:

/**
 * Custom container to center one label.
 */
public static class LabelAlignContainer extends WidgetGroup {

    private Label label;

    public LabelAlignContainer(Label label) {
        this.label = label;
        this.label.setAlignment(Align.center);
        this.label.setFillParent(true);
        this.addActor(label);
    }

}

But I don't really care about this Align behaviour cause I usually do it with the getPref layout.

And your right the first time getPrefWidth returns the "wrong" size but in the layout phase its all fine. So I guess its not a bug.