'LibGDX: Making mouse events in child objects happen only inside the custom container

I want to create my own custom UI in libGDX. I know there is scene2D provided by the framework but I want to make my own widgets without using scene2D. My container can clip the rendering if the child object is larger than the container but the child object mouse events still trigger even when the pointer is outside the container.

I have a test button inside my custom container and it will be green if the button has hovered.

The X mark shows where is my pointer.

This is my Container.java.

public class Container extends UIObject {

    //== Fields ==//

    protected List<UIObject> listUIObjects;

    protected OrthographicCamera camera;
    protected Viewport viewportContent;

    //== Constructor ==//

    public Container(Viewport viewport, float x, float y, float width, float height) {
        super(viewport, x, y, width, height);

        listUIObjects = new ArrayList<>();

        camera = new OrthographicCamera();
        viewportContent = new ScreenViewport(camera);

        viewportContent.update((int) width, (int) height);
        viewportContent.setWorldSize(width, height);
        viewportContent.setScreenPosition((int) x, (int) y);

        camera.position.set(width / 2f, height / 2f, 0);
    }

    //== Class Methods ==//

    public void add(UIObject object) {
        // Set the container viewport in object.
        object.setViewport(viewportContent);
        listUIObjects.add(object);
    }

    public UIObject get(int i) {
        return listUIObjects.get(i);
    }

    public void remove(int i) {
        listUIObjects.remove(i);
    }

    @Override
    public void update() {
        viewportContent.update((int) width, (int) height);
        viewportContent.setWorldSize(width, height);
        viewportContent.setScreenPosition((int) x, (int) y);

        camera.position.set(width / 2f, height / 2f, 0);

        for (UIObject object: listUIObjects) {
            object.update();
        }
    }

    @Override
    protected void renderObject(SpriteBatch batch) {
        Rectangle scissor = new Rectangle();
        Rectangle clipBounds = new Rectangle(x, y, width, height);

        ScissorStack.calculateScissors(viewport.getCamera(), viewport.getScreenX(), viewport.getScreenY(), viewport.getScreenWidth(), viewport.getScreenHeight(), batch.getTransformMatrix(), clipBounds, scissor);

        if (ScissorStack.pushScissors(scissor)) {
            for (UIObject object: listUIObjects) {
                float firstX, firstY;
                firstX = object.x;
                firstY = object.y;

                object.x += x;
                object.y += y;

                object.render(batch);

                object.x = firstX;
                object.y = firstY;
            }

            TextHelper.renderText(batch, "Container", TextAlignment.LEFT, Color.RED, x, y, 1);

            batch.flush();
            ScissorStack.popScissors();
        }
    }
}

Button.update()

public void update() {
        // TODO: Handle click/touch.

        // Get X and Y input. Check every finger.

        int finger;

        for (finger = 0; finger < 10; finger++) {
            Vector3 input = new Vector3(Gdx.input.getX(finger), Gdx.input.getY(finger), 0);

            if (viewport != null) {
                viewport.unproject(input);
            }

            // Check if the x and y coordinates are at the button.

            boolean atButtonX = (input.x >= x && input.x <= x + width);
            boolean atButtonY = (input.y >= y && input.y <= y + height);

            hovered = hoverable && atButtonX && atButtonY;
            if (hovered) break;
        }

        if (Gdx.input.isTouched(finger) || Gdx.input.isTouched(finger)) {
            if (hovered) {
                if (clickable) downed = true;
            }
        } else {
            downed = false;
        }

        if (Gdx.input.justTouched()) {
            if (hovered) {
                if (clickable) clicked = true;
            }
        } else {
            clicked = false;
        }
    }


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source