Search code examples
javalibgdx2dactor

LibGDX - Does modifying a Group affects children?


I wonder if there is a way to affect Actors children when their parent Group is modified ? Like they were attached to him. By modifying I mean doing some conventional actions like translation, rotation, scale ...

I know this is possible for the parent alpha to affect children's alpha via the draw() method, but what about the other attributes ?

For example if I add a TranslationAction to my Group I want it to also affect children.

So did I miss something like this in the Scene2d API or do I really have to code it by my own (not hard, but just want to avoid if possible) ?

If it's not possible with the actual API then what is the purpose of using a Group ?


Solution

  • The answer to your question is yes and no. It is because the Scene2d API is designed around using the SpriteBatch which sets all sorts of transformation information between parent and children actors.

    If you are using the SpriteBatch (i.e. drawing textures, and such with it) then yes actions applied to the parent also affect the children. There are a couple of exceptions to some actors if I remember correctly but I think that just has to do with things like Color, etc.

    If you are not using the SpriteBatch (i.e. drawing geometry directly with OpenGL, or custom drawing actions (such as meshes) outside of what is offered by the Scene2d API) then no actions are not likely to affect the children. You will have to write your own code to do this either by subclassing Scene2d or creating something simple for yourself. I know it isn't the best thing ever but 'Libgdx tries not be the "end all, be all" solution'.

    The 'magic' for how transforms work is located in Group (link to source). The group class uses a method called drawChildren() to iterate over the children and draws them based on a transformed SpriteBatch. The transformation occurs in the draw() method of the Group class.

    This isn't a real answer without some example code, I will assume you know how to setup skins. The end result of the program below is the Group button will be at 50,100 and the Hello button will be at 100,50. Notice I didn't make any direct changes to the Group button, but I put it inside a group and translated the whole group instead.

    public class Groups implements ApplicationListener {
        private Stage stage;
        private Skin uiSkin;
    
        @Override public void create() {
            this.stage = new Stage(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), false);
            Gdx.input.setInputProcessor(this.stage);
    
            this.uiSkin = new Skin(Gdx.files.internal("skin/uiskin.json"));
    
            final TextButton plainTextButton = new TextButton("Hello", this.uiSkin);
            this.stage.addActor(plainTextButton);
    
            final Group group = new Group();
            final TextButton groupTextButton = new TextButton("Group", this.uiSkin);
            group.addActor(groupTextButton);
            this.stage.addActor(group);
    
            plainTextButton.addAction(Actions.moveBy(100, 50));
            group.addAction(Actions.moveBy(50, 100));
    
            Gdx.gl20.glClearColor(0f, 0f, 0f, 1);
            Gdx.gl20.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
        }
    
        @Override public void render() {
            this.stage.act();
            Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT);
            this.stage.draw();
        }
    
        @Override public void dispose() {}
        @Override public void resize(final int width, final int height) {}
        @Override public void pause() {}
        @Override public void resume() {}
    }
    

    Hopefully this gives you enough information and a bit of explanation about Scene2d.