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

2 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