Recommended way to create irregular custom shaped GUI buttons?

I’m really loving Babylon.js GUI but am just wondering if there’s an easy way to create irregular custom shaped GUI buttons like say this:

It looks like I’d have to replicate the Rectangle class (modify the _localDraw method) to achieve what I want, or just make the default rectangle 100% transparent and use images for the button states, but either way I guess the mouse over hit target will still be a rectangle right?

Do not have a recommended way but wondered if something in this topic was useful with images
detectPointerOnOpaqueOnly for gui image only buttons

Only on mobile so cannot test.

2 Likes

Thanks @JohnK. I’ll check it out.

Approaches:

  1. Make background transparent and use image button:
    • Pros: easy implementation & custom hit target
    • Cons: can’t easily animate image color on state change (uses static colors of image)
  2. Extend Rectangle & Button classes with override methods to support background shapes other than rectangle:
    • Pros: can animate background color on state change
    • Cons: harder implementation & potentially no custom hit target (hit target still a rectangle despite background shape?)

Very interesting subject! :slight_smile:

I made an experiment here: Babylon.js Playground
Works for white/grayscale images to add a uniform color

basicly, image.recolor( redMultiplier, greenMultiplier, blueMultiplier)

2 Likes

@aWeirdo thanks!

I’m also having a bit of success with the second of my options. I created a Shape.ts extending the standard GUI Rectangle.ts then created a new draw method for the shapes I need:

    const stepArrowLength = height / 2 / 2;

    context.beginPath();
    switch(this._shape) {
        case Shape.STEP_ARROW_FIRST: {
            context.moveTo(x, y);
            context.lineTo(x + width - stepArrowLength, y);
            context.lineTo(x + width, y + (height / 2));
            context.lineTo(x + width - stepArrowLength, y + height);
            context.lineTo(x, y + height);
            context.lineTo(x, y);
            break;
        }
        case Shape.STEP_ARROW_MIDDLE: {
            context.moveTo(x, y);
            context.lineTo(x + width - stepArrowLength, y);
            context.lineTo(x + width, y + (height / 2));
            context.lineTo(x + width - stepArrowLength, y + height);
            context.lineTo(x, y + height);
            context.lineTo(x + stepArrowLength, y + (height / 2));
            context.lineTo(x, y);
            break;
        }
        case Shape.STEP_ARROW_LAST: {
            context.moveTo(x, y);
            context.lineTo(x + width, y);
            context.lineTo(x + width, y + height);
            context.lineTo(x, y + height);
            context.lineTo(x + stepArrowLength, y + (height / 2));
            context.lineTo(x, y);
            break;
        }
    }
    context.closePath();

Then I make a new ShapeButton.ts extending Shape which is essentially a duplicate of the inbuilt Button class.

I’m not sure how to show this in a PG, so I might just post the code here when complete.

Here’s a screenshot of the STEP_ARROW_MIDDLE shape:
Annotation 2020-06-22 114705

4 Likes

I think the image recolor option is a good one for say monochrome SVG icon color changes like is typically done with CSS.

1 Like

Is it possible to make an Image follow a mesh in any way? Like a rectangle does using linkWithMesh API? I have checked the playground by @aWeirdo but I want an image to follow a mesh. Thanks in advance.

1 Like

Why not using linkWithMesh with your gui elements ?

A playground would be nice to understand where you are blocked

1 Like

Yes I have tried that

And what is blocking you ???

1 Like

Sorry for the late reply. Actually I wanted to create a triangle in the GUI but I was not able to do so. So I changed my approach to adding an image. But after spending some more time I was able to create a triangle by extending the Rectangle. Here’s a very basic playground of the same : https://playground.babylonjs.com/#NTZ766#5

Thank you.

1 Like