diff --git a/.gitmodules b/.gitmodules
index 028a4fb..ccdc9c4 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,9 @@
[submodule "imgui"]
path = imgui
url = https://github.com/ocornut/imgui
+[submodule "imgui-node-editor"]
+ path = imgui-node-editor
+ url = https://github.com/thedmd/imgui-node-editor.git
+[submodule "imnodes"]
+ path = imnodes
+ url = https://github.com/Nelarius/imnodes.git
diff --git a/buildSrc/src/main/groovy/imgui/generate/GenerateLibs.groovy b/buildSrc/src/main/groovy/imgui/generate/GenerateLibs.groovy
index eb974e4..a01e1c3 100644
--- a/buildSrc/src/main/groovy/imgui/generate/GenerateLibs.groovy
+++ b/buildSrc/src/main/groovy/imgui/generate/GenerateLibs.groovy
@@ -39,7 +39,9 @@ class GenerateLibs extends DefaultTask {
// Copy ImGui h/cpp files
project.copy { CopySpec spec ->
- spec.from(project.rootProject.file('imgui')) { CopySpec it -> it.include('*.h', '*.cpp') }
+ ['imgui', 'imnodes', 'imgui-node-editor'].each {
+ spec.from(project.rootProject.file(it)) { CopySpec s -> s.include('*.h', '*.cpp', '*.inl') }
+ }
if (withFreeType) {
spec.from(project.rootProject.file('imgui/misc/freetype')) { CopySpec it -> it.include('*.h', '*.cpp') }
diff --git a/imgui-binding/src/main/java/imgui/imnodes/ImNodes.java b/imgui-binding/src/main/java/imgui/imnodes/ImNodes.java
new file mode 100644
index 0000000..7fa1a6d
--- /dev/null
+++ b/imgui-binding/src/main/java/imgui/imnodes/ImNodes.java
@@ -0,0 +1,501 @@
+package imgui.imnodes;
+
+import imgui.ImVec2;
+import imgui.type.ImBoolean;
+import imgui.type.ImInt;
+
+/**
+ * Bindings for Imnodes (https://github.com/Nelarius/imnodes/)
+ * Original library author - Johann Muszynski (https://github.com/Nelarius)
+ *
+ * Refer to the library's Github page for examples and support
+ */
+public final class ImNodes {
+ private static ImNodesStyle style;
+
+ private ImNodes() {
+ }
+
+ /*JNI
+ #include
+ #include
+ #include
+ #include "jni_common.h"
+ */
+
+ // An editor context corresponds to a set of nodes in a single workspace (created with a single
+ // Begin/EndNodeEditor pair)
+ //
+ // By default, the library creates an editor context behind the scenes, so using any of the imnodes
+ // functions doesn't require you to explicitly create a context.
+
+ public static ImNodesContext editorContextCreate() {
+ return new ImNodesContext();
+ }
+
+ public static void editorContextFree(final ImNodesContext context) {
+ context.destroy();
+ }
+
+ public static void editorContextSet(final ImNodesContext context) {
+ nEditorContextSet(context.ptr);
+ }
+
+ private static native void nEditorContextSet(long ptr); /*
+ imnodes::EditorContextSet((imnodes::EditorContext*)ptr);
+ */
+
+ /**
+ * Initialize the node editor system.
+ */
+ public static native void initialize(); /*
+ imnodes::Initialize();
+ */
+
+ public static native void shutdown(); /*
+ imnodes::Shutdown();
+ */
+
+ /**
+ * Returns the global style struct. See the struct declaration for default values.
+ */
+ public static ImNodesStyle getStyle() {
+ if (style == null) {
+ style = new ImNodesStyle(nGetStyle());
+ }
+ return style;
+ }
+
+ private static native long nGetStyle(); /*
+ return (intptr_t)&imnodes::GetStyle();
+ */
+
+ // Style presets matching the dear imgui styles of the same name.
+
+ public static native void styleColorsDark(); /*
+ imnodes::StyleColorsDark();
+ */
+
+ public static native void styleColorsClassic(); /*
+ imnodes::StyleColorsClassic();
+ */
+
+ public static native void styleColorsLight(); /*
+ imnodes::StyleColorsLight();
+ */
+
+ /**
+ * Use PushColorStyle and PopColorStyle to modify ImNodesColorStyle mid-frame.
+ */
+ public static native void pushColorStyle(int imNodesStyleColor, int color); /*
+ imnodes::PushColorStyle((imnodes::ColorStyle)imNodesStyleColor, color);
+ */
+
+ public static native void popColorStyle(); /*
+ imnodes::PopColorStyle();
+ */
+
+ public static native void pushStyleVar(int imNodesStyleVar, float value); /*
+ imnodes::PushStyleVar((imnodes::StyleVar)imNodesStyleVar, value);
+ */
+
+ public static native void popStyleVar(); /*
+ imnodes::PopStyleVar();
+ */
+
+ /**
+ * The top-level function call. Call this before calling BeginNode/EndNode. Calling this function
+ * will result the node editor grid workspace being rendered.
+ */
+ public static native void beginNodeEditor(); /*
+ imnodes::BeginNodeEditor();
+ */
+
+ public static native void endNodeEditor(); /*
+ imnodes::EndNodeEditor();
+ */
+
+ public static native void beginNode(int node); /*
+ imnodes::BeginNode(node);
+ */
+
+ public static native void endNode(); /*
+ imnodes::EndNode();
+ */
+
+ /**
+ * Render a link between attributes.
+ * The attributes ids used here must match the ids used in Begin(Input|Output)Attribute function
+ * calls. The order of source and target doesn't make a difference for rendering the link.
+ */
+ public static native void link(int id, int source, int target); /*
+ imnodes::Link(id, source, target);
+ */
+
+ /**
+ * Place your node title bar content (such as the node title, using ImGui::Text) between the
+ * following function calls. These functions have to be called before adding any attributes, or the
+ * layout of the node will be incorrect.
+ */
+ public static native void beginNodeTitleBar(); /*
+ imnodes::BeginNodeTitleBar();
+ */
+
+ public static native void endNodeTitleBar(); /*
+ imnodes::EndNodeTitleBar();
+ */
+
+ // Attributes are ImGui UI elements embedded within the node. Attributes can have pin shapes
+ // rendered next to them. Links are created between pins.
+ //
+ // The activity status of an attribute can be checked via the IsAttributeActive() and
+ // IsAnyAttributeActive() function calls. This is one easy way of checking for any changes made to
+ // an attribute's drag float UI, for instance.
+ //
+ // Each attribute id must be unique.
+
+ /**
+ * Create a static attribute block. A static attribute has no pin, and therefore can't be linked to
+ * anything. However, you can still use IsAttributeActive() and IsAnyAttributeActive() to check for
+ * attribute activity.
+ */
+ public static native void beginStaticAttribute(int id); /*
+ imnodes::BeginStaticAttribute(id);
+ */
+
+ public static native void endStaticAttribute(); /*
+ imnodes::EndStaticAttribute();
+ */
+
+ /**
+ * Create an input attribute block. The pin is rendered on left side.
+ */
+ public static void beginInputAttribute(final int id) {
+ beginInputAttribute(id, ImNodesPinShape.CircleFilled);
+ }
+
+ public static native void beginInputAttribute(int id, int imNodesPinShape); /*
+ imnodes::BeginInputAttribute(id, (imnodes::PinShape)imNodesPinShape);
+ */
+
+ public static native void endInputAttribute(); /*
+ imnodes::EndInputAttribute();
+ */
+
+ /**
+ * Create an output attribute block. The pin is rendered on the right side.
+ */
+ public static void beginOutputAttribute(final int id) {
+ beginOutputAttribute(id, ImNodesPinShape.CircleFilled);
+ }
+
+ public static native void beginOutputAttribute(int id, int imNodesPinShape); /*
+ imnodes::BeginOutputAttribute(id, (imnodes::PinShape)imNodesPinShape);
+ */
+
+ /**
+ * Push a single AttributeFlags value. By default, only AttributeFlags_None is set.
+ */
+ public static native void pushAttributeFlag(int imNodesAttributeFlags); /*
+ imnodes::PushAttributeFlag((imnodes::AttributeFlags)imNodesAttributeFlags);
+ */
+
+ public static native void endOutputAttribute(); /*
+ imnodes::EndOutputAttribute();
+ */
+
+ /**
+ * Returns true if the current node editor canvas is being hovered over by the mouse, and is not
+ * blocked by any other windows.
+ */
+ public static native boolean isEditorHovered(); /*
+ return imnodes::IsEditorHovered();
+ */
+
+ // Binding notice: getHoveredNode(), getHoveredLink() and getHoveredPin()
+ // return id of the hovered object. If there is no such object -1 will be returned.
+ // Use these functions after endNodeEditor() has been called.
+ //
+ // These methods implemented instead of the original bool imnodes::IsNodeHovered(int* node_id),
+ // bool imnodes::IsLinkHovered(int* link_id) and bool imnodes::IsPinHovered(int* attribute_id) for convenience.
+
+ /**
+ * @return id of the hovered node or -1 if there is no such object
+ */
+ public static native int getHoveredNode(); /*
+ int i;
+ return imnodes::IsNodeHovered(&i) ? i : -1;
+ */
+
+ /**
+ * @return id of the hovered link or -1 if there is no such object
+ */
+ public static native int getHoveredLink(); /*
+ int i;
+ return imnodes::IsLinkHovered(&i) ? i : -1;
+ */
+
+ /**
+ * @return id of the hovered pin or -1 if there is no such object
+ */
+ public static native int getHoveredPin(); /*
+ int i;
+ return imnodes::IsPinHovered(&i) ? i : -1;
+ */
+
+ /**
+ * Binding notice: getActiveAttribute() returns id the active attribute. If there is no active attribute -1 will be returned.
+ *
+ * This method implemented instead of the original bool imnodes::IsAnyAttributeActive(int* attribute_id) for convenience.
+ */
+ public static native int getActiveAttribute(); /*
+ int i;
+ return imnodes::IsAnyAttributeActive(&i) ? i : -1;
+ */
+
+ /**
+ * Was the previous attribute active? This will continuously return true while the left mouse button
+ * is being pressed over the UI content of the attribute.
+ */
+ public static native boolean isAttributeActive(); /*
+ return imnodes::IsAttributeActive();
+ */
+
+ // Use the following functions to query a change of state for an existing link, or new link. Call
+ // these after EndNodeEditor().
+
+ /**
+ * Did the user start dragging a new link from a pin?
+ */
+ public static boolean isLinkStarted(final ImInt startAtAttributeId) {
+ return nIsLinkStarted(startAtAttributeId.getData());
+ }
+
+ private static native boolean nIsLinkStarted(int[] data); /*
+ return imnodes::IsLinkStarted(&data[0]);
+ */
+
+ /**
+ * Did the user drop the dragged link before attaching it to a pin?
+ * There are two different kinds of situations to consider when handling this event:
+ * 1) a link which is created at a pin and then dropped
+ * 2) an existing link which is detached from a pin and then dropped
+ * Use the including_detached_links flag to control whether this function triggers when the user
+ * detaches a link and drops it.
+ */
+ public static boolean isLinkDropped(final ImInt startedAtAttributeId, final boolean includingDetachedLinks) {
+ return nIsLinkDropped(startedAtAttributeId.getData(), includingDetachedLinks);
+ }
+
+ private static native boolean nIsLinkDropped(int[] data, boolean includingDetachedLinks); /*
+ return imnodes::IsLinkDropped(&data[0], includingDetachedLinks);
+ */
+
+ /**
+ * Did the user finish creating a new link?
+ */
+ public static boolean isLinkCreated(final ImInt startedAtAttributeId, final ImInt endedAtAttributeId) {
+ return nIsLinkCreated(startedAtAttributeId.getData(), endedAtAttributeId.getData());
+ }
+
+ private static native boolean nIsLinkCreated(int[] sourceAttribute, int[] targetAttribute); /*
+ return imnodes::IsLinkCreated(&sourceAttribute[0], &targetAttribute[0]);
+ */
+
+ public static boolean isLinkCreated(final ImInt startedAtNodeId, final ImInt startedAtAttributeId,
+ final ImInt endedAtNodeId, final ImInt endedAtAttributeId,
+ final ImBoolean createdFromSnap) {
+ return nIsLinkCreated(startedAtNodeId.getData(), startedAtAttributeId.getData(), endedAtNodeId.getData(), endedAtAttributeId.getData(), createdFromSnap.getData());
+ }
+
+ private static native boolean nIsLinkCreated(int[] startedAtNodeId, int[] startedAtAttributeId, int[] endedAtNodeId, int[] endedAtAttributeId, boolean[] createdFromSnap); /*
+ return imnodes::IsLinkCreated(&startedAtNodeId[0], &startedAtAttributeId[0], &endedAtNodeId[0], &endedAtAttributeId[0], &createdFromSnap[0]);
+ */
+
+ /**
+ * Was an existing link detached from a pin by the user? The detached link's id is assigned to the
+ * output argument link_id.
+ */
+ public static boolean isLinkDestroyed(final ImInt linkId) {
+ return nIsLinkDestroyed(linkId.getData());
+ }
+
+ private static native boolean nIsLinkDestroyed(int[] linkId); /*
+ return imnodes::IsLinkDestroyed(&linkId[0]);
+ */
+
+ /**
+ * Use The following two functions to query the number of selected nodes or links in the current
+ * editor. Use after calling EndNodeEditor().
+ */
+ public static native int numSelectedNodes(); /*
+ return imnodes::NumSelectedNodes();
+ */
+
+ public static native int numSelectedLinks(); /*
+ return imnodes::NumSelectedLinks();
+ */
+
+ /**
+ * Get the selected node/link ids. The pointer argument should point to an integer array with at
+ * least as many elements as the respective NumSelectedNodes/NumSelectedLinks function call
+ * returned.
+ */
+ public static native void getSelectedNodes(int[] nodeIds); /*
+ imnodes::GetSelectedNodes(&nodeIds[0]);
+ */
+
+ public static native void getSelectedLinks(int[] linkIds); /*
+ imnodes::GetSelectedLinks(&linkIds[0]);
+ */
+
+ /**
+ * Clears the list of selected nodes/links. Useful if you want to delete a selected node or link.
+ */
+ public static native void clearNodeSelection(); /*
+ imnodes::ClearNodeSelection();
+ */
+
+ public static native void clearLinkSelection(); /*
+ imnodes::ClearLinkSelection();
+ */
+
+ /**
+ * Enable or disable the ability to click and drag a specific node.
+ */
+ public static native void setNodeDraggable(int node, boolean isDraggable); /*
+ imnodes::SetNodeDraggable(node, isDraggable);
+ */
+
+ public static native void getNodeDimensions(int node, ImVec2 result); /*
+ ImVec2 dst = imnodes::GetNodeDimensions(node);
+ Jni::ImVec2Cpy(env, &dst, result);
+ */
+
+ public static native float getNodeDimensionsX(int node); /*
+ return imnodes::GetNodeDimensions(node).x;
+ */
+
+ public static native float getNodeDimensionsY(int node); /*
+ return imnodes::GetNodeDimensions(node).y;
+ */
+
+
+ // The node's position can be expressed in three coordinate systems:
+ // * screen space coordinates, -- the origin is the upper left corner of the window.
+ // * editor space coordinates -- the origin is the upper left corner of the node editor window
+ // * grid space coordinates, -- the origin is the upper left corner of the node editor window,
+ // translated by the current editor panning vector (see EditorContextGetPanning() and
+ // EditorContextResetPanning())
+ // Use the following functions to get and set the node's coordinates in these coordinate systems.
+
+ public static native void setNodeScreenSpacePos(int node, float x, float y); /*
+ imnodes::SetNodeScreenSpacePos(node, ImVec2(x, y));
+ */
+
+ public static native void setNodeEditorSpacePos(int node, float x, float y); /*
+ imnodes::SetNodeEditorSpacePos(node, ImVec2(x, y));
+ */
+
+ public static native void setNodeGridSpacePos(int node, float x, float y); /*
+ imnodes::SetNodeGridSpacePos(node, ImVec2(x, y));
+ */
+
+ public static native void getNodeScreenSpacePos(int node, ImVec2 result); /*
+ ImVec2 dst = imnodes::GetNodeScreenSpacePos(node);
+ Jni::ImVec2Cpy(env, &dst, result);
+ */
+
+ public static native float getNodeScreenSpacePosX(int node); /*
+ return imnodes::GetNodeScreenSpacePos(node).x;
+ */
+
+ public static native float getNodeScreenSpacePosY(int node); /*
+ return imnodes::GetNodeScreenSpacePos(node).y;
+ */
+
+ public static native void getNodeEditorSpacePos(int node, ImVec2 result); /*
+ ImVec2 dst = imnodes::GetNodeEditorSpacePos(node);
+ Jni::ImVec2Cpy(env, &dst, result);
+ */
+
+ public static native float getNodeEditorSpacePosX(int node); /*
+ return imnodes::GetNodeEditorSpacePos(node).x;
+ */
+
+ public static native float getNodeEditorSpacePosY(int node); /*
+ return imnodes::GetNodeEditorSpacePos(node).y;
+ */
+
+ public static native void getNodeGridSpacePos(int node, ImVec2 dst); /*
+ ImVec2 result = imnodes::GetNodeGridSpacePos(node);
+ Jni::ImVec2Cpy(env, &result, dst);
+ */
+
+ public static native float getNodeGridSpacePosX(int node); /*
+ return imnodes::GetNodeGridSpacePos(node).x;
+ */
+
+ public static native float getNodeGridSpacePosY(int node); /*
+ return imnodes::GetNodeGridSpacePos(node).y;
+ */
+
+ public static native void editorResetPanning(float x, float y); /*
+ imnodes::EditorContextResetPanning(ImVec2(x, y));
+ */
+
+ public static native void editorMoveToNode(int node); /*
+ imnodes::EditorContextMoveToNode(node);
+ */
+
+ // Use the following functions to write the editor context's state to a string, or directly to a
+ // file. The editor context is serialized in the INI file format.
+
+ public static native String saveCurrentEditorStateToIniString(); /*
+ return env->NewStringUTF(imnodes::SaveCurrentEditorStateToIniString(NULL));
+ */
+
+ public static String saveEditorStateToIniString(final ImNodesContext context) {
+ return nSaveEditorStateToIniString(context.ptr);
+ }
+
+ private static native String nSaveEditorStateToIniString(long context); /*
+ return env->NewStringUTF(imnodes::SaveEditorStateToIniString((imnodes::EditorContext*)context, NULL));
+ */
+
+ public static native void loadCurrentEditorStateFromIniString(String data, int dataSize); /*
+ imnodes::LoadCurrentEditorStateFromIniString(data, dataSize);
+ */
+
+ public static void loadEditorStateFromIniString(final ImNodesContext context, final String data, final int dataSize) {
+ nLoadEditorStateFromIniString(context.ptr, data, dataSize);
+ }
+
+ private static native void nLoadEditorStateFromIniString(long context, String data, int dataSize); /*
+ imnodes::LoadEditorStateFromIniString((imnodes::EditorContext*)context, data, dataSize);
+ */
+
+ public static native void saveCurrentEditorStateToIniFile(String fileName); /*
+ imnodes::SaveCurrentEditorStateToIniFile(fileName);
+ */
+
+ public static void saveEditorStateToIniFile(final ImNodesContext context, final String fileName) {
+ nSaveEditorStateToIniFile(context.ptr, fileName);
+ }
+
+ private static native void nSaveEditorStateToIniFile(long context, String fileName); /*
+ imnodes::SaveEditorStateToIniFile((imnodes::EditorContext*)context, fileName);
+ */
+
+ public static native void loadCurrentEditorStateFromIniFile(String fileName); /*
+ imnodes::LoadCurrentEditorStateFromIniFile(fileName);
+ */
+
+ public static void loadEditorStateFromIniFile(final ImNodesContext context, final String fileName) {
+ nLoadEditorStateFromIniFile(context.ptr, fileName);
+ }
+
+ private static native void nLoadEditorStateFromIniFile(long context, String fileName); /*
+ imnodes::LoadEditorStateFromIniFile((imnodes::EditorContext*)context, fileName);
+ */
+}
diff --git a/imgui-binding/src/main/java/imgui/imnodes/ImNodesAttributeFlags.java b/imgui-binding/src/main/java/imgui/imnodes/ImNodesAttributeFlags.java
new file mode 100644
index 0000000..16a464a
--- /dev/null
+++ b/imgui-binding/src/main/java/imgui/imnodes/ImNodesAttributeFlags.java
@@ -0,0 +1,28 @@
+package imgui.imnodes;
+
+/**
+ * This enum controls the way the attribute pins behave.
+ */
+public final class ImNodesAttributeFlags {
+
+ private ImNodesAttributeFlags() {
+ }
+
+ public static final int None = 0;
+
+ /**
+ * Allow detaching a link by left-clicking and dragging the link at a pin it is connected to.
+ * NOTE: the user has to actually delete the link for this to work. A deleted link can be
+ * detected by calling IsLinkDestroyed() after EndNodeEditor().
+ */
+ public static final int EnableLinkDetachWithDragClick = 1;
+
+ /**
+ * Visual snapping of an in progress link will trigger IsLink Created/Destroyed events. Allows
+ * for previewing the creation of a link while dragging it across attributes. See here for demo:
+ * https://github.com/Nelarius/imnodes/issues/41#issuecomment-647132113 NOTE: the user has to
+ * actually delete the link for this to work. A deleted link can be detected by calling
+ * IsLinkDestroyed() after EndNodeEditor().
+ */
+ public static final int EnableLinkCreationOnSnap = 1 << 1;
+}
diff --git a/imgui-binding/src/main/java/imgui/imnodes/ImNodesColorStyle.java b/imgui-binding/src/main/java/imgui/imnodes/ImNodesColorStyle.java
new file mode 100644
index 0000000..dc05874
--- /dev/null
+++ b/imgui-binding/src/main/java/imgui/imnodes/ImNodesColorStyle.java
@@ -0,0 +1,23 @@
+package imgui.imnodes;
+
+public final class ImNodesColorStyle {
+ private ImNodesColorStyle() {
+ }
+
+ public static final int NodeBackground = 0;
+ public static final int NodeBackgroundHovered = 1;
+ public static final int NodeBackgroundSelected = 2;
+ public static final int NodeOutline = 3;
+ public static final int TitleBar = 4;
+ public static final int TitleBarHovered = 5;
+ public static final int TitleBarSelected = 6;
+ public static final int Link = 7;
+ public static final int LinkHovered = 8;
+ public static final int LinkSelected = 9;
+ public static final int Pin = 10;
+ public static final int PinHovered = 11;
+ public static final int BoxSelector = 12;
+ public static final int BoxSelectorOutline = 13;
+ public static final int GridBackground = 14;
+ public static final int GridLine = 15;
+}
diff --git a/imgui-binding/src/main/java/imgui/imnodes/ImNodesContext.java b/imgui-binding/src/main/java/imgui/imnodes/ImNodesContext.java
new file mode 100644
index 0000000..cc7dece
--- /dev/null
+++ b/imgui-binding/src/main/java/imgui/imnodes/ImNodesContext.java
@@ -0,0 +1,41 @@
+package imgui.imnodes;
+
+import imgui.binding.ImGuiStructDestroyable;
+
+public final class ImNodesContext extends ImGuiStructDestroyable {
+
+ public ImNodesContext() {
+ }
+
+ public ImNodesContext(final long ptr) {
+ super(ptr);
+ }
+
+ /*JNI
+ #include
+ #include
+ #include
+ #include "jni_common.h"
+ #include "jni_binding_struct.h"
+
+ #define IMNODES_CONTEXT ((imnodes::EditorContext*)STRUCT_PTR)
+ */
+
+ @Override
+ protected long create() {
+ return nCreate();
+ }
+
+ @Override
+ public void destroy() {
+ nDestroy();
+ }
+
+ private native long nCreate(); /*
+ return (intptr_t)imnodes::EditorContextCreate();
+ */
+
+ private native void nDestroy(); /*
+ imnodes::EditorContextFree(IMNODES_CONTEXT);
+ */
+}
diff --git a/imgui-binding/src/main/java/imgui/imnodes/ImNodesPinShape.java b/imgui-binding/src/main/java/imgui/imnodes/ImNodesPinShape.java
new file mode 100644
index 0000000..38def36
--- /dev/null
+++ b/imgui-binding/src/main/java/imgui/imnodes/ImNodesPinShape.java
@@ -0,0 +1,16 @@
+package imgui.imnodes;
+
+/**
+ * This enum controls the way attribute pins look.
+ */
+public final class ImNodesPinShape {
+ private ImNodesPinShape() {
+ }
+
+ public static final int Circle = 0;
+ public static final int CircleFilled = 1;
+ public static final int Triangle = 2;
+ public static final int TriangleFilled = 3;
+ public static final int Quad = 4;
+ public static final int QuadFilled = 5;
+}
diff --git a/imgui-binding/src/main/java/imgui/imnodes/ImNodesStyle.java b/imgui-binding/src/main/java/imgui/imnodes/ImNodesStyle.java
new file mode 100644
index 0000000..b5e94ef
--- /dev/null
+++ b/imgui-binding/src/main/java/imgui/imnodes/ImNodesStyle.java
@@ -0,0 +1,175 @@
+package imgui.imnodes;
+
+import imgui.binding.ImGuiStruct;
+
+public final class ImNodesStyle extends ImGuiStruct {
+ public ImNodesStyle(final long ptr) {
+ super(ptr);
+ }
+
+ /*JNI
+ #include
+ #include
+ #include
+ #include "jni_common.h"
+ #include "jni_binding_struct.h"
+
+ #define IMNODES_STYLE ((imnodes::Style*)STRUCT_PTR)
+ */
+
+ public native float getGridSpacing(); /*
+ return IMNODES_STYLE->grid_spacing;
+ */
+
+ public native void setGridSpacing(float gridSpacing); /*
+ IMNODES_STYLE->grid_spacing = gridSpacing;
+ */
+
+ public native float getNodeCornerRounding(); /*
+ return IMNODES_STYLE->node_corner_rounding;
+ */
+
+ public native void setNodeCornerRounding(float nodeCornerRounding); /*
+ IMNODES_STYLE->node_corner_rounding = nodeCornerRounding;
+ */
+
+ public native float getNodePaddingHorizontal(); /*
+ return IMNODES_STYLE->node_padding_horizontal;
+ */
+
+ public native void setNodePaddingHorizontal(float nodePaddingHorizontal); /*
+ IMNODES_STYLE->node_padding_horizontal = nodePaddingHorizontal;
+ */
+
+ public native float getNodePaddingVertical(); /*
+ return IMNODES_STYLE->node_padding_vertical;
+ */
+
+ public native void setNodePaddingVertical(float nodePaddingVertical); /*
+ IMNODES_STYLE->node_padding_vertical = nodePaddingVertical;
+ */
+
+ public native float getNodeBorderThickness(); /*
+ return IMNODES_STYLE->node_border_thickness;
+ */
+
+ public native void setNodeBorderThickness(float nodeBorderThickness); /*
+ IMNODES_STYLE->node_border_thickness = nodeBorderThickness;
+ */
+
+ public native float getLinkThickness(); /*
+ return IMNODES_STYLE->link_thickness;
+ */
+
+ public native void setLinkThickness(float linkThickness); /*
+ IMNODES_STYLE->link_thickness = linkThickness;
+ */
+
+ public native float getLinkLineSegmentsPerLength(); /*
+ return IMNODES_STYLE->link_line_segments_per_length;
+ */
+
+ public native void setLinkLineSegmentsPerLength(float linkLineSegmentsPerLength); /*
+ IMNODES_STYLE->link_line_segments_per_length = linkLineSegmentsPerLength;
+ */
+
+ public native float getLinkHoverDistance(); /*
+ return IMNODES_STYLE->link_hover_distance;
+ */
+
+ public native void setLinkHoverDistance(float linkHoverDistance); /*
+ IMNODES_STYLE->link_hover_distance = linkHoverDistance;
+ */
+
+ /**
+ * The circle radius used when the pin shape is either PinShape_Circle or PinShape_CircleFilled.
+ */
+ public native float getPinCircleRadius(); /*
+ return IMNODES_STYLE->pin_circle_radius;
+ */
+
+ /**
+ * The circle radius used when the pin shape is either PinShape_Circle or PinShape_CircleFilled.
+ */
+ public native void setPinCircleRadius(float pinCircleRadius); /*
+ IMNODES_STYLE->pin_circle_radius = pinCircleRadius;
+ */
+
+ /**
+ * The quad side length used when the shape is either PinShape_Quad or PinShape_QuadFilled.
+ */
+ public native float getPinQuadSideLength(); /*
+ return IMNODES_STYLE->pin_quad_side_length;
+ */
+
+ /**
+ * The quad side length used when the shape is either PinShape_Quad or PinShape_QuadFilled.
+ */
+ public native void setPinQuadSideLength(float pinQuadSideLength); /*
+ IMNODES_STYLE->pin_quad_side_length = pinQuadSideLength;
+ */
+
+ /**
+ * The equilateral triangle side length used when the pin shape is either PinShape_Triangle or PinShape_TriangleFilled.
+ */
+ public native float getPinTriangleSideLength(); /*
+ return IMNODES_STYLE->pin_triangle_side_length;
+ */
+
+ /**
+ * The equilateral triangle side length used when the pin shape is either PinShape_Triangle or PinShape_TriangleFilled.
+ */
+ public native void setPinTriangleSideLength(float pinTriangleSideLength); /*
+ IMNODES_STYLE->pin_triangle_side_length = pinTriangleSideLength;
+ */
+
+ /**
+ * The thickness of the line used when the pin shape is not filled.
+ */
+ public native float getPinLineThickness(); /*
+ return IMNODES_STYLE->pin_line_thickness;
+ */
+
+ /**
+ * The thickness of the line used when the pin shape is not filled.
+ */
+ public native void setPinLineThickness(float pinLineThickness); /*
+ IMNODES_STYLE->pin_line_thickness = pinLineThickness;
+ */
+
+ /**
+ * The radius from the pin's center position inside of which it is detected as being hovered over.
+ */
+ public native float getPinHoverRadius(); /*
+ return IMNODES_STYLE->pin_hover_radius;
+ */
+
+ /**
+ * The radius from the pin's center position inside of which it is detected as being hovered over.
+ */
+ public native void setPinHoverRadius(float pinHoverRadius); /*
+ IMNODES_STYLE->pin_hover_radius = pinHoverRadius;
+ */
+
+ /**
+ * Offsets the pins' positions from the edge of the node to the outside of the node.
+ */
+ public native float getPinOffset(); /*
+ return IMNODES_STYLE->pin_offset;
+ */
+
+ /**
+ * Offsets the pins' positions from the edge of the node to the outside of the node.
+ */
+ public native void setPinOffset(float pinOffset); /*
+ IMNODES_STYLE->pin_offset = pinOffset;
+ */
+
+ public native int getFlags(); /*
+ return IMNODES_STYLE->flags;
+ */
+
+ public native void setFlags(int imNodesStyleFlags); /*
+ IMNODES_STYLE->flags = (imnodes::StyleFlags)imNodesStyleFlags;
+ */
+}
diff --git a/imgui-binding/src/main/java/imgui/imnodes/ImNodesStyleFlags.java b/imgui-binding/src/main/java/imgui/imnodes/ImNodesStyleFlags.java
new file mode 100644
index 0000000..e3a9809
--- /dev/null
+++ b/imgui-binding/src/main/java/imgui/imnodes/ImNodesStyleFlags.java
@@ -0,0 +1,10 @@
+package imgui.imnodes;
+
+public final class ImNodesStyleFlags {
+ private ImNodesStyleFlags() {
+ }
+
+ public static final int None = 0;
+ public static final int NodeOutline = 1;
+ public static final int GridLines = 1 << 2;
+}
diff --git a/imgui-binding/src/main/java/imgui/imnodes/ImNodesStyleVar.java b/imgui-binding/src/main/java/imgui/imnodes/ImNodesStyleVar.java
new file mode 100644
index 0000000..19bfbac
--- /dev/null
+++ b/imgui-binding/src/main/java/imgui/imnodes/ImNodesStyleVar.java
@@ -0,0 +1,21 @@
+package imgui.imnodes;
+
+public final class ImNodesStyleVar {
+ private ImNodesStyleVar() {
+ }
+
+ public static final int GridSpacing = 0;
+ public static final int NodeCornerRounding = 1;
+ public static final int NodePaddingHorizontal = 2;
+ public static final int NodePaddingVertical = 3;
+ public static final int NodeBorderThickness = 4;
+ public static final int LinkThickness = 5;
+ public static final int LinkLineSegmentsPerLength = 6;
+ public static final int LinkHoverDistance = 7;
+ public static final int PinCircleRadius = 8;
+ public static final int PinQuadSideLength = 9;
+ public static final int PinTriangleSideLength = 10;
+ public static final int PinLineThickness = 11;
+ public static final int PinHoverRadius = 12;
+ public static final int PinOffset = 13;
+}
diff --git a/imgui-binding/src/main/java/imgui/nodeditor/ImNodeEditor.java b/imgui-binding/src/main/java/imgui/nodeditor/ImNodeEditor.java
new file mode 100644
index 0000000..4c802a9
--- /dev/null
+++ b/imgui-binding/src/main/java/imgui/nodeditor/ImNodeEditor.java
@@ -0,0 +1,554 @@
+package imgui.nodeditor;
+
+import imgui.ImDrawList;
+import imgui.ImVec2;
+import imgui.type.ImLong;
+
+/**
+ * Bindings for Imgui Node Editor (https://github.com/thedmd/imgui-node-editor)
+ * Original library author - Michał Cichoń (https://github.com/thedmd)
+ *
+ * An implementation of node editor with ImGui-like API.
+ * Project purpose is to serve as a basis for more complex solutions like blueprint editors.
+ *
+ * Refer to the library's Github page for examples and support
+ *
+ * Before you can start drawing editor you have to create ImNodeEditorContext
+ * (either by invoking constructor directly or using ImNodeEditor.createEditor()) and switch
+ * current editor via ImNodeEditor.setCurrentEditor(NodeEditorContext)
+ *
+ * Binding notice: instead of special types for ids of nodes, links and pins which used in native library
+ * we use longs to reduce boilerplate and garbage production
+ */
+public final class ImNodeEditor {
+ private static final ImDrawList HINT_FOREGROUND_DRAW_LIST = new ImDrawList(0);
+ private static final ImDrawList HINT_BACKGROUND_DRAW_LIST = new ImDrawList(0);
+ private static final ImDrawList NODE_BACKGROUND_DRAW_LIST = new ImDrawList(0);
+
+ private static ImNodeEditorStyle style;
+
+ private ImNodeEditor() {
+ }
+
+ /*JNI
+ #include
+ #include
+ #include
+ #include "jni_common.h"
+ #include "jni_binding_struct.h"
+
+ namespace ed = ax::NodeEditor;
+ */
+
+ /**
+ * This method exists for api consistency and you can just call NodeEditorContext manually
+ */
+ public static ImNodeEditorContext createEditor() {
+ return new ImNodeEditorContext();
+ }
+
+ public static ImNodeEditorContext createEditor(final ImNodeEditorConfig config) {
+ return new ImNodeEditorContext(config);
+ }
+
+ /**
+ * This method exists for api consistency and you can just call NodeEditorContext.destroy() manually
+ */
+ public static void destroyEditor(final ImNodeEditorContext editorContext) {
+ editorContext.destroy();
+ }
+
+ public static void setCurrentEditor(final ImNodeEditorContext editorContext) {
+ nSetCurrentEditor(editorContext.ptr);
+ }
+
+ private static native void nSetCurrentEditor(long editor); /*
+ ed::SetCurrentEditor((ed::EditorContext*)editor);
+ */
+
+ public static native void begin(String title); /*
+ ed::Begin(title);
+ */
+
+ public static native void beginNode(long id); /*
+ ed::BeginNode(id);
+ */
+
+ public static native void group(float w, float h); /*
+ ed::Group(ImVec2(w, h));
+ */
+
+ public static native boolean beginGroupHint(long id); /*
+ return ed::BeginGroupHint(id);
+ */
+
+
+ public static native void beginPin(long pin, int imNodeEditorPinKind); /*
+ ed::BeginPin(pin, (ed::PinKind)imNodeEditorPinKind);
+ */
+
+ public static native void endGroupHint(); /*
+ ed::EndGroupHint();
+ */
+
+ public static native void endPin(); /*
+ ed::EndPin();
+ */
+
+ public static native void endNode(); /*
+ ed::EndNode();
+ */
+
+ public static native void end(); /*
+ ed::End();
+ */
+
+ public static native float getScreenSizeX(); /*
+ return ed::GetScreenSize().x;
+ */
+
+ public static native float getScreenSizeY(); /*
+ return ed::GetScreenSize().y;
+ */
+
+ public static native float toCanvasX(float screenSpacePosX); /*
+ return ed::ScreenToCanvas(ImVec2(screenSpacePosX, 0.0f)).x;
+ */
+
+ public static native float toCanvasY(float screenSpacePosY); /*
+ return ed::ScreenToCanvas(ImVec2(0.0f, screenSpacePosY)).y;
+ */
+
+ public static native float toScreenX(float canvasSpacePosX); /*
+ return ed::CanvasToScreen(ImVec2(canvasSpacePosX, 0.0f)).x;
+ */
+
+ public static native float toScreenY(float canvasSpacePosY); /*
+ return ed::CanvasToScreen(ImVec2(0.0f, canvasSpacePosY)).y;
+ */
+
+ public static ImNodeEditorStyle getStyle() {
+ if (style == null) {
+ style = new ImNodeEditorStyle(nGetStyle());
+ }
+ return style;
+ }
+
+ private static native long nGetStyle(); /*
+ return (intptr_t)&ed::GetStyle();
+ */
+
+ public static native String getStyleColorName(int imNodeEditorStyleColor); /*
+ return env->NewStringUTF(ed::GetStyleColorName((ed::StyleColor)imNodeEditorStyleColor));
+ */
+
+ public static native void pushStyleColor(int imNodeEditorStyleColor, float r, float g, float b, float a); /*
+ ed::PushStyleColor((ed::StyleColor)imNodeEditorStyleColor, ImVec4(r, g, b, a));
+ */
+
+ public static native void popStyleColor(int count); /*
+ ed::PopStyleColor(count);
+ */
+
+ public static native void pushStyleVar(int imNodeEditorStyleVar, float v); /*
+ ed::PushStyleVar((ed::StyleVar)imNodeEditorStyleVar, v);
+ */
+
+ public static native void pushStyleVar(int imNodeEditorStyleVar, float x, float y); /*
+ ed::PushStyleVar((ed::StyleVar)imNodeEditorStyleVar, ImVec2(x, y));
+ */
+
+ public static native void pushStyleVar(int imNodeEditorStyleVar, float r, float g, float b, float a); /*
+ ed::PushStyleVar((ed::StyleVar)imNodeEditorStyleVar, ImVec4(r, g, b, a));
+ */
+
+ public static native void popStyleVar(int count); /*
+ ed::PopStyleVar(count);
+ */
+
+ public static native float getGroupMinX(); /*
+ return ed::GetGroupMin().x;
+ */
+
+ public static native float getGroupMinY(); /*
+ return ed::GetGroupMin().y;
+ */
+
+ public static native float getGroupMaxX(); /*
+ return ed::GetGroupMax().x;
+ */
+
+ public static native float getGroupMaxY(); /*
+ return ed::GetGroupMax().y;
+ */
+
+ /**
+ * Binding notice: both getHintForegroundDrawList(), getHintBackgroundDrawList() and getNodeBackgroundDrawList(long)
+ * return singleton objects which shouldn't be used outside of the scope of current hint/node
+ */
+
+ public static ImDrawList getHintForegroundDrawList() {
+ HINT_FOREGROUND_DRAW_LIST.ptr = nGetHintForegroundDrawList();
+ return HINT_FOREGROUND_DRAW_LIST;
+ }
+
+ public static ImDrawList getHintBackgroundDrawList() {
+ HINT_BACKGROUND_DRAW_LIST.ptr = nGetHintBackgroundDrawList();
+ return HINT_BACKGROUND_DRAW_LIST;
+ }
+
+ public static ImDrawList getNodeBackgroundDrawList(final long nodeId) {
+ final long ptr = nGetNodeBackgroundDrawList(nodeId);
+ if (ptr == 0) {
+ return null;
+ } else {
+ NODE_BACKGROUND_DRAW_LIST.ptr = ptr;
+ return NODE_BACKGROUND_DRAW_LIST;
+ }
+ }
+
+ private static native long nGetHintForegroundDrawList(); /*
+ return (intptr_t)(uintptr_t)ed::GetHintForegroundDrawList();
+ */
+
+ private static native long nGetHintBackgroundDrawList(); /*
+ return (intptr_t)(uintptr_t)ed::GetHintBackgroundDrawList();
+ */
+
+ private static native long nGetNodeBackgroundDrawList(long nodeId); /*
+ return (intptr_t)(uintptr_t)ed::GetNodeBackgroundDrawList(nodeId);
+ */
+
+ public static native long getDoubleClickedNode(); /*
+ return (intptr_t)(uintptr_t)ed::GetDoubleClickedNode();
+ */
+
+ public static native long getDoubleClickedPin(); /*
+ return (intptr_t)(uintptr_t)ed::GetDoubleClickedPin();
+ */
+
+ public static native long getDoubleClickedLink(); /*
+ return (intptr_t)(uintptr_t)ed::GetDoubleClickedLink();
+ */
+
+ public static native boolean isBackgroundClicked(); /*
+ return ed::IsBackgroundClicked();
+ */
+
+ public static native boolean isBackgroundDoubleClicked(); /*
+ return ed::IsBackgroundDoubleClicked();
+ */
+
+ public static native boolean pinHadAnyLinks(long pinId); /*
+ return ed::PinHadAnyLinks(pinId);
+ */
+
+ public static native float getCurrentZoom(); /*
+ return ed::GetCurrentZoom();
+ */
+
+ public static native void pinRect(float x, float y, float w, float h); /*
+ ed::PinRect(ImVec2(x, y), ImVec2(w, h));
+ */
+
+ public static native void pinPivotRect(float x, float y, float w, float h); /*
+ ed::PinPivotRect(ImVec2(x, y), ImVec2(w, h));
+ */
+
+ public static native void pinPivotSize(float w, float h); /*
+ ed::PinPivotSize(ImVec2(w, h));
+ */
+
+ public static native void pinPivotScale(float w, float h); /*
+ ed::PinPivotScale(ImVec2(w, h));
+ */
+
+ public static native void pinPivotAlignment(float x, float y); /*
+ ed::PinPivotAlignment(ImVec2(x, y));
+ */
+
+ public static boolean showNodeContextMenu(final ImLong nodeId) {
+ return nShowNodeContextMenu(nodeId.getData());
+ }
+
+ private static native boolean nShowNodeContextMenu(long[] nodeId); /*
+ return ed::ShowNodeContextMenu((ed::NodeId*)&nodeId[0]);
+ */
+
+ public static boolean showPinContextMenu(final ImLong pinId) {
+ return nShowPinContextMenu(pinId.getData());
+ }
+
+ private static native boolean nShowPinContextMenu(long[] pinId); /*
+ return ed::ShowPinContextMenu((ed::PinId*)&pinId[0]);
+ */
+
+ public static boolean showLinkContextMenu(final ImLong linkId) {
+ return nShowLinkContextMenu(linkId.getData());
+ }
+
+ private static native boolean nShowLinkContextMenu(long[] linkId); /*
+ return ed::ShowLinkContextMenu((ed::LinkId*)&linkId[0]);
+ */
+
+ /**
+ * Binding notice: getNodeWithContextMenu(), getPinWithContextMenu() and getLinkWithContextMenu()
+ * return id of the object for which context menu should be shown. If there is no such object -1 will be returned.
+ *
+ * These methods implemented as convenient alternative to showNodeContextMenu(ImLong), showPinContextMenu(ImLong) and
+ * showLinkContextMenu(ImLong)
+ */
+
+ public static native long getNodeWithContextMenu(); /*
+ ed::NodeId id;
+ return ed::ShowNodeContextMenu(&id) ? (intptr_t)(uintptr_t)id : -1;
+ */
+
+ public static native long getPinWithContextMenu(); /*
+ ed::PinId id;
+ return ed::ShowPinContextMenu(&id) ? (intptr_t)(uintptr_t)id : -1;
+ */
+
+ public static native long getLinkWithContextMenu(); /*
+ ed::LinkId id;
+ return ed::ShowLinkContextMenu(&id) ? (intptr_t)(uintptr_t)id : -1;
+ */
+
+ public static native boolean showBackgroundContextMenu(); /*
+ return ed::ShowBackgroundContextMenu();
+ */
+
+ public static native void restoreNodeState(long node); /*
+ ed::RestoreNodeState(node);
+ */
+
+ public static native void suspend(); /*
+ ed::Suspend();
+ */
+
+ public static native void resume(); /*
+ ed::Resume();
+ */
+
+ public static native boolean isSuspended(); /*
+ return ed::IsSuspended();
+ */
+
+ public static native boolean isActive(); /*
+ return ed::IsActive();
+ */
+
+ public static native void setNodePosition(long node, float x, float y); /*
+ ed::SetNodePosition(node, ImVec2(x, y));
+ */
+
+ public static void link(final long id, final long startPinId, final long endPinId) {
+ link(id, startPinId, endPinId, 1, 1, 1, 1, 1);
+ }
+
+ public static native void link(long id, long startPinId, long endPinId, float r, float g, float b, float a,
+ float thickness); /*
+ ed::Link(id, startPinId, endPinId, ImVec4(r, g, b, a), thickness);
+ */
+
+ public static native void flow(long linkId); /*
+ ed::Flow(linkId);
+ */
+
+ public static boolean beginCreate() {
+ return beginCreate(1, 1, 1, 1, 1);
+ }
+
+ public static native boolean beginCreate(float r, float g, float b, float a, float thickness); /*
+ return ed::BeginCreate(ImVec4(r, g, b, a), thickness);
+ */
+
+ public static boolean queryNewLink(final ImLong startId, final ImLong endId) {
+ return nQueryNewLink(startId.getData(), endId.getData(), 1, 1, 1, 1, 1);
+ }
+
+ public static boolean queryNewLink(final ImLong startId, final ImLong endId, final float r, final float g, final float b, final float a, final float thickness) {
+ return nQueryNewLink(startId.getData(), endId.getData(), r, g, b, a, thickness);
+ }
+
+ private static native boolean nQueryNewLink(long[] startId, long[] endId, float r, float g, float b, float a, float thickness); /*
+ return ed::QueryNewLink((ed::PinId*)&startId[0], (ed::PinId*)&endId[0], ImVec4(r, g, b, a), thickness);
+ */
+
+ public static boolean acceptNewItem() {
+ return acceptNewItem(1, 1, 1, 1, 1);
+ }
+
+ public static native boolean acceptNewItem(float r, float g, float b, float a, float thickness); /*
+ return ed::AcceptNewItem(ImVec4(r, g, b, a), thickness);
+ */
+
+ public static void rejectNewItem() {
+ rejectNewItem(1, 1, 1, 1, 1);
+ }
+
+ public static native void rejectNewItem(float r, float g, float b, float a, float thickness); /*
+ ed::RejectNewItem(ImVec4(r, g, b, a), thickness);
+ */
+
+ public static native void endCreate(); /*
+ ed::EndCreate();
+ */
+
+ public static native boolean beginDelete(); /*
+ return ed::BeginDelete();
+ */
+
+ public static boolean queryDeletedLink(final ImLong linkId, final ImLong startId, final ImLong endId) {
+ return nQueryDeletedLink(linkId.getData(), startId.getData(), endId.getData());
+ }
+
+ private static native boolean nQueryDeletedLink(long[] linkId, long[] startId, long[] endId); /*
+ return ed::QueryDeletedLink((ed::LinkId*)&linkId[0], (ed::PinId*)&startId[0], (ed::PinId*)&endId[0]);
+ */
+
+ public static boolean queryDeletedNode(final ImLong nodeId) {
+ return nQueryDeletedNode(nodeId.getData());
+ }
+
+ private static native boolean nQueryDeletedNode(long[] nodeId); /*
+ return ed::QueryDeletedNode((ed::NodeId*)&nodeId[0]);
+ */
+
+ public static native boolean acceptDeletedItem(); /*
+ return ed::AcceptDeletedItem();
+ */
+
+ public static native void rejectDeletedItem(); /*
+ ed::RejectDeletedItem();
+ */
+
+ public static native void endDelete(); /*
+ ed::EndDelete();
+ */
+
+ public static native void navigateToContent(float duration); /*
+ ed::NavigateToContent(duration);
+ */
+
+ public static native void navigateToSelection(boolean zoomIn, float duration); /*
+ ed::NavigateToSelection(zoomIn, duration);
+ */
+
+ public static native void getNodePosition(long node, ImVec2 dst); /*
+ ImVec2 result = ed::GetNodePosition(node);
+ Jni::ImVec2Cpy(env, &result, dst);
+ */
+
+ public static native float getNodePositionX(long node); /*
+ return ed::GetNodePosition(node).x;
+ */
+
+ public static native float getNodePositionY(long node); /*
+ return ed::GetNodePosition(node).y;
+ */
+
+ public static native float getNodeSizeX(long node); /*
+ return ed::GetNodeSize(node).x;
+ */
+
+ public static native float getNodeSizeY(long node); /*
+ return ed::GetNodeSize(node).y;
+ */
+
+ public static native void centerNodeOnScreen(long node); /*
+ ed::CenterNodeOnScreen(node);
+ */
+
+ public static native boolean hasSelectionChanged(); /*
+ return ed::HasSelectionChanged();
+ */
+
+ public static native int getSelectedObjectCount(); /*
+ return ed::GetSelectedObjectCount();
+ */
+
+ public static native int getSelectedNodes(long[] nodes, int size); /*
+ return ed::GetSelectedNodes((ed::NodeId*)&nodes[0], size);
+ */
+
+ public static native int getSelectedLinks(long[] links, int size); /*
+ return ed::GetSelectedLinks((ed::LinkId*)&links[0], size);
+ */
+
+ public static native void clearSelection(); /*
+ return ed::ClearSelection();
+ */
+
+ public static native void selectNode(long id, boolean append); /*
+ ed::SelectNode(id, append);
+ */
+
+ public static native void selectLink(long id, boolean append); /*
+ ed::SelectLink(id, append);
+ */
+
+ public static native void deselectNode(long id); /*
+ ed::DeselectNode(id);
+ */
+
+ public static native void deselectLink(long id); /*
+ ed::DeselectLink(id);
+ */
+
+ public static native boolean deleteNode(long nodeId); /*
+ return ed::DeleteNode(nodeId);
+ */
+
+ public static native boolean deleteLink(long linkId); /*
+ return ed::DeleteLink(linkId);
+ */
+
+ public static native void enableShortcuts(boolean enable); /*
+ ed::EnableShortcuts(enable);
+ */
+
+ public static native boolean areShortcutsEnabled(); /*
+ return ed::AreShortcutsEnabled();
+ */
+
+ public static native boolean beginShortcut(); /*
+ return ed::BeginShortcut();
+ */
+
+ public static native boolean acceptCut(); /*
+ return ed::AcceptCut();
+ */
+
+ public static native boolean acceptCopy(); /*
+ return ed::AcceptCopy();
+ */
+
+ public static native boolean acceptPaste(); /*
+ return ed::AcceptPaste();
+ */
+
+ public static native boolean acceptDuplicate(); /*
+ return ed::AcceptDuplicate();
+ */
+
+ public static native boolean acceptCreateNode(); /*
+ return ed::AcceptCreateNode();
+ */
+
+ public static native int getActionContextSize(); /*
+ return ed::GetActionContextSize();
+ */
+
+ public static native int getActionContextNodes(long[] nodes, int size); /*
+ return ed::GetActionContextNodes((ed::NodeId*)&nodes[0], size);
+ */
+
+ public static native int getActionContextLinks(long[] links, int size); /*
+ return ed::GetActionContextLinks((ed::LinkId*)&links[0], size);
+ */
+
+ public static native void endShortcut(); /*
+ ed::EndShortcut();
+ */
+}
diff --git a/imgui-binding/src/main/java/imgui/nodeditor/ImNodeEditorConfig.java b/imgui-binding/src/main/java/imgui/nodeditor/ImNodeEditorConfig.java
new file mode 100644
index 0000000..5302f2a
--- /dev/null
+++ b/imgui-binding/src/main/java/imgui/nodeditor/ImNodeEditorConfig.java
@@ -0,0 +1,41 @@
+package imgui.nodeditor;
+
+import imgui.binding.ImGuiStructDestroyable;
+
+public final class ImNodeEditorConfig extends ImGuiStructDestroyable {
+ public ImNodeEditorConfig() {
+ }
+
+ public ImNodeEditorConfig(final long ptr) {
+ super(ptr);
+ }
+
+ /*JNI
+ #include
+ #include
+ #include
+ #include
+ #include "jni_binding_struct.h"
+
+ namespace ed = ax::NodeEditor;
+
+ #define IM_NODE_EDITOR_CONFIG ((ed::Config*)STRUCT_PTR)
+ */
+
+ @Override
+ protected long create() {
+ return nCreate();
+ }
+
+ private native long nCreate(); /*
+ return (intptr_t)(new ed::Config());
+ */
+
+ public native String getSettingsFile(); /*
+ return env->NewStringUTF(IM_NODE_EDITOR_CONFIG->SettingsFile);
+ */
+
+ public native void setSettingsFile(String settingsFile); /*MANUAL
+ IM_NODE_EDITOR_CONFIG->SettingsFile = obj_settingsFile == NULL ? NULL : (char*)env->GetStringUTFChars(obj_settingsFile, JNI_FALSE);
+ */
+}
diff --git a/imgui-binding/src/main/java/imgui/nodeditor/ImNodeEditorContext.java b/imgui-binding/src/main/java/imgui/nodeditor/ImNodeEditorContext.java
new file mode 100644
index 0000000..c4ded88
--- /dev/null
+++ b/imgui-binding/src/main/java/imgui/nodeditor/ImNodeEditorContext.java
@@ -0,0 +1,48 @@
+package imgui.nodeditor;
+
+import imgui.binding.ImGuiStructDestroyable;
+
+public final class ImNodeEditorContext extends ImGuiStructDestroyable {
+ public ImNodeEditorContext() {
+ }
+
+ public ImNodeEditorContext(final ImNodeEditorConfig config) {
+ this(nCreate(config.ptr));
+ }
+
+ public ImNodeEditorContext(final long ptr) {
+ super(ptr);
+ }
+
+ /*JNI
+ #include
+ #include
+ #include "jni_binding_struct.h"
+
+ namespace ed = ax::NodeEditor;
+
+ #define IM_NODE_EDITOR_CONTEXT ((ed::EditorContext*)STRUCT_PTR)
+ */
+
+ @Override
+ protected long create() {
+ return nCreate();
+ }
+
+ @Override
+ public void destroy() {
+ nDestroyEditorContext();
+ }
+
+ private native long nCreate(); /*
+ return (intptr_t)ed::CreateEditor();
+ */
+
+ private static native long nCreate(long cfgPtr); /*
+ return (intptr_t)ed::CreateEditor((ed::Config*)cfgPtr);
+ */
+
+ private native void nDestroyEditorContext(); /*
+ ed::DestroyEditor(IM_NODE_EDITOR_CONTEXT);
+ */
+}
diff --git a/imgui-binding/src/main/java/imgui/nodeditor/ImNodeEditorPinKind.java b/imgui-binding/src/main/java/imgui/nodeditor/ImNodeEditorPinKind.java
new file mode 100644
index 0000000..d0df2fc
--- /dev/null
+++ b/imgui-binding/src/main/java/imgui/nodeditor/ImNodeEditorPinKind.java
@@ -0,0 +1,9 @@
+package imgui.nodeditor;
+
+public final class ImNodeEditorPinKind {
+ private ImNodeEditorPinKind() {
+ }
+
+ public static final int Input = 0;
+ public static final int Output = 1;
+}
diff --git a/imgui-binding/src/main/java/imgui/nodeditor/ImNodeEditorStyle.java b/imgui-binding/src/main/java/imgui/nodeditor/ImNodeEditorStyle.java
new file mode 100644
index 0000000..fb2cedb
--- /dev/null
+++ b/imgui-binding/src/main/java/imgui/nodeditor/ImNodeEditorStyle.java
@@ -0,0 +1,291 @@
+package imgui.nodeditor;
+
+import imgui.ImVec2;
+import imgui.ImVec4;
+import imgui.binding.ImGuiStruct;
+
+public final class ImNodeEditorStyle extends ImGuiStruct {
+ public ImNodeEditorStyle(final long ptr) {
+ super(ptr);
+ }
+
+ /*JNI
+ #include
+ #include
+ #include
+ #include
+ #include "jni_common.h"
+ #include "jni_binding_struct.h"
+
+ namespace ed = ax::NodeEditor;
+
+ #define IM_NODE_EDITOR_STYLE ((ed::Style*)STRUCT_PTR)
+ */
+
+ public native void getNodePadding(ImVec4 dstImVec4); /*
+ Jni::ImVec4Cpy(env, IM_NODE_EDITOR_STYLE->NodePadding, dstImVec4);
+ */
+
+ public native void setNodePadding(float x, float y, float z, float w); /*
+ IM_NODE_EDITOR_STYLE->NodePadding.x = x;
+ IM_NODE_EDITOR_STYLE->NodePadding.y = y;
+ IM_NODE_EDITOR_STYLE->NodePadding.z = z;
+ IM_NODE_EDITOR_STYLE->NodePadding.w = w;
+ */
+
+ public native float getNodeRounding(); /*
+ return IM_NODE_EDITOR_STYLE->NodeRounding;
+ */
+
+ public native void setNodeRounding(float nodeRounding); /*
+ IM_NODE_EDITOR_STYLE->NodeRounding = nodeRounding;
+ */
+
+ public native float getNodeBorderWidth(); /*
+ return IM_NODE_EDITOR_STYLE->NodeBorderWidth;
+ */
+
+ public native void setNodeBorderWidth(float nodeBorderWidth); /*
+ IM_NODE_EDITOR_STYLE->NodeBorderWidth = nodeBorderWidth;
+ */
+
+ public native float getHoveredNodeBorderWidth(); /*
+ return IM_NODE_EDITOR_STYLE->HoveredNodeBorderWidth;
+ */
+
+ public native void setHoveredNodeBorderWidth(float hoveredNodeBorderWidth); /*
+ IM_NODE_EDITOR_STYLE->HoveredNodeBorderWidth = hoveredNodeBorderWidth;
+ */
+
+ public native float getSelectedNodeBorderWidth(); /*
+ return IM_NODE_EDITOR_STYLE->SelectedNodeBorderWidth;
+ */
+
+ public native void setSelectedNodeBorderWidth(float selectedNodeBorderWidth); /*
+ IM_NODE_EDITOR_STYLE->SelectedNodeBorderWidth = selectedNodeBorderWidth;
+ */
+
+ public native float getPinRounding(); /*
+ return IM_NODE_EDITOR_STYLE->PinRounding;
+ */
+
+ public native void setPinRounding(float pinRounding); /*
+ IM_NODE_EDITOR_STYLE->PinRounding = pinRounding;
+ */
+
+ public native float getPinBorderWidth(); /*
+ return IM_NODE_EDITOR_STYLE->PinBorderWidth;
+ */
+
+ public native void setPinBorderWidth(float pinBorderWidth); /*
+ IM_NODE_EDITOR_STYLE->PinBorderWidth = pinBorderWidth;
+ */
+
+ public native float getLinkStrength(); /*
+ return IM_NODE_EDITOR_STYLE->LinkStrength;
+ */
+
+ public native void setLinkStrength(float linkStrength); /*
+ IM_NODE_EDITOR_STYLE->LinkStrength = linkStrength;
+ */
+
+ public native void getSourceDirection(ImVec2 dstImVec2); /*
+ Jni::ImVec2Cpy(env, &IM_NODE_EDITOR_STYLE->SourceDirection, dstImVec2);
+ */
+
+ public native float getSourceDirectionX(); /*
+ return IM_NODE_EDITOR_STYLE->SourceDirection.x;
+ */
+
+ public native float getSourceDirectionY(); /*
+ return IM_NODE_EDITOR_STYLE->SourceDirection.y;
+ */
+
+ public native void setSourceDirection(float x, float y); /*
+ IM_NODE_EDITOR_STYLE->SourceDirection.x = x;
+ IM_NODE_EDITOR_STYLE->SourceDirection.y = y;
+ */
+
+ public native void getTargetDirection(ImVec2 dstImVec2); /*
+ Jni::ImVec2Cpy(env, &IM_NODE_EDITOR_STYLE->TargetDirection, dstImVec2);
+ */
+
+
+ public native float getTargetDirectionX(); /*
+ return IM_NODE_EDITOR_STYLE->TargetDirection.x;
+ */
+
+ public native float getTargetDirectionY(); /*
+ return IM_NODE_EDITOR_STYLE->TargetDirection.y;
+ */
+
+ public native void setTargetDirection(float x, float y); /*
+ IM_NODE_EDITOR_STYLE->TargetDirection.x = x;
+ IM_NODE_EDITOR_STYLE->TargetDirection.y = y;
+ */
+
+ public native float getScrollDuration(); /*
+ return IM_NODE_EDITOR_STYLE->ScrollDuration;
+ */
+
+ public native void setScrollDuration(float scrollDuration); /*
+ IM_NODE_EDITOR_STYLE->ScrollDuration = scrollDuration;
+ */
+
+ public native float getFlowMarkerDistance(); /*
+ return IM_NODE_EDITOR_STYLE->FlowMarkerDistance;
+ */
+
+ public native void setFlowMarkerDistance(float flowMarkerDistance); /*
+ IM_NODE_EDITOR_STYLE->FlowMarkerDistance = flowMarkerDistance;
+ */
+
+ public native float getFlowSpeed(); /*
+ return IM_NODE_EDITOR_STYLE->FlowSpeed;
+ */
+
+ public native void setFlowSpeed(float flowSpeed); /*
+ IM_NODE_EDITOR_STYLE->FlowSpeed = flowSpeed;
+ */
+
+ public native float getFlowDuration(); /*
+ return IM_NODE_EDITOR_STYLE->FlowDuration;
+ */
+
+ public native void setFlowDuration(float flowDuration); /*
+ IM_NODE_EDITOR_STYLE->FlowDuration = flowDuration;
+ */
+
+ public native void getPivotAlignment(ImVec2 dstImVec2); /*
+ Jni::ImVec2Cpy(env, &IM_NODE_EDITOR_STYLE->PivotAlignment, dstImVec2);
+ */
+
+ public native float getPivotAlignmentX(); /*
+ return IM_NODE_EDITOR_STYLE->PivotAlignment.x;
+ */
+
+ public native float getPivotAlignmentY(); /*
+ return IM_NODE_EDITOR_STYLE->PivotAlignment.y;
+ */
+
+ public native void setPivotAlignment(float x, float y); /*
+ IM_NODE_EDITOR_STYLE->PivotAlignment.x = x;
+ IM_NODE_EDITOR_STYLE->PivotAlignment.y = y;
+ */
+
+ public native void getPivotSize(ImVec2 dstImVec2); /*
+ Jni::ImVec2Cpy(env, &IM_NODE_EDITOR_STYLE->PivotSize, dstImVec2);
+ */
+
+ public native float getPivotSizeX(); /*
+ return IM_NODE_EDITOR_STYLE->PivotSize.x;
+ */
+
+ public native float getPivotSizeY(); /*
+ return IM_NODE_EDITOR_STYLE->PivotSize.y;
+ */
+
+ public native void setPivotSize(float x, float y); /*
+ IM_NODE_EDITOR_STYLE->PivotSize.x = x;
+ IM_NODE_EDITOR_STYLE->PivotSize.y = y;
+ */
+
+ public native void getPivotScale(ImVec2 dstImVec2); /*
+ Jni::ImVec2Cpy(env, &IM_NODE_EDITOR_STYLE->PivotScale, dstImVec2);
+ */
+
+ public native float getPivotScaleX(); /*
+ return IM_NODE_EDITOR_STYLE->PivotScale.x;
+ */
+
+ public native float getPivotScaleY(); /*
+ return IM_NODE_EDITOR_STYLE->PivotScale.y;
+ */
+
+ public native void setPivotScale(float x, float y); /*
+ IM_NODE_EDITOR_STYLE->PivotScale.x = x;
+ IM_NODE_EDITOR_STYLE->PivotScale.y = y;
+ */
+
+ public native float getPinCorners(); /*
+ return IM_NODE_EDITOR_STYLE->PinCorners;
+ */
+
+ public native void setPinCorners(float pinCorners); /*
+ IM_NODE_EDITOR_STYLE->PinCorners = pinCorners;
+ */
+
+ public native float getPinRadius(); /*
+ return IM_NODE_EDITOR_STYLE->PinRadius;
+ */
+
+ public native void setPinRadius(float pinRadius); /*
+ IM_NODE_EDITOR_STYLE->PinRadius = pinRadius;
+ */
+
+ public native float getPinArrowSize(); /*
+ return IM_NODE_EDITOR_STYLE->PinArrowSize;
+ */
+
+ public native void setPinArrowSize(float pinArrowSize); /*
+ IM_NODE_EDITOR_STYLE->PinArrowSize = pinArrowSize;
+ */
+
+ public native float getPinArrowWidth(); /*
+ return IM_NODE_EDITOR_STYLE->PinArrowWidth;
+ */
+
+ public native void setPinArrowWidth(float pinArrowWidth); /*
+ IM_NODE_EDITOR_STYLE->PinArrowWidth = pinArrowWidth;
+ */
+
+ public native float getGroupRounding(); /*
+ return IM_NODE_EDITOR_STYLE->GroupRounding;
+ */
+
+ public native void setGroupRounding(float groupRounding); /*
+ IM_NODE_EDITOR_STYLE->GroupRounding = groupRounding;
+ */
+
+ public native float getGroupBorderWidth(); /*
+ return IM_NODE_EDITOR_STYLE->GroupBorderWidth;
+ */
+
+ public native void setGroupBorderWidth(float groupBorderWidth); /*
+ IM_NODE_EDITOR_STYLE->GroupBorderWidth = groupBorderWidth;
+ */
+
+ /**
+ * BINDING NOTICE: colors is a 2d array with sizes: [StyleColor_Count][4]
+ */
+ public native void setColors(float[][] colors); /*
+ for (int i = 0; i < ed::StyleColor_Count; i++) {
+ jfloatArray jColors = (jfloatArray)env->GetObjectArrayElement(colors, i);
+ jfloat* jColor = env->GetFloatArrayElements(jColors, 0);
+
+ IM_NODE_EDITOR_STYLE->Colors[i].x = jColor[0];
+ IM_NODE_EDITOR_STYLE->Colors[i].y = jColor[1];
+ IM_NODE_EDITOR_STYLE->Colors[i].z = jColor[2];
+ IM_NODE_EDITOR_STYLE->Colors[i].w = jColor[3];
+
+ env->ReleaseFloatArrayElements(jColors, jColor, 0);
+ env->DeleteLocalRef(jColors);
+ }
+ */
+
+ public native void getColor(int styleColor, ImVec4 dstImVec4); /*
+ Jni::ImVec4Cpy(env, IM_NODE_EDITOR_STYLE->Colors[styleColor], dstImVec4);
+ */
+
+ public native void setColor(int styleColor, float r, float g, float b, float a); /*
+ IM_NODE_EDITOR_STYLE->Colors[styleColor] = ImColor((float)r, (float)g, (float)b, (float)a);
+ */
+
+ public native void setColor(int styleColor, int r, int g, int b, int a); /*
+ IM_NODE_EDITOR_STYLE->Colors[styleColor] = ImColor((int)r, (int)g, (int)b, (int)a);
+ */
+
+ public native void setColor(int styleColor, int col); /*
+ IM_NODE_EDITOR_STYLE->Colors[styleColor] = ImColor(col);
+ */
+}
diff --git a/imgui-binding/src/main/java/imgui/nodeditor/ImNodeEditorStyleColor.java b/imgui-binding/src/main/java/imgui/nodeditor/ImNodeEditorStyleColor.java
new file mode 100644
index 0000000..f08846d
--- /dev/null
+++ b/imgui-binding/src/main/java/imgui/nodeditor/ImNodeEditorStyleColor.java
@@ -0,0 +1,25 @@
+package imgui.nodeditor;
+
+public final class ImNodeEditorStyleColor {
+ private ImNodeEditorStyleColor() {
+ }
+
+ public static final int Bg = 0;
+ public static final int Grid = 1;
+ public static final int NodeBg = 2;
+ public static final int NodeBorder = 3;
+ public static final int HovNodeBorder = 4;
+ public static final int SelNodeBorder = 5;
+ public static final int NodeSelRect = 6;
+ public static final int NodeSelRectBorder = 7;
+ public static final int HovLinkBorder = 8;
+ public static final int SelLinkBorder = 9;
+ public static final int LinkSelRect = 10;
+ public static final int LinkSelRectBorder = 11;
+ public static final int PinRect = 12;
+ public static final int PinRectBorder = 13;
+ public static final int Flow = 14;
+ public static final int FlowMarker = 15;
+ public static final int GroupBg = 16;
+ public static final int GroupBorder = 17;
+}
diff --git a/imgui-binding/src/main/java/imgui/nodeditor/ImNodeEditorStyleVar.java b/imgui-binding/src/main/java/imgui/nodeditor/ImNodeEditorStyleVar.java
new file mode 100644
index 0000000..65c4060
--- /dev/null
+++ b/imgui-binding/src/main/java/imgui/nodeditor/ImNodeEditorStyleVar.java
@@ -0,0 +1,30 @@
+package imgui.nodeditor;
+
+public final class ImNodeEditorStyleVar {
+ private ImNodeEditorStyleVar() {
+ }
+
+ public static final int NodePadding = 0;
+ public static final int NodeRounding = 1;
+ public static final int NodeBorderWidth = 2;
+ public static final int HoveredNodeBorderWidth = 3;
+ public static final int SelectedNodeBorderWidth = 4;
+ public static final int PinRounding = 5;
+ public static final int PinBorderWidth = 6;
+ public static final int LinkStrength = 7;
+ public static final int SourceDirection = 8;
+ public static final int TargetDirection = 9;
+ public static final int ScrollDuration = 10;
+ public static final int FlowMarkerDistance = 11;
+ public static final int FlowSpeed = 12;
+ public static final int FlowDuration = 13;
+ public static final int PivotAlignment = 14;
+ public static final int PivotSize = 15;
+ public static final int PivotScale = 16;
+ public static final int PinCorners = 17;
+ public static final int PinRadius = 18;
+ public static final int PinArrowSize = 19;
+ public static final int PinArrowWidth = 20;
+ public static final int GroupRounding = 21;
+ public static final int GroupBorderWidth = 22;
+}
diff --git a/imgui-lwjgl3/src/test/java/ExampleUi.java b/imgui-lwjgl3/src/test/java/ExampleUi.java
index 727ac53..e92d761 100644
--- a/imgui-lwjgl3/src/test/java/ExampleUi.java
+++ b/imgui-lwjgl3/src/test/java/ExampleUi.java
@@ -5,10 +5,19 @@ import imgui.flag.ImGuiDir;
import imgui.flag.ImGuiInputTextFlags;
import imgui.flag.ImGuiStyleVar;
import imgui.flag.ImGuiWindowFlags;
+import imgui.imnodes.ImNodes;
+import imgui.imnodes.ImNodesContext;
+import imgui.imnodes.ImNodesPinShape;
+import imgui.nodeditor.ImNodeEditor;
import imgui.internal.ImGui;
import imgui.internal.flag.ImGuiDockNodeFlags;
+import imgui.nodeditor.ImNodeEditorConfig;
+import imgui.nodeditor.ImNodeEditorContext;
+import imgui.nodeditor.ImNodeEditorPinKind;
import imgui.type.ImBoolean;
import imgui.ImColor;
+import imgui.type.ImInt;
+import imgui.type.ImLong;
import imgui.type.ImString;
import org.lwjgl.BufferUtils;
@@ -17,8 +26,23 @@ 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.*;
+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 {
@@ -37,6 +61,8 @@ final class ExampleUi {
// 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;
@@ -46,7 +72,25 @@ final class ExampleUi {
// 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 ImNodeEditorContext imNodeEditorContext;
+
+ // 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 (imNodeEditorContext == null) {
+ final ImNodeEditorConfig config = new ImNodeEditorConfig();
+ config.setSettingsFile(null);
+ imNodeEditorContext = new ImNodeEditorContext(config);
+ }
+
final int dockspaceId = ImGui.getID("MyDockSpace");
showDockSpace(dockspaceId);
setupBottomDockedWindow(dockspaceId);
@@ -57,7 +101,6 @@ final class ExampleUi {
ImGui.setNextWindowPos(mainViewport.getWorkPosX() + 10, mainViewport.getWorkPosY() + 10, ImGuiCond.Once);
ImGui.begin("Custom window"); // Start Custom window
-
showWindowImage();
showToggles();
@@ -80,6 +123,14 @@ final class ExampleUi {
if (showDemoWindow.get()) {
ImGui.showDemoWindow(showDemoWindow);
}
+
+ if (showImNodesWindow.get()) {
+ showImNodesWindow();
+ }
+
+ if (showImNodeEditorWindow.get()) {
+ showImNodeEditorWindow();
+ }
}
private void showDockSpace(final int dockspaceId) {
@@ -138,6 +189,8 @@ final class ExampleUi {
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;
}
@@ -190,6 +243,177 @@ final class ExampleUi {
}
}
+ 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")) {
+ ImNodeEditor.navigateToContent(1F);
+ }
+
+ ImNodeEditor.setCurrentEditor(imNodeEditorContext);
+ ImNodeEditor.begin("Node Editor");
+
+ for (Graph.GraphNode node : graph.nodes.values()) {
+ ImNodeEditor.beginNode(node.nodeId);
+
+ ImGui.text(node.getName());
+
+ ImNodeEditor.beginPin(node.getInputPinId(), ImNodeEditorPinKind.Input);
+ ImGui.text("-> In");
+ ImNodeEditor.endPin();
+
+ ImGui.sameLine();
+
+ ImNodeEditor.beginPin(node.getOutputPinId(), ImNodeEditorPinKind.Output);
+ ImGui.text("Out ->");
+ ImNodeEditor.endPin();
+
+ ImNodeEditor.endNode();
+ }
+
+ if (ImNodeEditor.beginCreate()) {
+ final ImLong a = new ImLong();
+ final ImLong b = new ImLong();
+ if (ImNodeEditor.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 && ImNodeEditor.acceptNewItem()) {
+ source.outputNodeId = target.nodeId;
+ }
+ }
+ }
+ ImNodeEditor.endCreate();
+
+ int uniqueLinkId = 1;
+ for (Graph.GraphNode node : graph.nodes.values()) {
+ if (graph.nodes.containsKey(node.outputNodeId)) {
+ ImNodeEditor.link(uniqueLinkId++, node.getOutputPinId(), graph.nodes.get(node.outputNodeId).getInputPinId());
+ }
+ }
+
+ ImNodeEditor.suspend();
+ final long nodeWithContextMenu = ImNodeEditor.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 (ImNodeEditor.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 = ImNodeEditor.toCanvasX(ImGui.getMousePosX());
+ final float canvasY = ImNodeEditor.toCanvasY(ImGui.getMousePosY());
+ ImNodeEditor.setNodePosition(node.nodeId, canvasX, canvasY);
+ ImGui.closeCurrentPopup();
+ }
+ ImGui.endPopup();
+ }
+ ImNodeEditor.resume();
+
+ ImNodeEditor.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());
@@ -219,4 +443,70 @@ final class ExampleUi {
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
index 8e7bff7..7e6f83f 100644
--- a/imgui-lwjgl3/src/test/java/ImGuiGlfwExample.java
+++ b/imgui-lwjgl3/src/test/java/ImGuiGlfwExample.java
@@ -1,5 +1,30 @@
import static org.lwjgl.glfw.Callbacks.glfwFreeCallbacks;
-import static org.lwjgl.glfw.GLFW.*;
+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;
@@ -22,6 +47,8 @@ import java.io.InputStream;
import java.io.UncheckedIOException;
import java.nio.IntBuffer;
import java.util.Objects;
+
+import imgui.imnodes.ImNodes;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.opengl.GL;
@@ -60,6 +87,7 @@ public final class ImGuiGlfwExample {
imGuiGl3.dispose();
imGuiGlfw.dispose();
+ ImNodes.shutdown();
ImGui.destroyContext();
disposeWindow();
@@ -137,7 +165,7 @@ public final class ImGuiGlfwExample {
// IMPORTANT!!
// This line is critical for Dear ImGui to work.
ImGui.createContext();
-
+ ImNodes.initialize();
// ------------------------------------------------------------
// Initialize ImGuiIO config
final ImGuiIO io = ImGui.getIO();
diff --git a/imgui-node-editor b/imgui-node-editor
new file mode 160000
index 0000000..687a72f
--- /dev/null
+++ b/imgui-node-editor
@@ -0,0 +1 @@
+Subproject commit 687a72f940c76cf5064e13fe55fa0408c18fcbe4
diff --git a/imnodes b/imnodes
new file mode 160000
index 0000000..5959729
--- /dev/null
+++ b/imnodes
@@ -0,0 +1 @@
+Subproject commit 595972941054e9fa453f5a6d5590a51c9e1c98a4