diff --git a/.gitmodules b/.gitmodules index 83a2b57..9b65434 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "include/imnodes"] path = include/imnodes url = https://github.com/Nelarius/imnodes +[submodule "include/imguizmo"] + path = include/imguizmo + url = https://github.com/CedricGuillemet/ImGuizmo.git diff --git a/buildSrc/src/main/groovy/imgui/generate/GenerateLibs.groovy b/buildSrc/src/main/groovy/imgui/generate/GenerateLibs.groovy index a87f327..cc688e0 100644 --- a/buildSrc/src/main/groovy/imgui/generate/GenerateLibs.groovy +++ b/buildSrc/src/main/groovy/imgui/generate/GenerateLibs.groovy @@ -48,7 +48,7 @@ class GenerateLibs extends DefaultTask { // Copy ImGui h/cpp files project.copy { CopySpec spec -> - ['include/imgui', 'include/imnodes', 'include/imgui-node-editor'].each { + ['include/imgui', 'include/imnodes', 'include/imgui-node-editor', 'include/imguizmo'].each { spec.from(project.rootProject.file(it)) { CopySpec s -> s.include('*.h', '*.cpp', '*.inl') } } spec.from(project.rootProject.file('imgui-binding/src/main/native')) diff --git a/example/src/main/java/ExampleImGuizmo.java b/example/src/main/java/ExampleImGuizmo.java new file mode 100644 index 0000000..4a72d6c --- /dev/null +++ b/example/src/main/java/ExampleImGuizmo.java @@ -0,0 +1,341 @@ +import imgui.ImGui; +import imgui.extension.imguizmo.ImGuizmo; +import imgui.extension.imguizmo.flag.Mode; +import imgui.extension.imguizmo.flag.Operation; +import imgui.flag.ImGuiCond; +import imgui.flag.ImGuiInputTextFlags; +import imgui.flag.ImGuiWindowFlags; +import imgui.type.ImBoolean; +import imgui.type.ImFloat; + +import java.awt.Desktop; +import java.net.URI; +import java.util.Arrays; + +import static org.lwjgl.glfw.GLFW.GLFW_KEY_LEFT_SHIFT; +import static org.lwjgl.glfw.GLFW.GLFW_KEY_R; +import static org.lwjgl.glfw.GLFW.GLFW_KEY_S; +import static org.lwjgl.glfw.GLFW.GLFW_KEY_T; + +public class ExampleImGuizmo { + private static final String URL = "https://github.com/CedricGuillemet/ImGuizmo/tree/f7bbbe"; + + private static final int CAM_DISTANCE = 8; + private static final float CAM_Y_ANGLE = 165.f / 180.f * (float) Math.PI; + private static final float CAM_X_ANGLE = 32.f / 180.f * (float) Math.PI; + private static final float FLT_EPSILON = 1.19209290E-07f; + + private static final float[][] OBJECT_MATRICES = { + { + 1.f, 0.f, 0.f, 0.f, + 0.f, 1.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + 0.f, 0.f, 0.f, 1.f + }, + { + 1.f, 0.f, 0.f, 0.f, + 0.f, 1.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + 2.f, 0.f, 0.f, 1.f + }, + { + 1.f, 0.f, 0.f, 0.f, + 0.f, 1.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + 2.f, 0.f, 2.f, 1.f + }, + { + 1.f, 0.f, 0.f, 0.f, + 0.f, 1.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + 0.f, 0.f, 2.f, 1.f + } + }; + + private static final float[] IDENTITY_MATRIX = { + 1.f, 0.f, 0.f, 0.f, + 0.f, 1.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + 0.f, 0.f, 0.f, 1.f + }; + + private static final float[] VIEW_MANIPULATE_SIZE = new float[]{128f, 128f}; + + private static final float[] EMPTY = new float[]{0}; + + private static final float[] INPUT_CAMERA_VIEW = { + 1.f, 0.f, 0.f, 0.f, + 0.f, 1.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + 0.f, 0.f, 0.f, 1.f + }; + + private static final float[] INPUT_BOUNDS = new float[]{-0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f}; + private static final float[] INPUT_BOUNDS_SNAP = new float[]{1f, 1f, 1f}; + + private static final float[] INPUT_SNAP_VALUE = new float[]{1f, 1f, 1f}; + private static final float[] INPUT_MATRIX_TRANSLATION = new float[3]; + private static final float[] INPUT_MATRIX_SCALE = new float[3]; + private static final float[] INPUT_MATRIX_ROTATION = new float[3]; + + private static final ImFloat INPUT_FLOAT = new ImFloat(); + + private static final ImBoolean BOUNDING_SIZE = new ImBoolean(false); + private static final ImBoolean USE_SNAP = new ImBoolean(false); + + private static int currentMode = Mode.LOCAL; + private static int currentGizmoOperation; + + private static boolean boundSizingSnap = false; + private static boolean firstFrame = true; + + public static void show(final ImBoolean showImGuizmoWindow) { + ImGuizmo.beginFrame(); + + if (ImGui.begin("ImGuizmo Demo", showImGuizmoWindow)) { + ImGui.text("This a demo for ImGuizmo"); + + ImGui.alignTextToFramePadding(); + ImGui.text("Repo:"); + ImGui.sameLine(); + if (ImGui.button(URL)) { + try { + Desktop.getDesktop().browse(new URI(URL)); + } catch (Exception e) { + e.printStackTrace(); + } + } + ImGui.separator(); + + if (firstFrame) { + float[] eye = new float[]{ + (float) (Math.cos(CAM_Y_ANGLE) * Math.cos(CAM_X_ANGLE) * CAM_DISTANCE), + (float) (Math.sin(CAM_X_ANGLE) * CAM_DISTANCE), + (float) (Math.sin(CAM_Y_ANGLE) * Math.cos(CAM_X_ANGLE) * CAM_DISTANCE) + }; + float[] at = new float[]{0.f, 0.f, 0.f}; + float[] up = new float[]{0.f, 1.f, 0.f}; + lookAt(eye, at, up, INPUT_CAMERA_VIEW); + firstFrame = false; + } + + ImGui.text("Keybindings:"); + ImGui.text("T - Translate"); + ImGui.text("R - Rotate"); + ImGui.text("S - Scale"); + ImGui.separator(); + + if (ImGuizmo.isUsing()) { + ImGui.text("Using gizmo"); + if (ImGuizmo.isOver()) { + ImGui.text("Over a gizmo"); + } + if (ImGuizmo.isOver(Operation.TRANSLATE)) { + ImGui.text("Over translate gizmo"); + } else if (ImGuizmo.isOver(Operation.ROTATE)) { + ImGui.text("Over rotate gizmo"); + } else if (ImGuizmo.isOver(Operation.SCALE)) { + ImGui.text("Over scale gizmo"); + } + } else { + ImGui.text("Not using gizmo"); + } + + editTransform(showImGuizmoWindow); + ImGui.end(); + } + } + + private static void editTransform(final ImBoolean showImGuizmoWindow) { + if (ImGui.isKeyPressed(GLFW_KEY_T)) { + currentGizmoOperation = Operation.TRANSLATE; + } else if (ImGui.isKeyPressed(GLFW_KEY_R)) { + currentGizmoOperation = Operation.ROTATE; + } else if (ImGui.isKeyPressed(GLFW_KEY_S)) { + currentGizmoOperation = Operation.SCALE; + } else if (ImGui.isKeyPressed(GLFW_KEY_LEFT_SHIFT)) { + USE_SNAP.set(!USE_SNAP.get()); + } + + if (ImGuizmo.isUsing()) { + ImGuizmo.decomposeMatrixToComponents(OBJECT_MATRICES[0], INPUT_MATRIX_TRANSLATION, INPUT_MATRIX_ROTATION, INPUT_MATRIX_SCALE); + } + + ImGui.inputFloat3("Tr", INPUT_MATRIX_TRANSLATION, "%.3f", ImGuiInputTextFlags.ReadOnly); + ImGui.inputFloat3("Rt", INPUT_MATRIX_ROTATION, "%.3f", ImGuiInputTextFlags.ReadOnly); + ImGui.inputFloat3("Sc", INPUT_MATRIX_SCALE, "%.3f", ImGuiInputTextFlags.ReadOnly); + + if (ImGuizmo.isUsing()) { + ImGuizmo.recomposeMatrixFromComponents(OBJECT_MATRICES[0], INPUT_MATRIX_TRANSLATION, INPUT_MATRIX_ROTATION, INPUT_MATRIX_SCALE); + } + + if (currentGizmoOperation != Operation.SCALE) { + if (ImGui.radioButton("Local", currentMode == Mode.LOCAL)) { + currentMode = Mode.LOCAL; + } + ImGui.sameLine(); + if (ImGui.radioButton("World", currentMode == Mode.WORLD)) { + currentMode = Mode.WORLD; + } + } + + ImGui.checkbox("Snap Checkbox", USE_SNAP); + + INPUT_FLOAT.set(INPUT_SNAP_VALUE[0]); + switch (currentGizmoOperation) { + case Operation.TRANSLATE: + ImGui.inputFloat3("Snap Value", INPUT_SNAP_VALUE); + break; + case Operation.ROTATE: + ImGui.inputFloat("Angle Value", INPUT_FLOAT); + float rotateValue = INPUT_FLOAT.get(); + Arrays.fill(INPUT_SNAP_VALUE, rotateValue); //avoiding allocation + break; + case Operation.SCALE: + ImGui.inputFloat("Scale Value", INPUT_FLOAT); + float scaleValue = INPUT_FLOAT.get(); + Arrays.fill(INPUT_SNAP_VALUE, scaleValue); + break; + } + + ImGui.checkbox("Show Bound Sizing", BOUNDING_SIZE); + + if (BOUNDING_SIZE.get()) { + if (ImGui.checkbox("BoundSizingSnap", boundSizingSnap)) { + boundSizingSnap = !boundSizingSnap; + } + ImGui.sameLine(); + ImGui.inputFloat3("Snap", INPUT_BOUNDS_SNAP); + } + + ImGui.setNextWindowPos(ImGui.getMainViewport().getPosX() + 100, ImGui.getMainViewport().getPosY() + 100, ImGuiCond.Once); + ImGui.setNextWindowSize(800, 400, ImGuiCond.Once); + ImGui.begin("Gizmo", showImGuizmoWindow); + ImGui.beginChild("prevent_window_from_moving_by_drag", 0, 0, false, ImGuiWindowFlags.NoMove); + + float aspect = ImGui.getWindowWidth() / ImGui.getWindowHeight(); + float[] cameraProjection = perspective(27, aspect, 0.1f, 100f); + + ImGuizmo.setOrthographic(false); + ImGuizmo.setEnabled(true); + ImGuizmo.setDrawList(); + + float windowWidth = ImGui.getWindowWidth(); + float windowHeight = ImGui.getWindowHeight(); + ImGuizmo.setRect(ImGui.getWindowPosX(), ImGui.getWindowPosY(), windowWidth, windowHeight); + + ImGuizmo.drawGrid(INPUT_CAMERA_VIEW, cameraProjection, IDENTITY_MATRIX, 100); + ImGuizmo.setId(0); + ImGuizmo.drawCubes(INPUT_CAMERA_VIEW, cameraProjection, OBJECT_MATRICES[0]); + + if (USE_SNAP.get() && BOUNDING_SIZE.get() && boundSizingSnap) { + ImGuizmo.manipulate(INPUT_CAMERA_VIEW, cameraProjection, OBJECT_MATRICES[0], currentGizmoOperation, currentMode, INPUT_SNAP_VALUE, INPUT_BOUNDS, INPUT_BOUNDS_SNAP); + } else if (USE_SNAP.get() && BOUNDING_SIZE.get()) { + ImGuizmo.manipulate(INPUT_CAMERA_VIEW, cameraProjection, OBJECT_MATRICES[0], currentGizmoOperation, currentMode, INPUT_SNAP_VALUE, INPUT_BOUNDS); + } else if (BOUNDING_SIZE.get() && boundSizingSnap) { + ImGuizmo.manipulate(INPUT_CAMERA_VIEW, cameraProjection, OBJECT_MATRICES[0], currentGizmoOperation, currentMode, EMPTY, INPUT_BOUNDS, INPUT_BOUNDS_SNAP); + } else if (BOUNDING_SIZE.get()) { + ImGuizmo.manipulate(INPUT_CAMERA_VIEW, cameraProjection, OBJECT_MATRICES[0], currentGizmoOperation, currentMode, EMPTY, INPUT_BOUNDS); + } else if (USE_SNAP.get()) { + ImGuizmo.manipulate(INPUT_CAMERA_VIEW, cameraProjection, OBJECT_MATRICES[0], currentGizmoOperation, currentMode, INPUT_SNAP_VALUE); + } else { + ImGuizmo.manipulate(INPUT_CAMERA_VIEW, cameraProjection, OBJECT_MATRICES[0], currentGizmoOperation, currentMode); + } + + float viewManipulateRight = ImGui.getWindowPosX() + windowWidth; + float viewManipulateTop = ImGui.getWindowPosY(); + ImGuizmo.viewManipulate(INPUT_CAMERA_VIEW, CAM_DISTANCE, new float[]{viewManipulateRight - 128, viewManipulateTop}, VIEW_MANIPULATE_SIZE, 0x10101010); + + ImGui.endChild(); + ImGui.end(); + } + + private static float[] perspective(float fovY, float aspect, float near, float far) { + float ymax, xmax; + ymax = (float) (near * Math.tan(fovY * Math.PI / 180.0f)); + xmax = ymax * aspect; + return frustum(-xmax, xmax, -ymax, ymax, near, far); + } + + private static float[] frustum(float left, float right, float bottom, float top, float near, float far) { + float[] r = new float[16]; + float temp = 2.0f * near; + float temp2 = right - left; + float temp3 = top - bottom; + float temp4 = far - near; + r[0] = temp / temp2; + r[1] = 0.0f; + r[2] = 0.0f; + r[3] = 0.0f; + r[4] = 0.0f; + r[5] = temp / temp3; + r[6] = 0.0f; + r[7] = 0.0f; + r[8] = (right + left) / temp2; + r[9] = (top + bottom) / temp3; + r[10] = (-far - near) / temp4; + r[11] = -1.0f; + r[12] = 0.0f; + r[13] = 0.0f; + r[14] = (-temp * far) / temp4; + r[15] = 0.0f; + return r; + } + + private static float[] cross(float[] a, float[] b) { + float[] r = new float[3]; + r[0] = a[1] * b[2] - a[2] * b[1]; + r[1] = a[2] * b[0] - a[0] * b[2]; + r[2] = a[0] * b[1] - a[1] * b[0]; + return r; + } + + private static float dot(float[] a, float[] b) { + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; + } + + private static float[] normalize(float[] a) { + float[] r = new float[3]; + float il = (float) (1.f / (Math.sqrt(dot(a, a)) + FLT_EPSILON)); + r[0] = a[0] * il; + r[1] = a[1] * il; + r[2] = a[2] * il; + return r; + } + + private static void lookAt(float[] eye, float[] at, float[] up, float[] m16) { + float[] x; + float[] y; + float[] z; + float[] tmp = new float[3]; + + tmp[0] = eye[0] - at[0]; + tmp[1] = eye[1] - at[1]; + tmp[2] = eye[2] - at[2]; + z = normalize(tmp); + y = normalize(up); + + tmp = cross(y, z); + x = normalize(tmp); + + tmp = cross(z, x); + y = normalize(tmp); + + m16[0] = x[0]; + m16[1] = y[0]; + m16[2] = z[0]; + m16[3] = 0.0f; + m16[4] = x[1]; + m16[5] = y[1]; + m16[6] = z[1]; + m16[7] = 0.0f; + m16[8] = x[2]; + m16[9] = y[2]; + m16[10] = z[2]; + m16[11] = 0.0f; + m16[12] = -dot(x, eye); + m16[13] = -dot(y, eye); + m16[14] = -dot(z, eye); + m16[15] = 1.0f; + } +} diff --git a/example/src/main/java/Extra.java b/example/src/main/java/Extra.java index 3d09c83..95b6ccb 100644 --- a/example/src/main/java/Extra.java +++ b/example/src/main/java/Extra.java @@ -7,6 +7,7 @@ public class Extra { 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 ImBoolean SHOW_DRAG_N_DROP_WINDOW = new ImBoolean(false); + private static final ImBoolean SHOW_IMGUIZMO_DEMO = new ImBoolean(false); private static final Graph GRAPH = new Graph(); @@ -16,6 +17,7 @@ public class Extra { ImGui.checkbox("Show ImNodes Demo Window", SHOW_IMNODES_DEMO_WINDOW); ImGui.checkbox("Show imgui-node-editor Demo Window", SHOW_IMGUI_NODE_EDITOR_DEMO_WINDOW); ImGui.checkbox("Show Drag'N'Drop Demo Window", SHOW_DRAG_N_DROP_WINDOW); + ImGui.checkbox("Show ImGuizmo Demo Window", SHOW_IMGUIZMO_DEMO); if (SHOW_DEMO_WINDOW.get()) { ImGui.showDemoWindow(SHOW_DEMO_WINDOW); @@ -29,6 +31,10 @@ public class Extra { ExampleImGuiNodeEditor.show(SHOW_IMGUI_NODE_EDITOR_DEMO_WINDOW, GRAPH); } + if (SHOW_IMGUIZMO_DEMO.get()) { + ExampleImGuizmo.show(SHOW_IMGUIZMO_DEMO); + } + if (SHOW_DRAG_N_DROP_WINDOW.get()) { ExampleDragAndDrop.show(SHOW_DRAG_N_DROP_WINDOW); } diff --git a/imgui-binding/src/main/java/imgui/extension/imguizmo/ImGuizmo.java b/imgui-binding/src/main/java/imgui/extension/imguizmo/ImGuizmo.java new file mode 100644 index 0000000..db00a09 --- /dev/null +++ b/imgui-binding/src/main/java/imgui/extension/imguizmo/ImGuizmo.java @@ -0,0 +1,341 @@ +package imgui.extension.imguizmo; + +import imgui.ImDrawList; +import imgui.ImGui; + +public final class ImGuizmo { + private static final float[] MATRICES = new float[4 * 16]; //for drawCubes() + + private ImGuizmo() { + } + + /*JNI + #include "_imguizmo.h" + */ + + private static native void nEnabled(boolean enabled); /* + ImGuizmo::Enable(enabled); + */ + + /** + * Enable/Disable the gizmo. + */ + public static void setEnabled(final boolean isEnabled) { + nEnabled(isEnabled); + } + + private static native boolean nIsUsing(); /* + return ImGuizmo::IsUsing(); + */ + + /** + * Checks to see if we're using the Gizmo. + */ + public static boolean isUsing() { + return nIsUsing(); + } + + private static native boolean nIsOver(); /* + return ImGuizmo::IsOver(); + */ + + /** + * Checks to see if we're over the Gizmo. + */ + public static boolean isOver() { + return nIsOver(); + } + + private static native void nSetDrawList(long pointer); /* + ImGuizmo::SetDrawlist((ImDrawList*)pointer); + */ + + /** + * Setting the draw list of the given Gizmo. + * + * @param drawList the target drawlist + */ + public static void setDrawList(final ImDrawList drawList) { + nSetDrawList(drawList.ptr); + } + + /** + * Setting the default window drawlist. + */ + public static void setDrawList() { + setDrawList(ImGui.getWindowDrawList()); + } + + /** + * Starts the next frame for the Gizmo. + * Call this after you've called ImGui.beginFrame(). + */ + public static native void beginFrame(); /* + ImGuizmo::BeginFrame(); + */ + + private static native void nDecomposeMatrixToComponents(float[] matrix, float[] translation, float[] rotation, float[] scale); /* + ImGuizmo::DecomposeMatrixToComponents(matrix, translation, rotation, scale); + */ + + /** + * Helper function for manually editing Translation/Rotation/Scale with an input float. + * Translation, Rotation and Scale float points to 3 floats each. + * Angles are in degrees (more suitable for human editing). + * + * @param modelMatrix the model matrix + * @param translation the model translation + * @param rotation the model rotation + * @param scale the model scale + * @see Reference Page + */ + public static void decomposeMatrixToComponents(final float[] modelMatrix, final float[] translation, final float[] rotation, final float[] scale) { + nDecomposeMatrixToComponents(modelMatrix, translation, rotation, scale); + } + + private static native void nRecomposeMatrixFromComponents(float[] matrix, float[] translation, float[] rotation, float[] scale); /* + ImGuizmo::RecomposeMatrixFromComponents(translation, rotation, scale, matrix); + */ + + /** + * Helper function for manually editing Translation/Rotation/Scale with an input float. + * Translation, Rotation and Scale float points to 3 floats each. + * Angles are in degrees (more suitable for human editing). + * + * @param modelMatrix the model matrix + * @param translation the model translation + * @param rotation the model rotation + * @param scale the model scale + * @see Reference Page + */ + public static void recomposeMatrixFromComponents(final float[] modelMatrix, final float[] translation, final float[] rotation, final float[] scale) { + nRecomposeMatrixFromComponents(modelMatrix, translation, rotation, scale); + } + + public static native void nSetRect(float x, float y, float width, float height); /* + ImGuizmo::SetRect(x, y, width, height); + */ + + /** + * This will set the rect position. + * + * @param x x coordinate of the rectangle + * @param y y coordinate of the rectangle + * @param width width of the rectangle + * @param height height of the rectangle + */ + public static void setRect(final float x, final float y, final float width, final float height) { + nSetRect(x, y, width, height); + } + + private static native void nSetOrthographic(boolean ortho); /* + ImGuizmo::SetOrthographic(ortho); + */ + + /** + * Making sure if we're set to ortho or not. + */ + public static void setOrthographic(final boolean ortho) { + nSetOrthographic(ortho); + } + + private static native void nDrawCubes(float[] view, float[] projection, float[] matrices, int matrixCount); /* + ImGuizmo::DrawCubes(view, projection, matrices, matrixCount); + */ + + /** + * Drawing an arbitrary cube in the world. + * + * @param view target camera view + * @param projection target camera projection + * @param cubeMatrices cube matrices (max. 4 cubes allowed) + */ + public static void drawCubes(final float[] view, final float[] projection, final float[]... cubeMatrices) { + if (cubeMatrices.length > 4) { + throw new IllegalArgumentException("Drawing cubes with ImGuizmo only supports up to 4 cubes because it should only be used for debugging purposes"); + } + + for (int i = 0, cubeMatricesLength = cubeMatrices.length; i < cubeMatricesLength; i++) { + final float[] cubeMatrix = cubeMatrices[i]; + System.arraycopy(cubeMatrix, 0, MATRICES, i * cubeMatrix.length, cubeMatrix.length); + } + + nDrawCubes(view, projection, MATRICES, cubeMatrices.length); + } + + private static native void nDrawGrid(float[] view, float[] projection, float[] matrix, int gridSize); /* + ImGuizmo::DrawGrid(view, projection, matrix, gridSize); + */ + + /** + * Drawing a grid to the world (should only be used for debugging purposes). + * + * @param view target camera view + * @param projection target camera projection + * @param matrix grid matrix + * @param gridSize grid size + */ + public static void drawGrid(final float[] view, final float[] projection, final float[] matrix, final int gridSize) { + nDrawGrid(view, projection, matrix, gridSize); + } + + private static native void nManipulate(float[] view, float[] projection, int operation, int mode, float[] matrix); /* + ImGuizmo::Manipulate(view, projection, (ImGuizmo::OPERATION) operation, (ImGuizmo::MODE) mode, matrix); + */ + + private static native void nManipulate(float[] view, float[] projection, int operation, int mode, float[] matrix, float[] snap); /* + ImGuizmo::Manipulate(view, projection, (ImGuizmo::OPERATION) operation, (ImGuizmo::MODE) mode, matrix, NULL, snap); + */ + + private static native void nManipulate(float[] view, float[] projection, int operation, int mode, float[] matrix, float[] snap, float[] bounds); /* + ImGuizmo::Manipulate(view, projection, (ImGuizmo::OPERATION) operation, (ImGuizmo::MODE) mode, matrix, NULL, snap, bounds, NULL); + */ + + private static native void nManipulate(float[] view, float[] projection, int operation, int mode, float[] matrix, float[] snap, float[] bounds, float[] boundsSnap); /* + ImGuizmo::Manipulate(view, projection, (ImGuizmo::OPERATION) operation, (ImGuizmo::MODE) mode, matrix, NULL, snap, bounds, boundsSnap); + */ + + private static native void nManipulate(float[] view, float[] projection, int operation, int mode, float[] matrix, float[] deltaMatrix, float[] snap, float[] bounds, float[] boundsSnap); /* + ImGuizmo::Manipulate(view, projection, (ImGuizmo::OPERATION) operation, (ImGuizmo::MODE) mode, matrix, deltaMatrix, snap, bounds, boundsSnap); + */ + + /** + * Manipulating the given model matrix. + * + * @param view target camera view + * @param projection target camera projection + * @param modelMatrix model matrix + * @param operation target operation + * @param mode target mode + */ + public static void manipulate(final float[] view, final float[] projection, final float[] modelMatrix, final int operation, final int mode) { + nManipulate(view, projection, operation, mode, modelMatrix); + } + + /** + * Manipulating the given model matrix with snap feature enabled! + * + * @param view target camera view + * @param projection target camera projection + * @param modelMatrix model matrix + * @param operation target operation + * @param mode target mode + * @param snap snap value + */ + public static void manipulate(final float[] view, final float[] projection, final float[] modelMatrix, final int operation, final int mode, final float[] snap) { + nManipulate(view, projection, operation, mode, modelMatrix, snap); + } + + /** + * Manipulating the given model matrix with snap and bounds feature enabled! + * + * @param view target camera view + * @param projection target camera projection + * @param modelMatrix model matrix + * @param operation target operation + * @param mode target mode + * @param snap snap value + * @param bounds bounds value + */ + public static void manipulate(final float[] view, final float[] projection, final float[] modelMatrix, final int operation, final int mode, final float[] snap, final float[] bounds) { + nManipulate(view, projection, operation, mode, modelMatrix, snap, bounds); + } + + /** + * Manipulating the given model matrix with snap and bounds(snap) feature enabled! + * + * @param view target camera view + * @param projection target camera projection + * @param modelMatrix model matrix + * @param operation target operation + * @param mode target mode + * @param snap snap value + * @param bounds bounds value + * @param boundsSnap bounds snap value + */ + public static void manipulate(final float[] view, final float[] projection, final float[] modelMatrix, final int operation, final int mode, final float[] snap, final float[] bounds, final float[] boundsSnap) { + nManipulate(view, projection, operation, mode, modelMatrix, snap, bounds, boundsSnap); + } + + /** + * Manipulating the given model matrix with delta matrix + * + * @param view target camera view + * @param projection target camera projection + * @param modelMatrix model matrix + * @param deltaMatrix delta matrix + * @param operation target operation + * @param mode target mode + * @param snap snap value + * @param bounds bounds value + * @param boundsSnap bounds snap value + */ + public static void manipulate(final float[] view, final float[] projection, final float[] modelMatrix, final float[] deltaMatrix, final int operation, final int mode, final float[] snap, final float[] bounds, final float[] boundsSnap) { + nManipulate(view, projection, operation, mode, modelMatrix, deltaMatrix, snap, bounds, boundsSnap); + } + + private static native void nViewManipulate(float[] view, float length, float[] position, float[] size, int color); /* + ImGuizmo::ViewManipulate(view, length, ImVec2(position[0], position[1]), ImVec2(size[0], size[1]), (ImU32) color); + */ + + /** + * Manipulating the view + * + * @param view target camera view + * @param length camera distance/length + * @param position position + * @param size size + * @param color color + */ + public static void viewManipulate(final float[] view, final float length, final float[] position, final float[] size, final int color) { + nViewManipulate(view, length, position, size, color); + } + + private static native void nSetId(int id); /* + ImGuizmo::SetID(id); + */ + + /** + * This will update the current id + */ + public static void setId(final int id) { + nSetId(id); + } + + private static native boolean nIsOver(int operation); /* + return ImGuizmo::IsOver((ImGuizmo::OPERATION) operation); + */ + + /** + * Checks if we're over the current operation + * + * One of: + * + * + * + * + * + * + *
{@link imgui.extension.imguizmo.flag.Operation#ROTATE}{@link imgui.extension.imguizmo.flag.Operation#SCALE}{@link imgui.extension.imguizmo.flag.Operation#TRANSLATE}
+ * + * @param operation target + */ + public static boolean isOver(final int operation) { + return nIsOver(operation); + } + + private static native void nSetGizmoSizeClipSpace(float value); /* + ImGuizmo::SetGizmoSizeClipSpace(value); + */ + + private static native void nAllowAxisFlip(boolean value); /* + ImGuizmo::AllowAxisFlip(value); + */ + + /** + * This will update the current axis flip value + */ + public static void setAllowAxisFlip(final boolean value) { + nAllowAxisFlip(value); + } +} diff --git a/imgui-binding/src/main/java/imgui/extension/imguizmo/flag/Mode.java b/imgui-binding/src/main/java/imgui/extension/imguizmo/flag/Mode.java new file mode 100644 index 0000000..1bb345e --- /dev/null +++ b/imgui-binding/src/main/java/imgui/extension/imguizmo/flag/Mode.java @@ -0,0 +1,9 @@ +package imgui.extension.imguizmo.flag; + +public final class Mode { + private Mode() { + } + + public static final int LOCAL = 0; + public static final int WORLD = 1; +} diff --git a/imgui-binding/src/main/java/imgui/extension/imguizmo/flag/Operation.java b/imgui-binding/src/main/java/imgui/extension/imguizmo/flag/Operation.java new file mode 100644 index 0000000..7367554 --- /dev/null +++ b/imgui-binding/src/main/java/imgui/extension/imguizmo/flag/Operation.java @@ -0,0 +1,64 @@ +package imgui.extension.imguizmo.flag; + +/** + * Needs view and projection matrices. + * Matrix parameter is the source matrix (where will be gizmo be drawn) and might be transformed by the function. Return deltaMatrix is optional. + * Translation is applied in world space. + */ +public final class Operation { + private Operation() { + } + + /** + * Translating X axis + */ + public static final int TRANSLATE_X = 1; + /** + * Translating Y axis + */ + public static final int TRANSLATE_Y = 1 << 1; + /** + * Translating Z axis + */ + public static final int TRANSLATE_Z = 1 << 2; + /** + * Rotating X axis + */ + public static final int ROTATE_X = 1 << 3; + /** + * Rotating Y axis + */ + public static final int ROTATE_Y = 1 << 4; + /** + * Rotating Z axis + */ + public static final int ROTATE_Z = 1 << 5; + /** + * Rotating screen + */ + public static final int ROTATE_SCREEN = 1 << 6; + /** + * Scaling X axis + */ + public static final int SCALE_X = 1 << 7; + /** + * Scaling Y axis + */ + public static final int SCALE_Y = 1 << 8; + /** + * Scaling Z axis + */ + public static final int SCALE_Z = 1 << 9; + /** + * Translating all axis + */ + public static final int TRANSLATE = TRANSLATE_X | TRANSLATE_Y | TRANSLATE_Z; + /** + * Rotating all axis + */ + public static final int ROTATE = ROTATE_X | ROTATE_Y | ROTATE_Z | ROTATE_SCREEN; + /** + * Scaling all axis + */ + public static final int SCALE = SCALE_X | SCALE_Y | SCALE_Z; +} diff --git a/imgui-binding/src/main/native/_imguizmo.h b/imgui-binding/src/main/native/_imguizmo.h new file mode 100644 index 0000000..2ccefc9 --- /dev/null +++ b/imgui-binding/src/main/native/_imguizmo.h @@ -0,0 +1,4 @@ +#pragma once + +#include "_common.h" +#include "ImGuizmo.h" diff --git a/include/imguizmo b/include/imguizmo new file mode 160000 index 0000000..f7bbbe3 --- /dev/null +++ b/include/imguizmo @@ -0,0 +1 @@ +Subproject commit f7bbbe39971d9d45816417a70e9b53a0f698c56e