0
\$\begingroup\$

I asked this question and implemented the accepted answer. One last piece of the puzzle remains, how to add event listener to the button?

I'm working with a teammate, I suggested to try Gdx.input.justTouched() but he wonders if it's possible to add event listeners like you would do for normal buttons.

\$\endgroup\$
3
\$\begingroup\$

One way to achieve this could be to extend the existing Button class and provide an implementation that sets the up, down, checked and disabled Drawables of the ButtonStyle to whatever the last key-frame of the animation loaded is.

That way you'd get standard button behavior and the only thing that changes is the (somewhat weird) continuously updating style.

Such a Button might look something like this; package com.bornander.sandbox;

import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.ui.Button;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;

public class AnimatedButton extends Button {

    private float elapsed;
    // Technically you'll need one of these for each state of the ButtonStyle, but I'll just cover up and down here.
    private final Animation<TextureRegion> upAnimation;
    private final Animation<TextureRegion> downAnimation;
    private final ButtonStyle overrideStyle = new ButtonStyle();
    private final TextureRegionDrawable upDrawable = new TextureRegionDrawable();
    private final TextureRegionDrawable downDrawable = new TextureRegionDrawable();

    public AnimatedButton(Animation<TextureRegion> upAnimation, Animation<TextureRegion> downAnimation) {
         this.upAnimation = upAnimation;
         this.downAnimation = downAnimation;
    }

    @Override
    public void act(float delta) {
        super.act(delta);
        elapsed += delta;

        upDrawable.setRegion(upAnimation.getKeyFrame(elapsed));
        downDrawable.setRegion(downAnimation.getKeyFrame(elapsed));
        overrideStyle.up = upDrawable;
        overrideStyle.down = downDrawable;

        setStyle(overrideStyle);
    }
}

And it would be instantiated with a list of animations (possibly created using a GifDecoder) for each state. Then it is possible to add listeners for clicked just like any other button owned by a Stage;

package com.bornander.sandbox;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Button;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.utils.viewport.ScreenViewport;
import com.holidaystudios.tools.GifDecoder;

public class SandboxGame extends ApplicationAdapter {

    Stage stage;

    @Override
    public void create () {
        stage = new Stage(new ScreenViewport());

        Animation<TextureRegion> upAnimation = GifDecoder.loadGIFAnimation(Animation.PlayMode.LOOP, Gdx.files.internal("throbber.gif").read());
        Animation<TextureRegion> downAnimation = GifDecoder.loadGIFAnimation(Animation.PlayMode.LOOP, Gdx.files.internal("throbber.gif").read());
        // Instanciate an AnimatedButton, providing animations for up and down states
        Button button = new AnimatedButton(upAnimation, downAnimation);

        button.setPosition(100, 100);
        button.setSize(32, 32);

        // Here the click listener is added by passing an anonymous type
        button.addListener(new ClickListener() {
            @Override
            public void clicked(InputEvent event, float x, float y) {
                super.clicked(event, x, y);

                //Add click handler here!

            }
        });

        // Add the button to the Stage
        stage.addActor(button);

        // And set the processor of input to be that stage
        Gdx.input.setInputProcessor(stage);
    }

    @Override
    public void render () {
        // Make sure to update the state of the stage
        stage.act(Gdx.graphics.getDeltaTime());
        Gdx.gl.glClearColor(1, 0, 0, 0);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        // Draw the state of the stage
        stage.draw();
    }

    @Override
    public void dispose () {
    }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.