libGDXのNinePatchDrawableでハマったのでメモ


先日、会社のブログにて、[AndroidのInterpolatorをlibGDXを使ってグラフ化してみた](http://kayosystem.com/blogs/android-interpolator-to-graph-by-libgdx/)という記事を書きました。その時に作ったミニアプリがあるんですが、その時に`NinePatchDrawable`を使ってちょっとハマってしまったのでメモです。

普通にTexture食わせてもNinePatchとして扱われない
--------------------------

公式の[Ninepatches](https://github.com/libgdx/libgdx/wiki/Ninepatches)のコードを見ると、Scene2Dの`TextButtonStyle`などにNinePatchDrawableのインスタンス入れれば良さそうな感じなんですが…

```java:MyGdxGame.java
public class MyGdxGame extends ApplicationAdapter {
    private Stage stage;
    private TextButton button;

    @Override
    public void create() {
        // リソース読み込み
        Texture texNormal = new Texture("btn_default_normal_holo_light.9.png");
        Texture texPressed = new Texture("btn_default_pressed_holo_light.9.png");
        BitmapFont bitmapFont = new BitmapFont(Gdx.files.internal("arial-32-pad.fnt"));

        // スタイルの定義
        TextButton.TextButtonStyle style = new TextButton.TextButtonStyle();
        style.up = new NinePatchDrawable(new NinePatch(texNormal));
        style.down = new NinePatchDrawable(new NinePatch(texPressed));
        style.font = bitmapFont;
        style.fontColor = Color.BLACK;

        // ボタン生成
        button = new TextButton("Lorem ipsum.", style);
        stage = new Stage(new ScreenViewport());
        Gdx.input.setInputProcessor(stage);
        stage.addActor(button);
    }

    @Override
    public void resize(int width, int height) {
        stage.getViewport().update(width, height, true);
        button.setX(width * 0.5f - button.getWidth() * 0.5f);
        button.setY(height * 0.5f - button.getHeight() * 0.5f);
    }

    @Override
    public void render() {
        Gdx.gl.glClearColor(1, 1, 1, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        stage.act(Gdx.graphics.getDeltaTime());
        stage.draw();
    }
}
```

結果はこう…

![libgdx-9patch-before.png](https://qiita-image-store.s3.amazonaws.com/0/20530/efb2bacf-9036-72a7-7e8a-9ef9e3015544.png "libgdx-9patch-before.png")


＼アカン／

`TextureAtlas`を使うとうまくいくみたい
-----------------------------------

TextureAtlasを使わない解決方法を探していたんですが、結局すぐには見つかりませんでした。。
その途中で、テクスチャアトラスにNinePatch画像をまとめることもできるっぽいことを発見しまして、それを使うとうまく動作させることができました。
先ほどのコードの`create()`メソッドの一部を修正すると、動作できます。

```java
public class MyGdxGame extends ApplicationAdapter {
    private Stage stage;
    private TextButton button;

    @Override
    public void create() {
        // リソース読み込み
        BitmapFont bitmapFont = new BitmapFont(Gdx.files.internal("arial-32-pad.fnt"));
        TextureAtlas atlas = new TextureAtlas("btn_default_holo_light.atlas");

        // スタイルの定義
        TextButton.TextButtonStyle style = new TextButton.TextButtonStyle();
        style.up = new NinePatchDrawable(new NinePatch(atlas.createPatch("btn_default_normal_holo_light")));
        style.down = new NinePatchDrawable(new NinePatch(atlas.createPatch("btn_default_pressed_holo_light")));
        style.font = bitmapFont;
        style.fontColor = Color.BLACK;

        // ...省略
    }


    // ...省略
}
```

![libgdx-9patch-after.png](https://qiita-image-store.s3.amazonaws.com/0/20530/54b6709b-a812-1a5f-38da-be765e81ee49.png "libgdx-9patch-after.png")

完璧ですね！少しめんどくさいんですが、NinePatchを使うときはテクスチャアトラスにまとめるのが良さそうです。もっと簡単に使う方法ないのかな。。

今回使った素材は、Android SDKの中にあった画像を少し加工して使ってます。[こちらで共有してます](https://www.dropbox.com/sh/456kngzo9d9f7cu/AAA4Q8PXE0689lwe7bCyWdfua?dl=0)。フォントファイルは、[libGDXの公式リポジトリにあるもの](https://github.com/libgdx/libgdx/tree/e094e550edba4f699dd69ec62ef29babecc705c6/tests/gdx-tests-android/assets/data)です。

あと、`TextureAtlas`向けのパックファイル(*.atlas)を作る方法に関しては、[以前書きました](http://qiita.com/esperia09/items/cc5ab1e8ed7a246496ef)のでそちらをどうぞ。