[SOLVED] Hover effect that doesn't replace the default image

Hello

Is it possible to have a Hover effect where the default image is not replaced, instead the hover image (or indeed pressed image) is alpha blended with it? I ask because I’d like a highlight over a number of my buttons. The highlight would be identical for all buttons, and I’d rather not create two images for each button if I could possibly avoid it. Ideally this could be a Pulse effect, or something like ImageSwap (but instead ImageOveraly).

I took a quick look and it looks like this is not currently possible, and would require shader changes to do so? I’ve not been near the shader yet, so probably won’t be hacking at the source for this one :wink:

RR

@rockfire said: Hello

Is it possible to have a Hover effect where the default image is not replaced, instead the hover image (or indeed pressed image) is alpha blended with it? I ask because I’d like a highlight over a number of my buttons. The highlight would be identical for all buttons, and I’d rather not create two images for each button if I could possibly avoid it. Ideally this could be a Pulse effect, or something like ImageSwap (but instead ImageOveraly).

I took a quick look and it looks like this is not currently possible, and would require shader changes to do so? I’ve not been near the shader yet, so probably won’t be hacking at the source for this one :wink:

RR

Did you try PulseColor?

I have to play around with it, as I’m not sure if I made it impossible to do… however, doing the following should work:

[java]
Effect effect = new Effect(EffectType.PulseColor, EffectEvent.Hover, 0.5f);
effect.setEffectColor(someColor);
b.addEffect(EffectEvent.Hover, effect); // or b.setEffect(effect); as the event has already been specified in the effect
[/java]

This should replace the current effect with one that alters the color of the current image in a pulse fashion. I believe that TextFields use this currently.

If I missed the point of this, just slap me and I’ll try again :wink: In the mean time, I’ll test to make sure this works correctly.

Nope… doesn’t work due to how the effects are loaded. I need to have a look at a few things, but think I can get this sorted out correctly to allow for whatever effect as apposed to image based only.

Heh, prepare for a tiny slap :smiley:

Thats not quite what I meant. An image would better illustrate :-

The defaultImg …

(I have lots of these)

The hoverImg …

( I have one of these)

Would result in a pulsing version of …

@rockfire said: Heh, prepare for a tiny slap :-D

Thats not quite what I meant. An image would better illustrate :-

The defaultImg …

(I have lots of these)

The hoverImg …

( I have one of these)

Would result in a pulsing version of …

Ah… gotcha. Currently, I am guessing that one fades out while the other fades in? Or? Otherwise this wouldn’t be an issue.

Heh… think I have a solution for this.

I’ll give it a go here to make sure it works… but I’m thinking you could use the button Icon as the hover image and forward the effect to that element instead.

I’ll see if I can put together a test and make sure it works correctly.

Here is a really quick (cheesy) implementation… it really needs to not be doing things like creating the images each time and such:

[java]
ButtonAdapter hover = new ButtonAdapter(
screen,
UIDUtil.getUID(),
Vector2f.ZERO,
new Vector2f(100,100)
) {
@Override
public void onButtonFocus(MouseMotionEvent evt) {
Effect effect = new Effect(EffectType.Pulse, EffectEvent.Hover, 0.25f);
effect.setBlendImage(screen.createNewTexture(“Textures/highlight.png”));
effect.setElement(this.getButtonIcon());
screen.getEffectManager().applyEffect(effect);
}
@Override
public void onButtonLostFocus(MouseMotionEvent evt) {
Effect effect = new Effect(EffectType.ImageSwap, EffectEvent.LoseFocus, 0.25f);
effect.setBlendImage(screen.createNewTexture(screen.getStyle(“Common”).getString(“blankImg”)));
effect.setElement(this.getButtonIcon());
screen.getEffectManager().applyEffect(effect);
}
};
hover.setColorMap(“Textures/button.png”);
hover.clearAltImages();
hover.setButtonIcon(100, 100, screen.getStyle(“Common”).getString(“blankImg”));

screen.addElement(hover);
hover.centerToParent();
[/java]

Thanks so much! That totally did the trick, this is exactly visual effect I was after. One minor thing however … is the hover + click sound effects don’t seem to work. Do I need to manually fire these from the onButtonFocus() overrides, and if so what is the best way?

@rockfire said: Thanks so much! That totally did the trick, this is exactly visual effect I was after. One minor thing however ... is the hover + click sound effects don't seem to work. Do I need to manually fire these from the onButtonFocus() overrides, and if so what is the best way?

Ooops… sorry, had to run out. There are a couple ways you can handle this.

Add the audio file to the effect and call the alternate method for applying it (screen.getEffectManager().applyEffect(etc, etc, audio info, vloume);
Or… don’t call clearAltImages and replace the effects you want one at a time.

I think the first choice is what you are looking for though.

EDIT: Yeah… clearAltImages removes all effects associated with the button. You’re just interested in removing the hover effect. Lemme see what the method name is. one sec…

I think this should do it:

[java]
button.setButtonHoverInfo(null,null);
[/java]

@t0neg0d said: Ooops... sorry, had to run out. There are a couple ways you can handle this.

Add the audio file to the effect and call the alternate method for applying it (screen.getEffectManager().applyEffect(etc, etc, audio info, vloume);
Or… don’t call clearAltImages and replace the effects you want one at a time.

I think the first choice is what you are looking for though.

EDIT: Yeah… clearAltImages removes all effects associated with the button. You’re just interested in removing the hover effect. Lemme see what the method name is. one sec…

I think this should do it:

[java]
button.setButtonHoverInfo(null,null);
[/java]

Thanks once again, all is now working :slight_smile:

Using setButtonHoverInfo(null, null) returned the click sound effect, but the hover sound was still missing in action. So I did as suggested, and just set audio file on the focus effect. For completeness, here is the full solution …

[java]
final Style style = screen.getStyle(“Button”);
final Texture hoverImage = screen.createNewTexture(style.getString(“hoverImg”));
final Texture blankImg = screen.createNewTexture(screen.getStyle(“Common”).getString(“blankImg”));
final Vector2f defSize = style.getVector2f(“defaultSize”);
ButtonAdapter button = new ButtonAdapter(screen, UIDUtil.getUID(), Vector2f.ZERO, defSize,
style.getVector4f(“resizeBorders”),
null) {
public void onButtonMouseLeftUp(MouseButtonEvent evt, boolean toggled) {
// Do stuff
}

        @Override
        public void onButtonFocus(MouseMotionEvent evt) {
            super.onButtonFocus(evt);
            Effect effect = new Effect(EffectType.Pulse, EffectEvent.Hover, 0.25f);
            effect.setBlendImage(hoverImage);
            effect.setElement(this.getButtonIcon());
            if (style.getBoolean("useHoverSound")) {
                effect.setAudioVolume(style.getFloat("hoverSoundVolume"));
                effect.setAudioFile(style.getString("hoverSound"));
            }
            screen.getEffectManager().applyEffect(effect);
        }

        @Override
        public void onButtonLostFocus(MouseMotionEvent evt) {
            super.onButtonLostFocus(evt);
            Effect effect = new Effect(EffectType.ImageSwap, EffectEvent.LoseFocus, 0.25f);
            effect.setBlendImage(blankImg);
            effect.setElement(this.getButtonIcon());
            screen.getEffectManager().applyEffect(effect);
        }
    };
    button.setColorMap(style.getString("defaultImg"));
    button.setButtonHoverInfo(null, null);
    button.setButtonIcon(defSize.x, defSize.y, screen.getStyle("Common").getString("blankImg"));

[/java]

Hello, since i got the same issue recently, maybe telling you how i managed it can help you.
I’ve used another approch as instead of using the effect manager, i’ve created a new windows on top of the button, that windows only got the Hover and i make it child of the button so he follow the button, it give me the same effect you looking for (i can’t tell for the sound i didn’t use it.).
As exemple (it’s for a card GUI so…) :
[java]
package entitysystem.card;

import com.jme3.asset.AssetManager;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector4f;
import tonegod.gui.controls.buttons.ButtonAdapter;
import tonegod.gui.controls.windows.Window;
import tonegod.gui.core.Screen;
import tonegod.gui.effects.Effect;

public class CardInitializer {
private Screen screen = null;
Window cardHover;

public ButtonAdapter initialize(String cardName) {
    
    ButtonAdapter card = new ButtonAdapter(screen, cardName, new Vector2f(300f, 250f), new Vector2f(200f, 300f), Vector4f.ZERO , "Textures/Cards/"+cardName+"_256px.png"){

        @Override
        public void setHasFocus(boolean hasFocus) {
            super.setHasFocus(hasFocus);
            if(hasFocus){
                cardHover.show();
            } else {
                cardHover.hide();
            }
        }
        
    };

    card.removeEffect(Effect.EffectEvent.Hover); //I remove the button effect as it annoy me.
    card.removeEffect(Effect.EffectEvent.Press); //same as the hover effect.
    card.setIsResizable(false);
    card.setIsMovable(true);
    card.centerToParent();
    
    card.addChild(cardHover);
    cardHover.centerToParent();   //The Hover image got the same size than the card.
    cardHover.hide();                      //I hide the hover until i need it.

    
    return card;
}

public void Init(Screen screen) {
    this.screen = screen;
    
    cardHover = new Window(screen, "cardHover", new Vector2f(300f, 250f), new Vector2f(200f, 300f), Vector4f.ZERO , "Textures/Cards/cardHover.png");
    cardHover.setIsResizable(false);                     //No resizing.
    cardHover.getDragBar().setIsVisible(false);   //We don't need the dragBar.
    cardHover.setIsMovable(false);                       //We don't want the hover to move by himself.
    cardHover.setIgnoreMouse(true);                  //Hover should not respond to mouse event.
    //I've founded the ignoreMouse recently maybe everything before isn't needed when activating it...
}

void cleanup() {
    screen.removeElement(cardHover);
    cardHover = null;
}

}
[/java]

Ps : I dono if it’s done properly, but, it’s how i did it XD. GL