[nifty] Creating generic button effects

I am attempting to make the generic button effects to where if you hover over the button, it changes image, and when the button is clicked it changes to a different image as well.



The problem is that I cannot get an to work with hover, and the options for hover are fighting with my onClick interaction.

[java] <controlDefinition name="player" controller="GUI.Side_Menu">

<interact onClick="player_click()" />

<effect>

<!-- <onClick name="fade" targetElement="img1" start="#ff" end="#00" oneShot="true" />–>

<!-- <onClick name="imageOverlay" targetElement="img1" filename="Textures/GUI/button_options_press.png" post="false" />–>

<onHover name="imageOverlay" targetElement="img1" filename="Textures/GUI/button_player_over.png" post="false" oneShot="true" />

<onHover name="fade" targetElement="img1" start="#ff" end="#00" oneShot="true" />

</effect>

<image id="img1" filename="Textures/GUI/button_player.png" imageMode="normal" align="left" valign="center" visibleToMouse="true" />

</controlDefinition>[/java]



This is about as close as I can get, if I uncomment the commented lines, i start running into problems. With the code the way it is right there, it works fine for hovering and not hovering, but if I activate the onClick stuff, the hover image never goes away and I cant see the onClick image.



Does anyone know what I could do to make this more efficient or to even make it work? Thanks!

Well, you can’t do that with the build in effects. It will only render the hover and onClick images on top of each other but there is currently no way you can change the image and make it not render the ones below. That’s what you’ve tried with the fade effect and this is btw a neat idea :slight_smile: But as you’ve noticed you can’t get it to work completly.



BUT :smiley:



What we need is a Nifty effect that can actually change the image that gets rendered. The idea is to have an effect that changes the image when the effect is active and resets it when the effects gets deactivated.



Well, here is the effect that you can simply add to your source. You can change the package if you want.



ChangeImage.java

[java]package de.lessvoid.nifty.effects.impl;



import java.util.logging.Logger;



import de.lessvoid.nifty.Nifty;

import de.lessvoid.nifty.effects.EffectImpl;

import de.lessvoid.nifty.effects.EffectProperties;

import de.lessvoid.nifty.effects.Falloff;

import de.lessvoid.nifty.elements.Element;

import de.lessvoid.nifty.elements.render.ImageRenderer;

import de.lessvoid.nifty.render.NiftyImage;

import de.lessvoid.nifty.render.NiftyImageMode;

import de.lessvoid.nifty.render.NiftyRenderEngine;



/**

  • This can be applied to an image element. This will change the original image of the
  • element to the image given in the “active” attribute. When the effect gets deactivated
  • the image is being restored to the image given with the “inactive” attribute.
  • @author void

    */

    public class ChangeImage implements EffectImpl {

    private Logger log = Logger.getLogger(ChangeImage.class.getName());

    private Element element;

    private NiftyImage activeImage;

    private NiftyImage inactiveImage;



    public void activate(final Nifty nifty, final Element element, final EffectProperties parameter) {

    this.element = element;

    this.activeImage = loadImage(“active”, nifty, parameter);

    this.inactiveImage = loadImage(“inactive”, nifty, parameter);

    }



    public void execute(final Element element, final float normalizedTime, final Falloff falloff, final NiftyRenderEngine r) {

    changeElementImage(activeImage);

    }



    public void deactivate() {

    changeElementImage(inactiveImage);

    activeImage.dispose();

    inactiveImage.dispose();

    }



    private NiftyImage loadImage(final String name, final Nifty nifty, final EffectProperties parameter) {

    NiftyImage image = nifty.getRenderEngine().createImage(parameter.getProperty(name), false);

    String imageMode = parameter.getProperty(“imageMode”, null);

    if (imageMode != null) {

    image.setImageMode(NiftyImageMode.valueOf(imageMode));

    }

    return image;

    }



    private void changeElementImage(final NiftyImage image) {

    ImageRenderer imageRenderer = element.getRenderer(ImageRenderer.class);

    if (imageRenderer == null) {

    log.warning(“this effect can only be applied to images!”);

    return;

    }

    imageRenderer.setImage(image);

    }

    }[/java]



    Once this effect is part of your code base you simply need to register it within your Nifty xml and you can use it. Here is an example:



    [xml] <registerEffect name=“changeImage” class=“de.lessvoid.nifty.effects.impl.ChangeImage” />

    …

    <controlDefinition name=“player”>

    <image filename=“normal.png” imageMode=“normal” align=“left” valign=“center” visibleToMouse=“true”>

    <effect>

    <onHover name=“changeImage” active=“hover.png” inactive=“normal.png” />

    <onClick name=“changeImage” active=“click.png” inactive=“normal.png” length=“infinite” />

    </effect>

    </image>

    </controlDefinition>[/xml]



    Note that we’re using two images here with the “active” and “inactive” attributes. This is necessary so that we can reset the image back to the original when the effect gets deactivated.



    Custom effects in Nifty simply require the implementation of the EffectImpl interface and when you register them with the registerEffect you can use them exactly as you would the build in ones.
1 Like

And I’ve just commited the new ChangeImage effect to the Nifty SVN :slight_smile:

2 Likes

wow awesome stuff guys. Thanks a ton!

Oh thank you for that new effect! :smiley:



Works like a charm. Not that I didn’t expect it not to, but glad I am. :wink: Of course I’m not using it that way exactly but it does the job nicely! All I need now is for it to do some nice fade-in/fade-out.

Hey void, could we get that ChangeImage class with the new ImageModeFactory please?



I’ve checked that class and, to say the least, it’s daunting. I know I’m stumped just reading through the constructor.



Would be much appreciated. :slight_smile:



Thanks.

hmm, sure. the new ImageModeFactory was contributed by someone else to open up nifty for more image modes (not yet documented I think ^^).



Well, I’ve checked the ChangeImage effect and the loadImage() method already supports the new image modes:



[java]private NiftyImage loadImage(final String name, final Nifty nifty, final EffectProperties parameter) {

NiftyImage image = nifty.getRenderEngine().createImage(parameter.getProperty(name), false);



String areaProviderProperty = new ImageModeHelper().getAreaProviderProperty(parameter);

String renderStrategyProperty = new ImageModeHelper().getRenderStrategyProperty(parameter);

if ((areaProviderProperty != null) || (renderStrategyProperty != null)) {

image.setImageMode(ImageModeFactory.getSharedInstance().createImageMode(areaProviderProperty,

renderStrategyProperty));

}



return image;

}[/java]



Which looks quite a bit odd. I agree :slight_smile: but it already supports the new image modes.



Am I missing something?

Thanks!



Seems to be working like a charm and the deprecated warning is gone. :slight_smile:

This seems to be broken here with the new version.



Getting this error:



[java]

H:UsersDanyDocumentsjMonkeyProjectsDisenthralsrccommadjackgamesdisenthralguiniftyChangeImage.java:57: error: ImageModeHelper() has private access in ImageModeHelper

ImageModeHelper imh = new ImageModeHelper();

[/java]



Code:

[java]

private NiftyImage loadImage(final String name, final Nifty nifty, final EffectProperties parameter) {

NiftyImage image = nifty.getRenderEngine().createImage(parameter.getProperty(name), false);

ImageModeHelper imh = new ImageModeHelper(); <-- Line 57

String areaProviderProperty = imh.getAreaProviderProperty(parameter);

String renderStrategyProperty = imh.getRenderStrategyProperty(parameter);

if ((areaProviderProperty != null) || (renderStrategyProperty != null)) {

image.setImageMode(ImageModeFactory.getSharedInstance().createImageMode(areaProviderProperty,

renderStrategyProperty));

}

return image;

}

[/java]



I suspect the new NetBeans is 'effing with me.