Dynamic Background Images on Lemur Buttons

Hi,

I’m creating a lemur button style - and I have three different background images that I want to use for “normal”, “clicked” and “hover” states. At the moment though the only option I see inside the button object is to set a hightlight colour which changes the text.

Have I missed something or is there no way to do this with swapping textures?

On a related note these buttons contain no text (one reason the highlight colour is no use!) but there seems to be no way to create a button without it creating all the un-needed (in this case) bitmap text objects. Is that right or did I miss something?

Thanks,
Tim

You should be able to set button actions in the style and those can do whatever you want them to. (For example, up/down presses on trigger and so on.)

You can even query the highlight state to see if you should switch images… even if you aren’t using the highlight color.

You can see how the glass style sets the button up/down thing (because that is not default behavior) here:

If you have trouble extrapolating that to swapping the image on highlight then let me know.

Never mind - fixed it.

Hi,

Very helpful thanks - got it working:

private static void setupButton(AssetManager assetManager, Styles styles, String id, String background, String pressed, String hover) {
    IconComponent backgroundTx = new IconComponent(background);
    IconComponent pressedTx = new IconComponent(pressed);
    IconComponent hoverTx = new IconComponent(hover);
    
    Attributes attrs = styles.getSelector(Button.ELEMENT_ID, RIGHT_ARROW);
    attrs.set("background", backgroundTx);
    
    List<Command<Button>> command = Collections.singletonList((source) -> {
        if( source.isPressed() ) {
            source.setBackground(pressedTx);
        } else {
            if( source.isHighlightOn()) {
                source.setBackground(hoverTx);
            } else {
                source.setBackground(backgroundTx);
            }
        }
    });
    
    Map<Button.ButtonAction, List<Command<Button>>> commands = new EnumMap<>(Button.ButtonAction.class);
    commands.put(Button.ButtonAction.Down, command);
    commands.put(Button.ButtonAction.Up, command);
    commands.put(Button.ButtonAction.HighlightOn, command);
    commands.put(Button.ButtonAction.HighlightOff, command);
    
    attrs.set("buttonCommands", commands);
}

I just have one more question - what’s the difference between Effect and Command and why are we using Command here?

Thanks,
Tim

Oh, bug in the above - it’s always using the same id not the one passed in. :smiley:

Effect is related to the animation system. Command is a general way of adding hooks to a button. You could also have used an effect in this case. I don’t know off the top of my head how to set it through styling and I thought that’s what you were asking at first… so I went with the one I know works. :slight_smile:

Edit: effects are nice especially for concepts like up/down highlight/unhighlight because they have a built in concept of things that are the reverse of another thing. But Buttons give us options because they keep the state anyway.

I am setting through styling, just not using Groovy :slight_smile:

It works well, I just set the button style and the background and clicking and everything all magically appears. Very nice :slight_smile:

1 Like

So, for anyone else coming to this thread trying to do this I had to make a change:

private static void setupButton(AssetManager assetManager, Styles styles, String id, String background, String pressed, String hover) {
    QuadBackgroundComponent backgroundTx = new QuadBackgroundComponent(assetManager.loadTexture(background));
    QuadBackgroundComponent pressedTx = new QuadBackgroundComponent(assetManager.loadTexture(pressed));
    QuadBackgroundComponent hoverTx = new QuadBackgroundComponent(assetManager.loadTexture(hover));
    
    Attributes attrs = styles.getSelector(Button.ELEMENT_ID, id);
    attrs.set("background", backgroundTx);
    attrs.set("insets", new Insets3f(2, 2, 2, 2));
    
    List<Command<Button>> command = Collections.singletonList((source) -> {
        if( source.isPressed() ) {
            source.setBackground(pressedTx.clone());
        } else {
            if( source.isHighlightOn()) {
                source.setBackground(hoverTx.clone());
            } else {
                source.setBackground(backgroundTx.clone());
            }
        }
    });
    
    Map<Button.ButtonAction, List<Command<Button>>> commands = new EnumMap<>(Button.ButtonAction.class);
    commands.put(Button.ButtonAction.Down, command);
    commands.put(Button.ButtonAction.Up, command);
    commands.put(Button.ButtonAction.HighlightOn, command);
    commands.put(Button.ButtonAction.HighlightOff, command);
    
    attrs.set("buttonCommands", commands);
}

If I don’t clone() the QuadBackgroundComponent every time it vanishes after the first time it is displayed!

i.e. the button displays, then when I hover over it the hover displays, but then when I move off it the original never comes back and we end up with an empty space!

If you don’t clone it then it’s shared with all of the other ones… the next time you add it to something else then it will disappear from the others.

Styling normally takes care of the cloning for you but it can’t when you are setting it directly like that.

You may be better off in the long run creating an actual listener class that can hold references… but I can’t remember if the action commands are also cloned (I think they are but I’m not sure).

In any case, I’m glad you got it working.

Yeah. It’s not ideal having to constantly clone it instead of cycling through the same 3 per component.
Not worth trying to optimise though I think. The extra complexity would be a lot for the small gain.