Reputation:
Hello I whant to make a ImageButton and the disabled image should be tinted gray. I use a Skin and a .json file to define it. Is there a better way to get a gray tinted image than duplicate all images and add them to the texturepacker?
Upvotes: 6
Views: 1847
Reputation: 1751
You can set the tint color on disabled buttons, by using an ImageButtonStyle object, and use the newDrawable(Drawable drawable, Color tint) method from the Skin class.
In code it could look a little something like this. Notice that we have initialised the Skin object with a Texture Atlas, which holds our UI Textures. See the wiki for more information.
// Create the tint color. Notice we use LibGDX Color class
Color tintColor = new Color(0.5f, 0.5f, 0.5f, 1f);
ImageButton.ImageButtonStyle btnStyle = new ImageButton.ImageButtonStyle();
btnStyle.up = skin.getDrawable("my_button");
btnStyle.disabled = skin.newDrawable("my_button", tintColor);
ImageButton myButton = new ImageButton(btnStyle);
Upvotes: 3
Reputation: 6038
I think the best way (or even the only way) to accomplish this is by using shaders. Notice that shaders
is a whole subject on its own, but once mastered, or even acquainted with, can give your game many cool capabilities, like graying out images.
As to your question: The first things that are needed, are shaders that will affect your images (or, in our case, ImageButton
) in a way that will tint them gray. Luckily, these shaders have been implemented by somebody else, as an answer to a similar question. So, if we extract the required shaders from the above, we have the following:
grey.vsh:
attribute vec4 a_position;
attribute vec4 a_color;
attribute vec2 a_texCoord0;
uniform mat4 u_projTrans;
varying vec4 vColor;
varying vec2 vTexCoord;
void main() {
vColor = a_color;
vTexCoord = a_texCoord0;
gl_Position = u_projTrans * a_position;
}
grey.fsh:
#ifdef GL_ES
#define LOWP lowp
precision mediump float;
#else
#define LOWP
#endif
varying LOWP vec4 vColor;
varying vec2 vTexCoord;
uniform sampler2D u_texture;
uniform float grayscale;
void main() {
vec4 texColor = texture2D(u_texture, vTexCoord);
float gray = dot(texColor.rgb, vec3(0.96, 0.96, 0.96));
texColor.rgb = mix(vec3(gray), texColor.rgb, grayscale);
gl_FragColor = texColor * vColor;
}
Assuming these files are in your assets
folder, we can create a ShaderProgram that will compile and use these shaders:
ShaderProgram shader = new ShaderProgram(Gdx.files.internal("grey.vsh"), Gdx.files.internal("grey.fsh"));
Now we can extend ImageButton
so that it'll use shader
when we want it to be grey out. In this example, ImageButton
is greyed out (or colored in) when it's clicked:
public class GreyedOutImageBtn extends ImageButton {
private boolean isGreyedOut; // A flag that determines whther or not this should be greyed out
public GreyedOutImageBtn(ImageButtonStyle style) {
super(style);
addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
// When clicked, toggle the grey effect
Gdx.app.log("ClickListener", "Click");
setIsGreyedOut(!getIsGreyedOut());
}
});
isGreyedOut = false;
}
public boolean getIsGreyedOut() {
return isGreyedOut;
}
public void setIsGreyedOut(boolean isGreyedOut) {
this.isGreyedOut = isGreyedOut;
}
@Override
public void draw(Batch batch, float parentAlpha) {
if (getIsGreyedOut()) {
batch.end();
batch.setShader(shader); // Set our grey-out shader to the batch
batch.begin();
super.draw(batch, parentAlpha); // Draw the image with the greyed out affect
batch.setShader(null); // Remove shader from batch so that other images using the same batch won't be affected
}
else {
// If not required to be grey-out, do normal drawing
super.draw(batch, parentAlpha);
}
}
}
This give the following results. Before:
After:
After you've better understood shaders
, you can build your own to be specific for your needs.
Upvotes: 3