Skip to content

Using libGDX

Nick Johnson edited this page Feb 21, 2019 · 15 revisions

Setup

1. use LWJGL3 in libGDX

LWJGL3 is required.

One can use czyzby/gdx-setup (an alternative libgdx setup program) to setup a libgdx project with LWJGL3 enabled without breaking a sweat.

2. import ImGui

Follow Install page and things should be fine 😛.

Note that projects built by czyzby/gdx-setup don't need to add any more LWJGL dependency explicitly.

3. an example

An example is given below, using Gradle, targeting Windows desktop, ImGui v1.63-beta-03, libGDX v1.9.8. (libGDX v1.9.8 is the minimal version, more detail at this issue) and the libGDX project is built using czyzby/gdx-setup.

  • build.gradle at libgdx root
subprojects {
    repositories {
        ...
        maven { url "https://dl.bintray.com/kotlin/kotlin-dev" } // for Kotlin
        maven { url 'https://jitpack.io' } // repository Jitpack for kotlin-graphics/imgui
    }
}
  • build.gradle at core module
ext {
    ...
    imguiVersion = "ca150b4905132dfb66e2a12cdc279e087e56d0a5"
}
dependencies {
    ...
    //ImGui
    compile "com.github.kotlin-graphics:imgui:$imguiVersion"

    //required for retrieving a handle within core module
    compile "com.badlogicgames.gdx:gdx-backend-lwjgl3:$gdxVersion"
}

Hello, world! (java)

public class ImGuiExample extends ApplicationAdapter {
    private GlfwWindow window;
    private LwjglGlfw lwjglGlfw = LwjglGlfw.INSTANCE;
    private ImplGL3 implGL3 = ImplGL3.INSTANCE;
    private ImGui imGui = ImGui.INSTANCE;
    private Context context;

    @Override
    public void create() {
        window = new GlfwWindow(((Lwjgl3Graphics) Gdx.graphics).getWindow().getWindowHandle());
        context = new Context(null);
        lwjglGlfw.init(window, true, LwjglGlfw.GlfwClientApi.OpenGL);
        imGui.styleColorsDark(null);
    }

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

        lwjglGlfw.newFrame();

        imGui.begin("Demo_0", new boolean[]{true}, 0);
        imGui.text("Hello, world!");
        imGui.end();

        imGui.showDemoWindow(new boolean[]{true});

        imGui.render();
        implGL3.renderDrawData(imGui.getDrawData());
    }

    @Override
    public void dispose() {
        lwjglGlfw.shutdown();
        context.shutdown();
    }
}

Using imgui image with libGDX texture

In order to use image and imageButton from imgui, we need to recover the ID handle from our texture in order to be able to pass it to imgui.

To retrieve this handle, just call the getTextureObjectHandle method of our texture and pass the result to imgui for the userTextureId as for example:

ImGui.image(texture.textureObjectHandle, Vec2(imageWidth, imageHeight))

Input callbacks

To be able to use imgui inputs with libGDX, you must first create an InputProcessor or an InputAdapter in order to send the various callback to imgui.

Here is an example of the implementation :

class ImGuiInputProcessor : InputAdapter() {
    private val gdxGLFWKeyMap = mutableMapOf<Int, Int>()

    init {
        gdxGLFWKeyMap[Input.Keys.TAB] = GLFW.GLFW_KEY_TAB

        gdxGLFWKeyMap[Input.Keys.LEFT] = GLFW.GLFW_KEY_LEFT
        gdxGLFWKeyMap[Input.Keys.RIGHT] = GLFW.GLFW_KEY_RIGHT
        gdxGLFWKeyMap[Input.Keys.UP] = GLFW.GLFW_KEY_UP
        gdxGLFWKeyMap[Input.Keys.DOWN] = GLFW.GLFW_KEY_DOWN

        gdxGLFWKeyMap[Input.Keys.PAGE_UP] = GLFW.GLFW_KEY_PAGE_UP
        gdxGLFWKeyMap[Input.Keys.PAGE_DOWN] = GLFW.GLFW_KEY_PAGE_DOWN

        gdxGLFWKeyMap[Input.Keys.HOME] = GLFW.GLFW_KEY_HOME
        gdxGLFWKeyMap[Input.Keys.END] = GLFW.GLFW_KEY_END

        gdxGLFWKeyMap[Input.Keys.BACKSPACE] = GLFW.GLFW_KEY_BACKSPACE

        gdxGLFWKeyMap[Input.Keys.ENTER] = GLFW.GLFW_KEY_ENTER
        gdxGLFWKeyMap[Input.Keys.ESCAPE] = GLFW.GLFW_KEY_ESCAPE

        gdxGLFWKeyMap[Input.Keys.CONTROL_LEFT] = GLFW.GLFW_KEY_LEFT_CONTROL
        gdxGLFWKeyMap[Input.Keys.CONTROL_RIGHT] = GLFW.GLFW_KEY_RIGHT_CONTROL
        gdxGLFWKeyMap[Input.Keys.ALT_LEFT] = GLFW.GLFW_KEY_LEFT_ALT
        gdxGLFWKeyMap[Input.Keys.ALT_RIGHT] = GLFW.GLFW_KEY_RIGHT_ALT
        gdxGLFWKeyMap[Input.Keys.SHIFT_LEFT] = GLFW.GLFW_KEY_LEFT_SHIFT
        gdxGLFWKeyMap[Input.Keys.SHIFT_RIGHT] = GLFW.GLFW_KEY_RIGHT_SHIFT

        gdxGLFWKeyMap[Input.Keys.A] = GLFW.GLFW_KEY_A
        gdxGLFWKeyMap[Input.Keys.C] = GLFW.GLFW_KEY_C
        gdxGLFWKeyMap[Input.Keys.V] = GLFW.GLFW_KEY_V
        gdxGLFWKeyMap[Input.Keys.X] = GLFW.GLFW_KEY_X
        gdxGLFWKeyMap[Input.Keys.Y] = GLFW.GLFW_KEY_Y
        gdxGLFWKeyMap[Input.Keys.Z] = GLFW.GLFW_KEY_Z
    }

    override fun keyTyped(character: Char): Boolean {
        LwjglGL3.charCallback(character.toInt())
        return false
    }

    override fun scrolled(amount: Int): Boolean {
        LwjglGL3.scrollCallback(Vec2d(0, -amount))
        return false
    }

    override fun touchUp(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
        LwjglGL3.mouseButtonCallback(button, GLFW.GLFW_PRESS, 0)
        return false
    }

    override fun keyUp(keycode: Int): Boolean {
        gdxGLFWKeyMap[keycode]?.apply {
            LwjglGL3.keyCallback(this, 0, GLFW.GLFW_RELEASE, 0)
        }
        return false
    }

    override fun keyDown(keycode: Int): Boolean {
         gdxGLFWKeyMap[keycode]?.apply {
            LwjglGL3.keyCallback(this, 0, GLFW.GLFW_PRESS, 0)
        }
        return false
    }
}

Then, add this input processor in libGDX :

Gdx.input.inputProcessor = ImGuiInputProcessor()

Or with a multiplexer to be able to use it with a stage :

Gdx.input.inputProcessor = InputMultiplexer(stage, ImGuiInputProcessor())