Make GUI plane only pickable where Controls are placed (click through whitespace)

Hello!

To increase performance I use a single plane for multiple GUI controls.
On this GUI plane there is some whitespace where no controls are placed.
When I want to click a GUI element that is behind this bigger GUI, the events are blocked by the whitespace of the GUI.

This is the GUI I want to create:

The red box is the plane where I placed the GUI on:

This playground show an example. You cannot click the back buttons when you click between the front buttons:
https://playground.babylonjs.com/#SWB9QN#1

Is there a solution for that or should I create a plane for every single UI element?

Thank you!

Pinging @msDestiny14

Is it possible to archive a similar behavior to the FullscreenUI? When using the fullscreen UI only the Controls are pickable and not the whole screen.

1 Like

Let me take a look. :slight_smile:

Hi there! I agree with @marlon360 a fullscreen UI would help because then you can just layout controls onto of controls. However that may not get the depth you want.

I tried a bunch of different solutions but didn’t yield the result we wanted. I tried:
firstPlane.isPickable = false;
button.isHitTestVisible = true;

The problem is we want the mesh to not be active but the Gui to still be clickable.

This is a very naive approach, but you could play with mesh picking in that case - GUI blocking other GUI | Babylon.js Playground

Those events are anyhow being triggered, so there is no performance hit

2 Likes

You can sample from the ADT texture and discard hits on transparent pixels by adding this to the end of your intersects method on the related mesh (pi: PickingInfo, advancedTexture: AdvancedDynamicTexture)

      if (pi.hit && pi.getTextureCoordinates()) {
        const { x, y } = pi.getTextureCoordinates()!;
        const { width, height } = advancedTexture.getSize();
        const sx = Math.round(x * width);
        const sy = Math.round(height - y * height);
        const point = advancedTexture.getContext().getImageData(sx, sy, 1, 1);
        // if the texture pixel under the picked point is transparent, ignore the hit
        if (point.data[3] < 0.5) {
          pi.hit = false;
          pi.pickedPoint = null;
          pi.pickedMesh = null;
        }
      }
1 Like