Question

I'm rendering the game environment using lwjgl while using scene2d.UI to construct a table which contains my inputs.

Currently, if I click on the UI it does react but so does the game environment. Obviously because I haven't handled it. The problem here is -where- should I handle input so that mouse clicks on the UI do not also activate the environment's input handling.

My thought is to attach a listener to the UI table and move the input processing to the listener. I just don't know how to set this up. Should I be setting up a ClickListener on the Table, on it's children, or is there something else I should be doing here?

This is the method that is run in the render loop:

    private void processInput() {
    //Handle user input here
    //[...]
    //Mouse input
    if(Gdx.input.isButtonPressed(Input.Buttons.LEFT) && lastClick == null) {
        //lastClick = new Vector2(Gdx.input.getX() + CameraOrigen().x, (CameraOrigen().y+camera.viewportHeight)-Gdx.input.getY());
        lastClick = ScreenToWorld(new Vector2(Gdx.input.getX(),Gdx.input.getY()));
        gridIntersect = WorldToTileCoord(lastClick);
    }
    else if (!Gdx.input.isButtonPressed(Input.Buttons.LEFT) && lastClick != null) { lastClick = null; }
}

And this is how I am currently constructing the UI:

//------------- UI Construction ------------//
    table.align(Align.top);
    Table debugTable = new Table();
    debugTable.add(debugMouseTable);
    debugTable.add(debugTileSelectTable);
    table.add(debugTable).expandX().height((float)(game.VIRTUAL_HEIGHT * 0.85));
    table.add(spTest).width((float)(game.VIRTUAL_WIDTH * 0.2)).height((float)(game.VIRTUAL_HEIGHT * 0.85)).bottom();
    table.row();
    table.add(sbTileTypes).align(Align.left).expandY();
    table.add("corner");

    spDebug.pad(10).defaults().expandX().space(4);
    for (AtlasRegion aReg : hmTiles.get(TileType.FLOOR)) {
        spDebug.add(new Button_TilePreview(aReg, skin, sbTileTypes.GetSelectionValue(), this, brush));
        spDebug.row();
    }
    spDebug.invalidateHierarchy();
    //------------------------------------------//
Was it helpful?

Solution

Don't use the polling mechanism for input (Gdx.input.isXXX(...)). It is not very stable because you might miss some events and it is also framerate dependent.

Implement an InputProcessor for your gameplay input as well. Then use InputMultiplexer to let both processors (Stage and your GameplayInputProcessor) have a chance to handle the events.

This should look like the following:

InputMultiplexer multiplexer = new InputMultiplexer();
multiplexer.addProcessor(stage);
multiplexer.addProcessor(gameplayInputProcessor);
Gdx.input.setInputProcessor(mutliplexer);

This way your stage will get the events first. In case you don't want your second processor to receive the input events if your UI already handled them, then you need to return true in the handling methods of the stage.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top