Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LibGDX 9 patch image over a tilable background

Tags:

java

libgdx

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:

enter image description here

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?

like image 468
Guillaume Avatar asked Sep 13 '25 10:09

Guillaume


1 Answers

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:

tiled and ninepatch

It does't fully work if your nine-patch has very rounded corners but that is also easy to tweak.

like image 79
bornander Avatar answered Sep 16 '25 00:09

bornander