diff --git a/example/build.gradle b/example/build.gradle index 39da07f..ab2573e 100644 --- a/example/build.gradle +++ b/example/build.gradle @@ -1,12 +1,25 @@ plugins { id 'application' - id 'checkstyle' } repositories { mavenCentral() } +application { + mainClass = 'Main' +} + dependencies { implementation project(':imgui-app') } + +task start(type: JavaExec, dependsOn: build) { + main = 'Main' + classpath = sourceSets.test.runtimeClasspath + jvmArgs = ["-Dimgui.library.path=${System.getProperty('libPath', '../bin')}"] + + if (org.gradle.internal.os.OperatingSystem.current().isMacOsX()) { + jvmArgs += ['-XstartOnFirstThread', '-Djava.awt.headless=true'] + } +} diff --git a/example/src/main/java/ExampleImGuiNodeEditor.java b/example/src/main/java/ExampleImGuiNodeEditor.java new file mode 100644 index 0000000..0567a8d --- /dev/null +++ b/example/src/main/java/ExampleImGuiNodeEditor.java @@ -0,0 +1,124 @@ +import imgui.extension.nodeditor.NodeEditor; +import imgui.extension.nodeditor.NodeEditorConfig; +import imgui.extension.nodeditor.NodeEditorContext; +import imgui.extension.nodeditor.flag.NodeEditorPinKind; +import imgui.flag.ImGuiCond; +import imgui.internal.ImGui; +import imgui.type.ImBoolean; +import imgui.type.ImLong; + +import java.awt.Desktop; +import java.net.URI; + +public class ExampleImGuiNodeEditor { + private static final NodeEditorContext CONTEXT; + private static final String URL = "https://github.com/thedmd/imgui-node-editor/tree/687a72f940"; + + static { + NodeEditorConfig config = new NodeEditorConfig(); + config.setSettingsFile(null); + CONTEXT = new NodeEditorContext(config); + } + + public static void show(final ImBoolean showImNodeEditorWindow, final Graph graph) { + ImGui.setNextWindowSize(500, 400, ImGuiCond.Once); + ImGui.setNextWindowPos(ImGui.getMainViewport().getPosX() + 100, ImGui.getMainViewport().getPosY() + 200, ImGuiCond.Once); + if (ImGui.begin("imgui-node-editor Demo", showImNodeEditorWindow)) { + ImGui.text("This a demo graph editor for imgui-node-editor"); + + ImGui.alignTextToFramePadding(); + ImGui.text("Repo:"); + ImGui.sameLine(); + if (ImGui.button(URL)) { + try { + Desktop.getDesktop().browse(new URI(URL)); + } catch (Exception e) { + e.printStackTrace(); + } + } + + if (ImGui.button("Navigate to content")) { + NodeEditor.navigateToContent(1); + } + + NodeEditor.setCurrentEditor(CONTEXT); + NodeEditor.begin("Node Editor"); + + for (Graph.GraphNode node : graph.nodes.values()) { + NodeEditor.beginNode(node.nodeId); + + ImGui.text(node.getName()); + + NodeEditor.beginPin(node.getInputPinId(), NodeEditorPinKind.Input); + ImGui.text("-> In"); + NodeEditor.endPin(); + + ImGui.sameLine(); + + NodeEditor.beginPin(node.getOutputPinId(), NodeEditorPinKind.Output); + ImGui.text("Out ->"); + NodeEditor.endPin(); + + NodeEditor.endNode(); + } + + if (NodeEditor.beginCreate()) { + final ImLong a = new ImLong(); + final ImLong b = new ImLong(); + if (NodeEditor.queryNewLink(a, b)) { + final Graph.GraphNode source = graph.findByOutput(a.get()); + final Graph.GraphNode target = graph.findByInput(b.get()); + if (source != null && target != null && source.outputNodeId != target.nodeId && NodeEditor.acceptNewItem()) { + source.outputNodeId = target.nodeId; + } + } + } + NodeEditor.endCreate(); + + int uniqueLinkId = 1; + for (Graph.GraphNode node : graph.nodes.values()) { + if (graph.nodes.containsKey(node.outputNodeId)) { + NodeEditor.link(uniqueLinkId++, node.getOutputPinId(), graph.nodes.get(node.outputNodeId).getInputPinId()); + } + } + + NodeEditor.suspend(); + + final long nodeWithContextMenu = NodeEditor.getNodeWithContextMenu(); + if (nodeWithContextMenu != -1) { + ImGui.openPopup("node_context"); + ImGui.getStateStorage().setInt(ImGui.getID("delete_node_id"), (int) nodeWithContextMenu); + } + + if (ImGui.isPopupOpen("node_context")) { + final int targetNode = ImGui.getStateStorage().getInt(ImGui.getID("delete_node_id")); + if (ImGui.beginPopup("node_context")) { + if (ImGui.button("Delete " + graph.nodes.get(targetNode).getName())) { + graph.nodes.remove(targetNode); + ImGui.closeCurrentPopup(); + } + ImGui.endPopup(); + } + } + + if (NodeEditor.showBackgroundContextMenu()) { + ImGui.openPopup("node_editor_context"); + } + + if (ImGui.beginPopup("node_editor_context")) { + if (ImGui.button("Create New Node")) { + final Graph.GraphNode node = graph.createGraphNode(); + final float canvasX = NodeEditor.toCanvasX(ImGui.getMousePosX()); + final float canvasY = NodeEditor.toCanvasY(ImGui.getMousePosY()); + NodeEditor.setNodePosition(node.nodeId, canvasX, canvasY); + ImGui.closeCurrentPopup(); + } + ImGui.endPopup(); + } + + NodeEditor.resume(); + NodeEditor.end(); + } + ImGui.end(); + } +} diff --git a/example/src/main/java/ExampleImNodes.java b/example/src/main/java/ExampleImNodes.java new file mode 100644 index 0000000..565b4c8 --- /dev/null +++ b/example/src/main/java/ExampleImNodes.java @@ -0,0 +1,111 @@ +import imgui.extension.imnodes.ImNodes; +import imgui.extension.imnodes.ImNodesContext; +import imgui.extension.imnodes.flag.ImNodesPinShape; +import imgui.flag.ImGuiCond; +import imgui.flag.ImGuiMouseButton; +import imgui.internal.ImGui; +import imgui.type.ImBoolean; +import imgui.type.ImInt; + +import java.awt.Desktop; +import java.net.URI; + +public class ExampleImNodes { + private static final ImNodesContext CONTEXT = new ImNodesContext(); + private static final String URL = "https://github.com/Nelarius/imnodes/tree/5959729410"; + + private static final ImInt LINK_A = new ImInt(); + private static final ImInt LINK_B = new ImInt(); + + public static void show(final ImBoolean showImNodesWindow, final Graph graph) { + ImGui.setNextWindowSize(500, 400, ImGuiCond.Once); + ImGui.setNextWindowPos(ImGui.getMainViewport().getPosX() + 100, ImGui.getMainViewport().getPosY() + 100, ImGuiCond.Once); + if (ImGui.begin("ImNodes Demo", showImNodesWindow)) { + ImGui.text("This a demo graph editor for ImNodes"); + + ImGui.alignTextToFramePadding(); + ImGui.text("Repo:"); + ImGui.sameLine(); + if (ImGui.button(URL)) { + try { + Desktop.getDesktop().browse(new URI(URL)); + } catch (Exception e) { + e.printStackTrace(); + } + } + + ImNodes.editorContextSet(CONTEXT); + ImNodes.beginNodeEditor(); + + for (Graph.GraphNode node : graph.nodes.values()) { + ImNodes.beginNode(node.nodeId); + + ImNodes.beginNodeTitleBar(); + ImGui.text(node.getName()); + ImNodes.endNodeTitleBar(); + + ImNodes.beginInputAttribute(node.getInputPinId(), ImNodesPinShape.CircleFilled); + ImGui.text("In"); + ImNodes.endInputAttribute(); + + ImGui.sameLine(); + + ImNodes.beginOutputAttribute(node.getOutputPinId()); + ImGui.text("Out"); + ImNodes.endOutputAttribute(); + + ImNodes.endNode(); + } + + int uniqueLinkId = 1; + for (Graph.GraphNode node : graph.nodes.values()) { + if (graph.nodes.containsKey(node.outputNodeId)) { + ImNodes.link(uniqueLinkId++, node.getOutputPinId(), graph.nodes.get(node.outputNodeId).getInputPinId()); + } + } + + final boolean isEditorHovered = ImNodes.isEditorHovered(); + + ImNodes.endNodeEditor(); + + if (ImNodes.isLinkCreated(LINK_A, LINK_B)) { + final Graph.GraphNode source = graph.findByOutput(LINK_A.get()); + final Graph.GraphNode target = graph.findByInput(LINK_B.get()); + if (source != null && target != null && source.outputNodeId != target.nodeId) { + source.outputNodeId = target.nodeId; + } + } + + if (ImGui.isMouseClicked(ImGuiMouseButton.Right)) { + final int hoveredNode = ImNodes.getHoveredNode(); + if (hoveredNode != -1) { + ImGui.openPopup("node_context"); + ImGui.getStateStorage().setInt(ImGui.getID("delete_node_id"), hoveredNode); + } else if (isEditorHovered) { + ImGui.openPopup("node_editor_context"); + } + } + + if (ImGui.isPopupOpen("node_context")) { + final int targetNode = ImGui.getStateStorage().getInt(ImGui.getID("delete_node_id")); + if (ImGui.beginPopup("node_context")) { + if (ImGui.button("Delete " + graph.nodes.get(targetNode).getName())) { + graph.nodes.remove(targetNode); + ImGui.closeCurrentPopup(); + } + ImGui.endPopup(); + } + } + + if (ImGui.beginPopup("node_editor_context")) { + if (ImGui.button("Create New Node")) { + final Graph.GraphNode node = graph.createGraphNode(); + ImNodes.setNodeScreenSpacePos(node.nodeId, ImGui.getMousePosX(), ImGui.getMousePosY()); + ImGui.closeCurrentPopup(); + } + ImGui.endPopup(); + } + } + ImGui.end(); + } +} diff --git a/example/src/main/java/Extra.java b/example/src/main/java/Extra.java new file mode 100644 index 0000000..6d29f57 --- /dev/null +++ b/example/src/main/java/Extra.java @@ -0,0 +1,30 @@ +import imgui.ImGui; +import imgui.app.Application; +import imgui.type.ImBoolean; + +public class Extra { + private static final ImBoolean SHOW_DEMO_WINDOW = new ImBoolean(false); + private static final ImBoolean SHOW_IMNODES_DEMO_WINDOW = new ImBoolean(false); + private static final ImBoolean SHOW_IMGUI_NODE_EDITOR_DEMO_WINDOW = new ImBoolean(false); + + private static final Graph GRAPH = new Graph(); + + public static void show(final Application app) { + ImGui.colorEdit3("Background Color", app.getColorBg().getData()); + ImGui.checkbox("Show Demo Window", SHOW_DEMO_WINDOW); + ImGui.checkbox("Show ImNodes Demo Window", SHOW_IMNODES_DEMO_WINDOW); + ImGui.checkbox("Show imgui-node-editor Demo Window", SHOW_IMGUI_NODE_EDITOR_DEMO_WINDOW); + + if (SHOW_DEMO_WINDOW.get()) { + ImGui.showDemoWindow(SHOW_DEMO_WINDOW); + } + + if (SHOW_IMNODES_DEMO_WINDOW.get()) { + ExampleImNodes.show(SHOW_IMNODES_DEMO_WINDOW, GRAPH); + } + + if (SHOW_IMGUI_NODE_EDITOR_DEMO_WINDOW.get()) { + ExampleImGuiNodeEditor.show(SHOW_IMGUI_NODE_EDITOR_DEMO_WINDOW, GRAPH); + } + } +} diff --git a/example/src/main/java/Graph.java b/example/src/main/java/Graph.java new file mode 100644 index 0000000..04f24e1 --- /dev/null +++ b/example/src/main/java/Graph.java @@ -0,0 +1,65 @@ +import java.util.HashMap; +import java.util.Map; + +public final class Graph { + public int nextNodeId = 1; + public int nextPinId = 100; + + public final Map nodes = new HashMap<>(); + + public Graph() { + final GraphNode first = createGraphNode(); + final GraphNode second = createGraphNode(); + first.outputNodeId = second.nodeId; + } + + public GraphNode createGraphNode() { + final GraphNode node = new GraphNode(nextNodeId++, nextPinId++, nextPinId++); + this.nodes.put(node.nodeId, node); + return node; + } + + public GraphNode findByInput(final long inputPinId) { + for (GraphNode node : nodes.values()) { + if (node.getInputPinId() == inputPinId) { + return node; + } + } + return null; + } + + public GraphNode findByOutput(final long outputPinId) { + for (GraphNode node : nodes.values()) { + if (node.getOutputPinId() == outputPinId) { + return node; + } + } + return null; + } + + public static final class GraphNode { + public final int nodeId; + public final int inputPinId; + public final int outputPinId; + + public int outputNodeId = -1; + + public GraphNode(final int nodeId, final int inputPinId, final int outputPintId) { + this.nodeId = nodeId; + this.inputPinId = inputPinId; + this.outputPinId = outputPintId; + } + + public int getInputPinId() { + return inputPinId; + } + + public int getOutputPinId() { + return outputPinId; + } + + public String getName() { + return "Node " + (char) (64 + nodeId); + } + } +} diff --git a/example/src/main/java/Main.java b/example/src/main/java/Main.java index 60b941a..728d195 100644 --- a/example/src/main/java/Main.java +++ b/example/src/main/java/Main.java @@ -2,9 +2,16 @@ import imgui.ImGui; import imgui.ImGuiIO; import imgui.app.Application; import imgui.app.Configuration; +import imgui.extension.imnodes.ImNodes; import imgui.flag.ImGuiConfigFlags; +import imgui.flag.ImGuiInputTextFlags; +import imgui.type.ImString; + +public class Main extends Application { + private final ImString str = new ImString(5); + private final float[] flt = new float[1]; + private int count = 0; -public final class Main extends Application { @Override protected void configure(final Configuration config) { config.setTitle("Example Application"); @@ -20,11 +27,29 @@ public final class Main extends Application { io.addConfigFlags(ImGuiConfigFlags.DockingEnable); // Enable Docking io.addConfigFlags(ImGuiConfigFlags.ViewportsEnable); // Enable Multi-Viewport / Platform Windows io.setConfigViewportsNoTaskBarIcon(true); + + ImNodes.initialize(); + } + + @Override + protected void disposeImGui() { + ImNodes.shutdown(); + super.disposeImGui(); } @Override public void process() { - ImGui.text("Hello, World"); + ImGui.text("Hello, World!"); + if (ImGui.button("Save")) { + count++; + } + ImGui.sameLine(); + ImGui.text(String.valueOf(count)); + ImGui.inputText("string", str, ImGuiInputTextFlags.CallbackResize); + ImGui.sliderFloat("float", flt, 0, 1); + ImGui.separator(); + ImGui.text("Extra"); + Extra.show(this); } public static void main(final String[] args) { diff --git a/imgui-app/src/main/java/imgui/app/Application.java b/imgui-app/src/main/java/imgui/app/Application.java index ed7a6dd..3224ad4 100644 --- a/imgui-app/src/main/java/imgui/app/Application.java +++ b/imgui-app/src/main/java/imgui/app/Application.java @@ -12,7 +12,11 @@ package imgui.app; *
  • {@link #configure(Configuration)} It's called before window creation, so only basic application setups are expected.
  • *
  • {@link #initWindow(Configuration)} Method creates application window.
  • *
  • {@link #initImGui(Configuration)} Method initializes Dear ImGui context. Could be used to do Dear ImGui setup as well.
  • + *
  • {@link #preRun()} Method called once, before application loop.
  • + *
  • {@link #preProcess()} Method called every frame, before {@link #process()}.
  • *
  • {@link #process()} Method is meant to be overridden with user application logic.
  • + *
  • {@link #postProcess()} Method called every frame, after {@link #process()}.
  • + *
  • {@link #postRun()} Method called once, after application loop.
  • *
  • {@link #disposeImGui()} Destroys Dear ImGui context.
  • *
  • {@link #disposeWindow()} Destroys application window.
  • * @@ -27,17 +31,11 @@ package imgui.app; *
    {@code
      * import imgui.ImGui;
      * import imgui.app.Application;
    - * import imgui.app.Configuration;
      *
      * public class Main extends Application {
      *     @Override
    - *     protected void configure(final Configuration config) {
    - *         config.setTitle("Example Application");
    - *     }
    - *
    - *     @Override
      *     public void process() {
    - *         ImGui.text("Hello, World");
    + *         ImGui.text("Hello, World!");
      *     }
      *
      *     public static void main(final String[] args) {
    @@ -55,13 +53,25 @@ package imgui.app;
      */
     public abstract class Application extends Window {
         /**
    -     * Method is called before window creation. Could be used to provide basic window information, like title name etc.
    +     * Method called before window creation. Could be used to provide basic window information, like title name etc.
          *
          * @param config configuration object with basic window information
          */
         protected void configure(final Configuration config) {
         }
     
    +    /**
    +     * Method called once, before application run loop.
    +     */
    +    protected void preRun() {
    +    }
    +
    +    /**
    +     * Method called once, after application run loop.
    +     */
    +    protected void postRun() {
    +    }
    +
         /**
          * Entry point of any ImGui application. Use it to start the application loop.
          *
    @@ -69,7 +79,9 @@ public abstract class Application extends Window {
          */
         public static void launch(final Application app) {
             initialize(app);
    +        app.preRun();
             app.run();
    +        app.postRun();
             app.dispose();
         }
     
    diff --git a/imgui-app/src/main/java/imgui/app/Color.java b/imgui-app/src/main/java/imgui/app/Color.java
    new file mode 100644
    index 0000000..33cb78a
    --- /dev/null
    +++ b/imgui-app/src/main/java/imgui/app/Color.java
    @@ -0,0 +1,62 @@
    +package imgui.app;
    +
    +import lombok.Data;
    +import lombok.NoArgsConstructor;
    +
    +/**
    + * Object for color data.
    + */
    +@Data
    +@NoArgsConstructor
    +public class Color implements Cloneable {
    +    private final float[] data = new float[4];
    +
    +    public Color(final float[] color) {
    +        set(color);
    +    }
    +
    +    public Color(final float red, final float green, final float blue, final float alpha) {
    +        data[0] = red;
    +        data[1] = green;
    +        data[2] = blue;
    +        data[3] = alpha;
    +    }
    +
    +    public final void set(final float red, final float green, final float blue, final float alpha) {
    +        data[0] = red;
    +        data[1] = green;
    +        data[2] = blue;
    +        data[3] = alpha;
    +    }
    +
    +    public final void set(final float[] color) {
    +        System.arraycopy(color, 0, data, 0, 4);
    +    }
    +
    +    public final float getRed() {
    +        return data[0];
    +    }
    +
    +    public final float getGreen() {
    +        return data[1];
    +    }
    +
    +    public final float getBlue() {
    +        return data[2];
    +    }
    +
    +    public final float getAlpha() {
    +        return data[3];
    +    }
    +
    +    /**
    +     * Method to clone Color instance.
    +     *
    +     * @return cloned Color instance
    +     */
    +    @Override
    +    @SuppressWarnings("MethodDoesntCallSuperMethod")
    +    public Color clone() {
    +        return new Color(data);
    +    }
    +}
    diff --git a/imgui-app/src/main/java/imgui/app/Configuration.java b/imgui-app/src/main/java/imgui/app/Configuration.java
    index 92f6d55..3692504 100644
    --- a/imgui-app/src/main/java/imgui/app/Configuration.java
    +++ b/imgui-app/src/main/java/imgui/app/Configuration.java
    @@ -6,7 +6,7 @@ import lombok.Data;
      * Data class to provide basic information about the window. Like, the title name etc.
      */
     @Data
    -public final class Configuration {
    +public class Configuration {
         /**
          * Application title.
          */
    diff --git a/imgui-app/src/main/java/imgui/app/Window.java b/imgui-app/src/main/java/imgui/app/Window.java
    index c5b36d8..8e6f06a 100644
    --- a/imgui-app/src/main/java/imgui/app/Window.java
    +++ b/imgui-app/src/main/java/imgui/app/Window.java
    @@ -13,7 +13,6 @@ import org.lwjgl.opengl.GL32;
     import org.lwjgl.system.MemoryStack;
     import org.lwjgl.system.MemoryUtil;
     
    -import java.awt.Color;
     import java.nio.IntBuffer;
     import java.util.Objects;
     
    @@ -29,13 +28,14 @@ public abstract class Window {
         private String glslVersion = null;
     
         /**
    -     * Pointer to native GLFW window.
    +     * Pointer to the native GLFW window.
          */
         protected long handle;
    +
         /**
          * Background color of the window.
          */
    -    protected Color colorBg = Color.GRAY;
    +    protected final Color colorBg = new Color(.5f, .5f, .5f, 1);
     
         /**
          * Method to initialize application.
    @@ -126,13 +126,27 @@ public abstract class Window {
             ImGui.createContext();
         }
     
    +    /**
    +     * Method called every frame, before calling {@link #process()} method.
    +     */
    +    protected void preProcess() {
    +    }
    +
    +    /**
    +     * Method called every frame, after calling {@link #process()} method.
    +     */
    +    protected void postProcess() {
    +    }
    +
         /**
          * Main application loop.
          */
         protected final void run() {
             while (!GLFW.glfwWindowShouldClose(handle)) {
                 startFrame();
    +            preProcess();
                 process();
    +            postProcess();
                 endFrame();
             }
         }
    @@ -143,10 +157,7 @@ public abstract class Window {
         public abstract void process();
     
         private void startFrame() {
    -        if (colorBg != null) {
    -            GL32.glClearColor(colorBg.getRed() / 255f, colorBg.getGreen() / 255f, colorBg.getBlue() / 255f, colorBg.getAlpha() / 255f);
    -        }
    -
    +        GL32.glClearColor(colorBg.getRed(), colorBg.getGreen(), colorBg.getBlue(), colorBg.getAlpha());
             GL32.glClear(GL32.GL_COLOR_BUFFER_BIT | GL32.GL_DEPTH_BUFFER_BIT);
             imGuiGlfw.newFrame();
             ImGui.newFrame();
    @@ -183,4 +194,18 @@ public abstract class Window {
             GLFW.glfwTerminate();
             Objects.requireNonNull(GLFW.glfwSetErrorCallback(null)).free();
         }
    +
    +    /**
    +     * @return pointer to the native GLFW window
    +     */
    +    public final long getHandle() {
    +        return handle;
    +    }
    +
    +    /**
    +     * @return {@link Color} instance, which represents background color for the window
    +     */
    +    public final Color getColorBg() {
    +        return colorBg;
    +    }
     }
    diff --git a/imgui-binding/src/main/java/imgui/ImGui.java b/imgui-binding/src/main/java/imgui/ImGui.java
    index be6bf03..88f8220 100644
    --- a/imgui-binding/src/main/java/imgui/ImGui.java
    +++ b/imgui-binding/src/main/java/imgui/ImGui.java
    @@ -45,10 +45,10 @@ public class ImGui {
     
             final String extractedLibAbsPath = tryLoadFromClasspath(fullLibName);
     
    -        if (extractedLibAbsPath != null) {
    -            System.load(extractedLibAbsPath);
    -        } else if (libPath != null) {
    +        if (libPath != null) {
                 System.load(Paths.get(libPath).resolve(fullLibName).toFile().getAbsolutePath());
    +        } else if (extractedLibAbsPath != null) {
    +            System.load(extractedLibAbsPath);
             } else {
                 System.loadLibrary(libName);
             }
    diff --git a/imgui-lwjgl3/src/test/java/ExampleUi.java b/imgui-lwjgl3/src/test/java/ExampleUi.java
    deleted file mode 100644
    index c20d36d..0000000
    --- a/imgui-lwjgl3/src/test/java/ExampleUi.java
    +++ /dev/null
    @@ -1,512 +0,0 @@
    -import imgui.ImGuiViewport;
    -import imgui.flag.ImGuiColorEditFlags;
    -import imgui.flag.ImGuiCond;
    -import imgui.flag.ImGuiDir;
    -import imgui.flag.ImGuiInputTextFlags;
    -import imgui.flag.ImGuiStyleVar;
    -import imgui.flag.ImGuiWindowFlags;
    -import imgui.extension.imnodes.ImNodes;
    -import imgui.extension.imnodes.ImNodesContext;
    -import imgui.extension.imnodes.flag.ImNodesPinShape;
    -import imgui.extension.nodeditor.NodeEditor;
    -import imgui.internal.ImGui;
    -import imgui.internal.flag.ImGuiDockNodeFlags;
    -import imgui.extension.nodeditor.NodeEditorConfig;
    -import imgui.extension.nodeditor.NodeEditorContext;
    -import imgui.extension.nodeditor.flag.NodeEditorPinKind;
    -import imgui.type.ImBoolean;
    -import imgui.ImColor;
    -import imgui.type.ImInt;
    -import imgui.type.ImLong;
    -import imgui.type.ImString;
    -import org.lwjgl.BufferUtils;
    -
    -import javax.imageio.ImageIO;
    -import java.awt.image.BufferedImage;
    -import java.io.File;
    -import java.io.IOException;
    -import java.nio.ByteBuffer;
    -import java.util.HashMap;
    -import java.util.Map;
    -
    -import static org.lwjgl.opengl.GL32.GL_CLAMP_TO_EDGE;
    -import static org.lwjgl.opengl.GL32.GL_LINEAR;
    -import static org.lwjgl.opengl.GL32.GL_RGBA;
    -import static org.lwjgl.opengl.GL32.GL_RGBA8;
    -import static org.lwjgl.opengl.GL32.GL_TEXTURE_2D;
    -import static org.lwjgl.opengl.GL32.GL_TEXTURE_MAG_FILTER;
    -import static org.lwjgl.opengl.GL32.GL_TEXTURE_MIN_FILTER;
    -import static org.lwjgl.opengl.GL32.GL_TEXTURE_WRAP_S;
    -import static org.lwjgl.opengl.GL32.GL_TEXTURE_WRAP_T;
    -import static org.lwjgl.opengl.GL32.GL_UNSIGNED_BYTE;
    -import static org.lwjgl.opengl.GL32.glBindTexture;
    -import static org.lwjgl.opengl.GL32.glGenTextures;
    -import static org.lwjgl.opengl.GL32.glTexImage2D;
    -import static org.lwjgl.opengl.GL32.glTexParameteri;
    -
    -@SuppressWarnings({"MagicNumber", "VisibilityModifier"})
    -final class ExampleUi {
    -    private static final String IMGUI_DEMO_LINK = "https://raw.githubusercontent.com/ocornut/imgui/05bc204/imgui_demo.cpp";
    -
    -    private static final int COLOR_DODGERBLUE = ImColor.rgbToColor("#1E90FF");
    -    private static final int COLOR_CORAL = ImColor.rgbToColor("#FF7F50");
    -    private static final int COLOR_LIMEGREEN = ImColor.rgbToColor("#32CD32");
    -
    -    // Test data for payload
    -    private String dropTargetText = "Drop Here";
    -
    -    // Resizable input example
    -    private final ImString resizableStr = new ImString(5);
    -
    -    // Toggles
    -    private final ImBoolean showBottomDockedWindow = new ImBoolean(true);
    -    private final ImBoolean showDemoWindow = new ImBoolean();
    -    private final ImBoolean showImNodesWindow = new ImBoolean(false);
    -    private final ImBoolean showImNodeEditorWindow = new ImBoolean(false);
    -
    -    // Attach image example
    -    private int dukeTexture = 0;
    -
    -    private boolean isBottomDockedWindowInit = false;
    -
    -    // To modify background color dynamically
    -    final float[] backgroundColor = new float[]{0.5f, 0, 0};
    -
    -    // Context for imnodes example
    -    private ImNodesContext imNodesContext;
    -
    -    // Context for imgui-node-editor example
    -    private NodeEditorContext nodeEditorContext;
    -
    -    // Graph used both for imnodes and imgui-node-editor demo
    -    private final Graph graph = new Graph();
    -
    -    void render() throws Exception {
    -        if (imNodesContext == null) {
    -            imNodesContext = new ImNodesContext();
    -        }
    -        if (nodeEditorContext == null) {
    -            final NodeEditorConfig config = new NodeEditorConfig();
    -            config.setSettingsFile(null);
    -            nodeEditorContext = new NodeEditorContext(config);
    -        }
    -
    -        final int dockspaceId = ImGui.getID("MyDockSpace");
    -        showDockSpace(dockspaceId);
    -        setupBottomDockedWindow(dockspaceId);
    -        showBottomDockedWindow();
    -
    -        final ImGuiViewport mainViewport = ImGui.getMainViewport();
    -        ImGui.setNextWindowSize(600, 300, ImGuiCond.Once);
    -        ImGui.setNextWindowPos(mainViewport.getWorkPosX() + 10, mainViewport.getWorkPosY() + 10, ImGuiCond.Once);
    -
    -        ImGui.begin("Custom window");  // Start Custom window
    -        showWindowImage();
    -        showToggles();
    -
    -        ImGui.separator();
    -
    -        showDragNDrop();
    -        showBackgroundPicker();
    -
    -        ImGui.separator();
    -
    -        showResizableInput();
    -
    -        ImGui.separator();
    -        ImGui.newLine();
    -
    -        showDemoLink();
    -
    -        ImGui.end();  // End Custom window
    -
    -        if (showDemoWindow.get()) {
    -            ImGui.showDemoWindow(showDemoWindow);
    -        }
    -
    -        if (showImNodesWindow.get()) {
    -           showImNodesWindow();
    -        }
    -
    -        if (showImNodeEditorWindow.get()) {
    -            showImNodeEditorWindow();
    -        }
    -    }
    -
    -    private void showDockSpace(final int dockspaceId) {
    -        final ImGuiViewport mainViewport = ImGui.getMainViewport();
    -        final int windowFlags = ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoResize
    -            | ImGuiWindowFlags.NoMove | ImGuiWindowFlags.NoBringToFrontOnFocus | ImGuiWindowFlags.NoNavFocus | ImGuiWindowFlags.NoBackground;
    -
    -        ImGui.setNextWindowPos(mainViewport.getWorkPosX(), mainViewport.getWorkPosY());
    -        ImGui.setNextWindowSize(mainViewport.getWorkSizeX(), mainViewport.getWorkSizeY());
    -        ImGui.setNextWindowViewport(mainViewport.getID());
    -        ImGui.pushStyleVar(ImGuiStyleVar.WindowRounding, 0);
    -        ImGui.pushStyleVar(ImGuiStyleVar.WindowBorderSize, 0);
    -
    -        ImGui.pushStyleVar(ImGuiStyleVar.WindowPadding, 0, 0);
    -        ImGui.begin("Dockspace Demo", windowFlags);
    -        ImGui.popStyleVar(3);
    -
    -        ImGui.dockSpace(dockspaceId, 0, 0, ImGuiDockNodeFlags.PassthruCentralNode);
    -        ImGui.end();
    -    }
    -
    -    private void setupBottomDockedWindow(final int dockspaceId) {
    -        if (!isBottomDockedWindowInit) {
    -            ImGui.dockBuilderRemoveNode(dockspaceId);
    -            ImGui.dockBuilderAddNode(dockspaceId, ImGuiDockNodeFlags.DockSpace);
    -
    -            final int dockIdBottom = ImGui.dockBuilderSplitNode(dockspaceId, ImGuiDir.Down, .25f, null, null);
    -
    -            ImGui.dockBuilderDockWindow("Bottom Docked Window", dockIdBottom);
    -            ImGui.dockBuilderSetNodeSize(dockIdBottom, 150f, 150f);
    -            ImGui.dockBuilderFinish(dockspaceId);
    -
    -            isBottomDockedWindowInit = true;
    -        }
    -    }
    -
    -    private void showBottomDockedWindow() {
    -        if (showBottomDockedWindow.get()) {
    -            ImGui.begin("Bottom Docked Window", showBottomDockedWindow, ImGuiWindowFlags.AlwaysAutoResize);
    -            ImGui.text("An example of how to create docked windows.");
    -            ImGui.end();
    -        }
    -    }
    -
    -    private void showWindowImage() throws IOException {
    -        if (dukeTexture == 0) {
    -            dukeTexture = loadTexture(ImageIO.read(new File("src/test/resources/Duke_waving.png")));
    -        }
    -
    -        // Draw an image in the bottom-right corner of the window
    -        final float xPoint = ImGui.getWindowPosX() + ImGui.getWindowSizeX() - 100;
    -        final float yPoint = ImGui.getWindowPosY() + ImGui.getWindowSizeY();
    -        ImGui.getWindowDrawList().addImage(dukeTexture, xPoint, yPoint - 180, xPoint + 100, yPoint);
    -    }
    -
    -    private void showToggles() {
    -        ImGui.checkbox("Show Demo Window", showDemoWindow);
    -        ImGui.checkbox("Show Bottom Docked Window", showBottomDockedWindow);
    -        ImGui.checkbox("Show demo for imnodes", showImNodesWindow);
    -        ImGui.checkbox("Show demo for imgui-node-editor", showImNodeEditorWindow);
    -        if (ImGui.button("Reset Bottom Dock Window")) {
    -            isBottomDockedWindowInit = false;
    -        }
    -    }
    -
    -    private void showDragNDrop() {
    -        ImGui.button("Drag me");
    -        if (ImGui.beginDragDropSource()) {
    -            ImGui.setDragDropPayloadObject("payload_type", "Test Payload");
    -            ImGui.text("Drag started");
    -            ImGui.endDragDropSource();
    -        }
    -        ImGui.sameLine();
    -        ImGui.text(dropTargetText);
    -        if (ImGui.beginDragDropTarget()) {
    -            final Object payload = ImGui.acceptDragDropPayloadObject("payload_type");
    -            if (payload != null) {
    -                dropTargetText = (String) payload;
    -            }
    -            ImGui.endDragDropTarget();
    -        }
    -    }
    -
    -    private void showBackgroundPicker() {
    -        ImGui.alignTextToFramePadding();
    -        ImGui.text("Background color:");
    -        ImGui.sameLine();
    -        ImGui.colorEdit3("##click_counter_col", backgroundColor, ImGuiColorEditFlags.NoInputs | ImGuiColorEditFlags.NoDragDrop);
    -    }
    -
    -    private void showResizableInput() {
    -        ImGui.text("You can use text inputs with auto-resizable strings!");
    -        ImGui.inputText("Resizable input", resizableStr, ImGuiInputTextFlags.CallbackResize);
    -        ImGui.text("text len:");
    -        ImGui.sameLine();
    -        ImGui.textColored(COLOR_DODGERBLUE, Integer.toString(resizableStr.getLength()));
    -        ImGui.sameLine();
    -        ImGui.text("| buffer size:");
    -        ImGui.sameLine();
    -        ImGui.textColored(COLOR_CORAL, Integer.toString(resizableStr.getBufferSize()));
    -    }
    -
    -    private void showDemoLink() {
    -        ImGui.text("Consider to look the original ImGui demo: ");
    -        ImGui.setNextItemWidth(500);
    -        ImGui.textColored(COLOR_LIMEGREEN, IMGUI_DEMO_LINK);
    -        ImGui.sameLine();
    -        if (ImGui.button("Copy")) {
    -            ImGui.setClipboardText(IMGUI_DEMO_LINK);
    -        }
    -    }
    -
    -    private void showImNodesWindow() {
    -        ImGui.setNextWindowSize(400F, 400F, ImGuiCond.Appearing);
    -        ImGui.begin("Demo imnodes", showImNodesWindow);
    -
    -        ImGui.text("This a demo graph editor for ImNodes");
    -
    -        ImNodes.editorContextSet(imNodesContext);
    -        ImNodes.beginNodeEditor();
    -
    -        for (Graph.GraphNode node : graph.nodes.values()) {
    -            ImNodes.beginNode(node.nodeId);
    -
    -            ImNodes.beginNodeTitleBar();
    -            ImGui.text(node.getName());
    -            ImNodes.endNodeTitleBar();
    -
    -
    -            ImNodes.beginInputAttribute(node.getInputPinId(), ImNodesPinShape.CircleFilled);
    -            ImGui.text("In");
    -            ImNodes.endInputAttribute();
    -
    -            ImGui.sameLine();
    -
    -            ImNodes.beginOutputAttribute(node.getOutputPinId());
    -            ImGui.text("Out");
    -            ImNodes.endOutputAttribute();
    -
    -            ImNodes.endNode();
    -        }
    -
    -        int uniqueLinkId = 1;
    -        for (Graph.GraphNode node : graph.nodes.values()) {
    -            if (graph.nodes.containsKey(node.outputNodeId)) {
    -                ImNodes.link(uniqueLinkId++, node.getOutputPinId(), graph.nodes.get(node.outputNodeId).getInputPinId());
    -            }
    -        }
    -
    -        final boolean isEditorHovered = ImNodes.isEditorHovered();
    -
    -        ImNodes.endNodeEditor();
    -        final ImInt a = new ImInt();
    -        final ImInt b = new ImInt();
    -        if (ImNodes.isLinkCreated(a, b)) {
    -            final Graph.GraphNode source = graph.findByOutput(a.get());
    -            final Graph.GraphNode target = graph.findByInput(b.get());
    -            if (source != null && target != null && source.outputNodeId != target.nodeId) {
    -               source.outputNodeId = target.nodeId;
    -            }
    -        }
    -
    -        if (ImGui.isMouseClicked(1)) {
    -            final int hoveredNode = ImNodes.getHoveredNode();
    -            if (hoveredNode != -1) {
    -                ImGui.openPopup("node-context");
    -                ImGui.getStateStorage().setInt(ImGui.getID("delete-node-id"), hoveredNode);
    -            } else if (isEditorHovered) {
    -                ImGui.openPopup("node-editor-context");
    -            }
    -        }
    -
    -        if (ImGui.isPopupOpen("node-context")) {
    -            final int targetNode = ImGui.getStateStorage().getInt(ImGui.getID("delete-node-id"));
    -            if (ImGui.beginPopup("node-context")) {
    -                if (ImGui.button("Delete " + graph.nodes.get(targetNode).getName())) {
    -                    graph.nodes.remove(targetNode);
    -                    ImGui.closeCurrentPopup();
    -                }
    -                ImGui.endPopup();
    -            }
    -        }
    -
    -        if (ImGui.beginPopup("node-editor-context")) {
    -            if (ImGui.button("Create new node")) {
    -                final Graph.GraphNode node = graph.createGraphNode();
    -                ImNodes.setNodeScreenSpacePos(node.nodeId, ImGui.getMousePosX(), ImGui.getMousePosY());
    -                ImGui.closeCurrentPopup();
    -            }
    -            ImGui.endPopup();
    -        }
    -
    -        ImGui.end();
    -    }
    -
    -    private void showImNodeEditorWindow() {
    -        ImGui.setNextWindowSize(400F, 400F, ImGuiCond.Appearing);
    -        ImGui.begin("Demo imgui-node-editor", showImNodeEditorWindow);
    -
    -        ImGui.text("This a demo graph editor for imgui-node-editor");
    -
    -        if (ImGui.button("Navigate to content")) {
    -            NodeEditor.navigateToContent(1F);
    -        }
    -
    -        NodeEditor.setCurrentEditor(nodeEditorContext);
    -        NodeEditor.begin("Node Editor");
    -
    -        for (Graph.GraphNode node : graph.nodes.values()) {
    -            NodeEditor.beginNode(node.nodeId);
    -
    -            ImGui.text(node.getName());
    -
    -            NodeEditor.beginPin(node.getInputPinId(), NodeEditorPinKind.Input);
    -            ImGui.text("-> In");
    -            NodeEditor.endPin();
    -
    -            ImGui.sameLine();
    -
    -            NodeEditor.beginPin(node.getOutputPinId(), NodeEditorPinKind.Output);
    -            ImGui.text("Out ->");
    -            NodeEditor.endPin();
    -
    -            NodeEditor.endNode();
    -        }
    -
    -        if (NodeEditor.beginCreate()) {
    -            final ImLong a = new ImLong();
    -            final ImLong b = new ImLong();
    -            if (NodeEditor.queryNewLink(a, b)) {
    -                final Graph.GraphNode source = graph.findByOutput(a.get());
    -                final Graph.GraphNode target = graph.findByInput(b.get());
    -                if (source != null && target != null && source.outputNodeId != target.nodeId && NodeEditor.acceptNewItem()) {
    -                    source.outputNodeId = target.nodeId;
    -                }
    -            }
    -        }
    -        NodeEditor.endCreate();
    -
    -        int uniqueLinkId = 1;
    -        for (Graph.GraphNode node : graph.nodes.values()) {
    -            if (graph.nodes.containsKey(node.outputNodeId)) {
    -                NodeEditor.link(uniqueLinkId++, node.getOutputPinId(), graph.nodes.get(node.outputNodeId).getInputPinId());
    -            }
    -        }
    -
    -        NodeEditor.suspend();
    -        final long nodeWithContextMenu = NodeEditor.getNodeWithContextMenu();
    -        if (nodeWithContextMenu != -1) {
    -            ImGui.openPopup("node-context");
    -            ImGui.getStateStorage().setInt(ImGui.getID("delete-node-id"), (int) nodeWithContextMenu);
    -        }
    -
    -        if (ImGui.isPopupOpen("node-context")) {
    -            final int targetNode = ImGui.getStateStorage().getInt(ImGui.getID("delete-node-id"));
    -            if (ImGui.beginPopup("node-context")) {
    -                if (ImGui.button("Delete " + graph.nodes.get(targetNode).getName())) {
    -                    graph.nodes.remove(targetNode);
    -                    ImGui.closeCurrentPopup();
    -                }
    -                ImGui.endPopup();
    -            }
    -        }
    -
    -        if (NodeEditor.showBackgroundContextMenu()) {
    -            ImGui.openPopup("node-editor-context");
    -        }
    -        if (ImGui.beginPopup("node-editor-context")) {
    -            if (ImGui.button("Create new node")) {
    -                final Graph.GraphNode node = graph.createGraphNode();
    -                final float canvasX = NodeEditor.toCanvasX(ImGui.getMousePosX());
    -                final float canvasY = NodeEditor.toCanvasY(ImGui.getMousePosY());
    -                NodeEditor.setNodePosition(node.nodeId, canvasX, canvasY);
    -                ImGui.closeCurrentPopup();
    -            }
    -            ImGui.endPopup();
    -        }
    -        NodeEditor.resume();
    -
    -        NodeEditor.end();
    -        ImGui.end();
    -    }
    -
    -    private int loadTexture(final BufferedImage image) {
    -        final int[] pixels = new int[image.getWidth() * image.getHeight()];
    -        image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());
    -
    -        final ByteBuffer buffer = BufferUtils.createByteBuffer(image.getWidth() * image.getHeight() * 4); // 4 for RGBA, 3 for RGB
    -        for (int y = 0; y < image.getHeight(); y++) {
    -            for (int x = 0; x < image.getWidth(); x++) {
    -                final int pixel = pixels[y * image.getWidth() + x];
    -                buffer.put((byte) ((pixel >> 16) & 0xFF));
    -                buffer.put((byte) ((pixel >> 8) & 0xFF));
    -                buffer.put((byte) (pixel & 0xFF));
    -                buffer.put((byte) ((pixel >> 24) & 0xFF));
    -            }
    -        }
    -        buffer.flip();
    -
    -        final int textureID = glGenTextures();
    -        glBindTexture(GL_TEXTURE_2D, textureID);
    -
    -        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    -        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    -
    -        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    -        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    -
    -        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, image.getWidth(), image.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
    -
    -        return textureID;
    -    }
    -
    -
    -    // Simple graph struct for both of node editors demos
    -    private static final class Graph {
    -
    -        private int nextNodeId = 1;
    -        private int nextPinId = 100;
    -
    -        final Map nodes = new HashMap<>();
    -
    -        private Graph() {
    -            final GraphNode first = createGraphNode();
    -            final GraphNode second = createGraphNode();
    -            first.outputNodeId = second.nodeId;
    -        }
    -
    -        public GraphNode createGraphNode() {
    -            final GraphNode node = new GraphNode(nextNodeId++, nextPinId++, nextPinId++);
    -            this.nodes.put(node.nodeId, node);
    -            return node;
    -        }
    -
    -        public GraphNode findByInput(final long inputPinId) {
    -            for (GraphNode node : nodes.values()) {
    -                if (node.getInputPinId() == inputPinId) {
    -                    return node;
    -                }
    -            }
    -            return null;
    -        }
    -
    -        public GraphNode findByOutput(final long outputPinId) {
    -            for (GraphNode node : nodes.values()) {
    -                if (node.getOutputPinId() == outputPinId) {
    -                    return node;
    -                }
    -            }
    -            return null;
    -        }
    -
    -        private static final class GraphNode {
    -            private final int nodeId;
    -            private final int inputPinId;
    -            private final int outputPinId;
    -
    -            public int outputNodeId = -1;
    -
    -            private GraphNode(final int nodeId, final int inputPinId, final int outputPintId) {
    -                this.nodeId = nodeId;
    -                this.inputPinId = inputPinId;
    -                this.outputPinId = outputPintId;
    -            }
    -
    -            public int getInputPinId() {
    -                return inputPinId;
    -            }
    -
    -            public int getOutputPinId() {
    -                return outputPinId;
    -            }
    -
    -            public String getName() {
    -                return "Node " + (char) (64 + nodeId);
    -            }
    -        }
    -    }
    -}
    diff --git a/imgui-lwjgl3/src/test/java/ImGuiGlfwExample.java b/imgui-lwjgl3/src/test/java/ImGuiGlfwExample.java
    deleted file mode 100644
    index d6169a4..0000000
    --- a/imgui-lwjgl3/src/test/java/ImGuiGlfwExample.java
    +++ /dev/null
    @@ -1,288 +0,0 @@
    -import static org.lwjgl.glfw.Callbacks.glfwFreeCallbacks;
    -import static org.lwjgl.glfw.GLFW.GLFW_CONTEXT_VERSION_MAJOR;
    -import static org.lwjgl.glfw.GLFW.GLFW_CONTEXT_VERSION_MINOR;
    -import static org.lwjgl.glfw.GLFW.GLFW_FALSE;
    -import static org.lwjgl.glfw.GLFW.GLFW_OPENGL_CORE_PROFILE;
    -import static org.lwjgl.glfw.GLFW.GLFW_OPENGL_FORWARD_COMPAT;
    -import static org.lwjgl.glfw.GLFW.GLFW_OPENGL_PROFILE;
    -import static org.lwjgl.glfw.GLFW.GLFW_TRUE;
    -import static org.lwjgl.glfw.GLFW.GLFW_VISIBLE;
    -import static org.lwjgl.glfw.GLFW.glfwCreateWindow;
    -import static org.lwjgl.glfw.GLFW.glfwDefaultWindowHints;
    -import static org.lwjgl.glfw.GLFW.glfwDestroyWindow;
    -import static org.lwjgl.glfw.GLFW.glfwGetCurrentContext;
    -import static org.lwjgl.glfw.GLFW.glfwGetPrimaryMonitor;
    -import static org.lwjgl.glfw.GLFW.glfwGetVideoMode;
    -import static org.lwjgl.glfw.GLFW.glfwGetWindowSize;
    -import static org.lwjgl.glfw.GLFW.glfwInit;
    -import static org.lwjgl.glfw.GLFW.glfwMakeContextCurrent;
    -import static org.lwjgl.glfw.GLFW.glfwPollEvents;
    -import static org.lwjgl.glfw.GLFW.glfwSetErrorCallback;
    -import static org.lwjgl.glfw.GLFW.glfwSetWindowPos;
    -import static org.lwjgl.glfw.GLFW.glfwShowWindow;
    -import static org.lwjgl.glfw.GLFW.glfwSwapBuffers;
    -import static org.lwjgl.glfw.GLFW.glfwSwapInterval;
    -import static org.lwjgl.glfw.GLFW.glfwTerminate;
    -import static org.lwjgl.glfw.GLFW.glfwWindowHint;
    -import static org.lwjgl.glfw.GLFW.glfwWindowShouldClose;
    -import static org.lwjgl.opengl.GL32.GL_COLOR_BUFFER_BIT;
    -import static org.lwjgl.opengl.GL32.GL_TRUE;
    -import static org.lwjgl.opengl.GL32.glClear;
    -import static org.lwjgl.opengl.GL32.glClearColor;
    -import static org.lwjgl.system.MemoryStack.stackPush;
    -import static org.lwjgl.system.MemoryUtil.NULL;
    -
    -import imgui.ImFontAtlas;
    -import imgui.ImFontConfig;
    -import imgui.ImGui;
    -import imgui.ImGuiIO;
    -import imgui.ImGuiStyle;
    -import imgui.flag.ImGuiCol;
    -import imgui.flag.ImGuiConfigFlags;
    -import imgui.gl3.ImGuiImplGl3;
    -import imgui.glfw.ImGuiImplGlfw;
    -import java.io.ByteArrayOutputStream;
    -import java.io.IOException;
    -import java.io.InputStream;
    -import java.io.UncheckedIOException;
    -import java.nio.IntBuffer;
    -import java.util.Objects;
    -
    -import imgui.extension.imnodes.ImNodes;
    -import org.lwjgl.glfw.GLFWErrorCallback;
    -import org.lwjgl.glfw.GLFWVidMode;
    -import org.lwjgl.opengl.GL;
    -import org.lwjgl.system.MemoryStack;
    -
    -@SuppressWarnings("MagicNumber")
    -public final class ImGuiGlfwExample {
    -    private long windowPtr; // pointer to the current GLFW window
    -
    -    // LWJGJ3 window backend
    -    private final ImGuiImplGlfw imGuiGlfw = new ImGuiImplGlfw();
    -
    -    // LWJGL3 renderer (SHOULD be initialized)
    -    private final ImGuiImplGl3 imGuiGl3 = new ImGuiImplGl3();
    -    private String glslVersion = null; // We can initialize our renderer with different versions of the GLSL
    -
    -    // User UI to render
    -    private final ExampleUi exampleUi = new ExampleUi();
    -
    -    public void run() throws Exception {
    -        setupGlfw();
    -        setupImGui();
    -
    -        // Method initializes GLFW backend.
    -        // This method SHOULD be called after you've setup GLFW.
    -        // ImGui context should be created as well.
    -        imGuiGlfw.init(windowPtr, true);
    -        // Method initializes LWJGL3 renderer.
    -        // This method SHOULD be called after you've initialized your ImGui configuration (fonts and so on).
    -        // ImGui context should be created as well.
    -        imGuiGl3.init(glslVersion);
    -
    -        loop();
    -
    -        // You should clean up after yourself in reverse order.
    -        imGuiGl3.dispose();
    -        imGuiGlfw.dispose();
    -
    -        ImNodes.shutdown();
    -        ImGui.destroyContext();
    -
    -        disposeWindow();
    -    }
    -
    -    // Initialize GLFW + create an OpenGL context.
    -    // All code is mostly a copy-paste from the official LWJGL3 "Get Started": https://www.lwjgl.org/guide
    -    private void setupGlfw() {
    -        // Setup an error callback. The default implementation
    -        // will print the error message in System.err.
    -        GLFWErrorCallback.createPrint(System.err).set();
    -
    -        // Initialize GLFW. Most GLFW functions will not work before doing this.
    -        if (!glfwInit()) {
    -            throw new IllegalStateException("Unable to initialize GLFW");
    -        }
    -
    -        // Configure GLFW
    -        glfwDefaultWindowHints(); // optional, the current window hints are already the default
    -        glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // the window will stay hidden after creation
    -
    -        decideGlGlslVersions();
    -
    -        windowPtr = glfwCreateWindow(1280, 768, "Dear ImGui+LWJGL Example", NULL, NULL);
    -
    -        if (windowPtr == NULL) {
    -            throw new RuntimeException("Failed to create the GLFW window");
    -        }
    -
    -        // Get the thread stack and push a new frame
    -        try (MemoryStack stack = stackPush()) {
    -            final IntBuffer pWidth = stack.mallocInt(1); // int*
    -            final IntBuffer pHeight = stack.mallocInt(1); // int*
    -
    -            // Get the window size passed to glfwCreateWindow
    -            glfwGetWindowSize(windowPtr, pWidth, pHeight);
    -
    -            // Get the resolution of the primary monitor
    -            final GLFWVidMode vidmode = Objects.requireNonNull(glfwGetVideoMode(glfwGetPrimaryMonitor()));
    -
    -            // Center the window
    -            glfwSetWindowPos(windowPtr, (vidmode.width() - pWidth.get(0)) / 2, (vidmode.height() - pHeight.get(0)) / 2);
    -        } // the stack frame is popped automatically
    -
    -        glfwMakeContextCurrent(windowPtr); // Make the OpenGL context current
    -        glfwSwapInterval(GLFW_TRUE); // Enable v-sync
    -        glfwShowWindow(windowPtr); // Make the window visible
    -
    -        // IMPORTANT!!
    -        // This line is critical for LWJGL's interoperation with GLFW's
    -        // OpenGL context, or any context that is managed externally.
    -        // LWJGL detects the context that is current in the current thread,
    -        // creates the GLCapabilities instance and makes the OpenGL
    -        // bindings available for use.
    -        GL.createCapabilities();
    -    }
    -
    -    private void decideGlGlslVersions() {
    -        final boolean isMac = System.getProperty("os.name").toLowerCase().contains("mac");
    -        if (isMac) {
    -            glslVersion = "#version 150";
    -            glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    -            glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
    -            glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);  // 3.2+ only
    -            glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);            // Required on Mac
    -        } else {
    -            glslVersion = "#version 130";
    -            glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    -            glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
    -        }
    -    }
    -
    -    // Initialize Dear ImGui.
    -    private void setupImGui() {
    -        // IMPORTANT!!
    -        // This line is critical for Dear ImGui to work.
    -        ImGui.createContext();
    -        ImNodes.initialize();
    -        // ------------------------------------------------------------
    -        // Initialize ImGuiIO config
    -        final ImGuiIO io = ImGui.getIO();
    -
    -        io.setIniFilename(null); // We don't want to save .ini file
    -        io.addConfigFlags(ImGuiConfigFlags.NavEnableKeyboard);  // Enable Keyboard Controls
    -        io.addConfigFlags(ImGuiConfigFlags.DockingEnable);      // Enable Docking
    -        io.addConfigFlags(ImGuiConfigFlags.ViewportsEnable);    // Enable Multi-Viewport / Platform Windows
    -        io.setConfigViewportsNoTaskBarIcon(true);
    -
    -        // ------------------------------------------------------------
    -        // Fonts configuration
    -        // Read: https://raw.githubusercontent.com/ocornut/imgui/master/docs/FONTS.txt
    -
    -        final ImFontAtlas fontAtlas = io.getFonts();
    -        final ImFontConfig fontConfig = new ImFontConfig(); // Natively allocated object, should be explicitly destroyed
    -
    -        // Glyphs could be added per-font as well as per config used globally like here
    -        fontConfig.setGlyphRanges(fontAtlas.getGlyphRangesCyrillic());
    -
    -        // Add a default font, which is 'ProggyClean.ttf, 13px'
    -        fontAtlas.addFontDefault();
    -
    -        // Fonts merge example
    -        fontConfig.setMergeMode(true); // When enabled, all fonts added with this config would be merged with the previously added font
    -        fontConfig.setPixelSnapH(true);
    -
    -        fontAtlas.addFontFromMemoryTTF(loadFromResources("basis33.ttf"), 16, fontConfig);
    -
    -        fontConfig.setMergeMode(false);
    -        fontConfig.setPixelSnapH(false);
    -
    -        // Fonts from file/memory example
    -        // We can add new fonts from the file system
    -        fontAtlas.addFontFromFileTTF("src/test/resources/Righteous-Regular.ttf", 14, fontConfig);
    -        fontAtlas.addFontFromFileTTF("src/test/resources/Righteous-Regular.ttf", 16, fontConfig);
    -
    -        // Or directly from the memory
    -        fontConfig.setName("Roboto-Regular.ttf, 14px"); // This name will be displayed in Style Editor
    -        fontAtlas.addFontFromMemoryTTF(loadFromResources("Roboto-Regular.ttf"), 14, fontConfig);
    -        fontConfig.setName("Roboto-Regular.ttf, 16px"); // We can apply a new config value every time we add a new font
    -        fontAtlas.addFontFromMemoryTTF(loadFromResources("Roboto-Regular.ttf"), 16, fontConfig);
    -
    -        fontConfig.destroy(); // After all fonts were added we don't need this config more
    -
    -        // When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones.
    -        if (io.hasConfigFlags(ImGuiConfigFlags.ViewportsEnable)) {
    -            final ImGuiStyle style = ImGui.getStyle();
    -            style.setWindowRounding(0.0f);
    -            style.setColor(ImGuiCol.WindowBg, ImGui.getColorU32(ImGuiCol.WindowBg, 1));
    -        }
    -    }
    -
    -    // Main application loop
    -    private void loop() throws Exception {
    -        // Run the rendering loop until the user has attempted to close the window
    -        while (!glfwWindowShouldClose(windowPtr)) {
    -            startFrame();
    -
    -            // Any Dear ImGui code SHOULD go between ImGui.newFrame()/ImGui.render() methods
    -            imGuiGlfw.newFrame();
    -            ImGui.newFrame();
    -
    -            exampleUi.render();
    -            ImGui.render();
    -
    -            endFrame();
    -        }
    -    }
    -
    -    private void startFrame() {
    -        // Set the clear color and clear the window
    -        glClearColor(exampleUi.backgroundColor[0], exampleUi.backgroundColor[1], exampleUi.backgroundColor[2], 0.0f);
    -        glClear(GL_COLOR_BUFFER_BIT);
    -    }
    -
    -    private void endFrame() {
    -        // After Dear ImGui prepared a draw data, we use it in the LWJGL3 renderer.
    -        // At that moment ImGui will be rendered to the current OpenGL context.
    -        imGuiGl3.renderDrawData(ImGui.getDrawData());
    -
    -        if (ImGui.getIO().hasConfigFlags(ImGuiConfigFlags.ViewportsEnable)) {
    -            final long backupWindowPtr = glfwGetCurrentContext();
    -            ImGui.updatePlatformWindows();
    -            ImGui.renderPlatformWindowsDefault();
    -            glfwMakeContextCurrent(backupWindowPtr);
    -        }
    -
    -        glfwSwapBuffers(windowPtr);
    -        glfwPollEvents();
    -    }
    -
    -    private void disposeWindow() {
    -        glfwFreeCallbacks(windowPtr);
    -        glfwDestroyWindow(windowPtr);
    -        glfwTerminate();
    -        Objects.requireNonNull(glfwSetErrorCallback(null)).free();
    -    }
    -
    -    private byte[] loadFromResources(final String fileName) {
    -        try (InputStream is = Objects.requireNonNull(getClass().getClassLoader().getResourceAsStream(fileName));
    -            ByteArrayOutputStream buffer = new ByteArrayOutputStream()) {
    -
    -            final byte[] data = new byte[16384];
    -
    -            int nRead;
    -            while ((nRead = is.read(data, 0, data.length)) != -1) {
    -                buffer.write(data, 0, nRead);
    -            }
    -
    -            return buffer.toByteArray();
    -        } catch (IOException e) {
    -            throw new UncheckedIOException(e);
    -        }
    -    }
    -
    -    public static void main(final String[] args) throws Exception {
    -        new ImGuiGlfwExample().run();
    -    }
    -}
    diff --git a/imgui-lwjgl3/src/test/resources/Duke_waving.png b/imgui-lwjgl3/src/test/resources/Duke_waving.png
    deleted file mode 100644
    index 5c396a1..0000000
    Binary files a/imgui-lwjgl3/src/test/resources/Duke_waving.png and /dev/null differ
    diff --git a/imgui-lwjgl3/src/test/resources/Righteous-Regular.ttf b/imgui-lwjgl3/src/test/resources/Righteous-Regular.ttf
    deleted file mode 100644
    index fc9c0a8..0000000
    Binary files a/imgui-lwjgl3/src/test/resources/Righteous-Regular.ttf and /dev/null differ
    diff --git a/imgui-lwjgl3/src/test/resources/Roboto-Regular.ttf b/imgui-lwjgl3/src/test/resources/Roboto-Regular.ttf
    deleted file mode 100644
    index 7d9a6c4..0000000
    Binary files a/imgui-lwjgl3/src/test/resources/Roboto-Regular.ttf and /dev/null differ
    diff --git a/imgui-lwjgl3/src/test/resources/basis33.ttf b/imgui-lwjgl3/src/test/resources/basis33.ttf
    deleted file mode 100644
    index b20255b..0000000
    Binary files a/imgui-lwjgl3/src/test/resources/basis33.ttf and /dev/null differ