I'm using LibGDX UI components to display the UI of my game.
I want to show a framed marble background behind my menus. For this I have a nine-patch image with the frame and a marble background image.
It tried to use both in my menu, composed of a ScrollPane containing a Table.
So I defined the 9 patch frame as the ScrollPane background:
com.badlogic.gdx.scenes.scene2d.ui.ScrollPane$ScrollPaneStyle: {
default: { ..., background: frame }
}
And add the (big) marble background to my table:
table.setBackground(skin.getTiledDrawable("big-marble-texture"));
However it looks like the frame is around the marble background, not part of it:
I cannot just make the marble texture part of the 9 patch: I want it to be tiled, not scaled to the menu dimension (I tried, it looks horrible). I also tried to display the frame directly in the Stage on top of the menu, it works but then the code is really painful to use, especially with dynamic UI like tooltips or moving cards.
What is the recommended way of doing this in libgdx UI components?
I am not sure what the recommended way of solving this is but one way is to create a class that is a composite of a TiledDrawable
and a NinePatch
and let that class extend BaseDrawable
.
That way you can override the draw
method to first draw the background as a TiledDrawable
(offset to account for the insets of the NinePatch
) and then draw the NinePatch
as the border.
For example:
package com.bornander.sandbox;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.NinePatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.utils.BaseDrawable;
import com.badlogic.gdx.scenes.scene2d.utils.TiledDrawable;
import com.badlogic.gdx.scenes.scene2d.utils.TransformDrawable;
public class BorderedTiledDrawable extends BaseDrawable implements TransformDrawable {
private TiledDrawable region;
private NinePatch patch;
private int left;
private int top;
private int right;
private int bottom;
public BorderedTiledDrawable(Texture background, Texture border, int left, int top, int right, int bottom) {
region = new TiledDrawable(new TextureRegion(background));
this.patch = new NinePatch(border, left, top, right, bottom);
this.left = left - 1;
this.top = top - 1;
this.right = right - 1;
this.bottom = bottom - 1;
setMinWidth(patch.getTotalWidth());
setMinHeight(patch.getTotalHeight());
setTopHeight(patch.getPadTop());
setRightWidth(patch.getPadRight());
setBottomHeight(patch.getPadBottom());
setLeftWidth(patch.getPadLeft());
}
@Override
public void draw(Batch batch, float x, float y, float originX, float originY, float width, float height, float scaleX, float scaleY, float rotation) {
region.draw(batch, x, y, originX, originY, width, height, scaleX, scaleY, rotation);
patch.draw(batch, x, y, originX, originY, width, height, scaleX, scaleY, rotation);
}
@Override
public void draw(Batch batch, float x, float y, float width, float height) {
region.draw(batch, x + left, y + top, width - (left + right), height - (top + bottom));
patch.draw(batch, x, y, width, height);
}
}
Which looks like this:
It does't fully work if your nine-patch has very rounded corners but that is also easy to tweak.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With