[API] Up GLFW impl

This commit is contained in:
SpaiR committed 2021-12-27 11:30:16 +02:00
1 parent 384e24a6c5
commit 0c37ac6dfd
3 files changed
+102 -27

No files matched your search

@@ -4,8 +4,8 @@ package imgui.app;
* Application class from which ImGui applications extend. * Application class from which ImGui applications extend.
* Serves as an abstraction layer to hide all low-level details about window creation and rendering routine. * Serves as an abstraction layer to hide all low-level details about window creation and rendering routine.
* *
* <p><h3>Life-cycle</h3> * <h3>Life-cycle</h3>
* The entry point for ImGui applications is the Application class and {@link #launch(Application)} method. * <p>The entry point for ImGui applications is the Application class and {@link #launch(Application)} method.
* It initializes application instance and starts the main application loop. * It initializes application instance and starts the main application loop.
* *
* <ol> * <ol>
@@ -25,8 +25,8 @@ package imgui.app;
* Instead of creating widgets and adding listeners to them we have an application loop where everything is handled right away. * Instead of creating widgets and adding listeners to them we have an application loop where everything is handled right away.
* Read more about Immediate GUI mode to understand that paradigm better. * Read more about Immediate GUI mode to understand that paradigm better.
* *
* <p><h3>Example</h3> * <h3>Example</h3>
* The simplest application example could be done in the next way: * <p>The simplest application example could be done in the next way:
* *
* <pre> * <pre>
* import imgui.ImGui; * import imgui.ImGui;
@@ -44,10 +44,11 @@ package imgui.app;
* } * }
* </pre> * </pre>
* *
* <p>As its said, {@link #process()} method is meant to be overridden. All your application logic should go there. * <p>
* As its said, {@link #process()} method is meant to be overridden. All your application logic should go there.
* *
* <p><h3>Threading</h3> * <h3>Threading</h3>
* Unlike other Java applications, ImGui is about "one thread for everything". You still can use multi-threading, but be careful. * <p>Unlike other Java applications, ImGui is about "one thread for everything". You still can use multi-threading, but be careful.
* For example, large list of computations could be separated between application ticks. {@link #process()} method is called constantly. * For example, large list of computations could be separated between application ticks. {@link #process()} method is called constantly.
* Use that wisely and remember that all GUI should be in the main thread. * Use that wisely and remember that all GUI should be in the main thread.
*/ */
@@ -111,6 +111,8 @@ public final class ImGuiImplGl3 {
* </pre> * </pre>
* <p> * <p>
* If the argument is null, then a "#version 130" string will be used by default. * If the argument is null, then a "#version 130" string will be used by default.
*
* @param glslVersion string with the version of the GLSL
*/ */
public void init(final String glslVersion) { public void init(final String glslVersion) {
readGlVersion(); readGlVersion();
@@ -131,6 +133,8 @@ public final class ImGuiImplGl3 {
/** /**
* Method to render {@link ImDrawData} into current OpenGL context. * Method to render {@link ImDrawData} into current OpenGL context.
*
* @param drawData draw data to render
*/ */
public void renderDrawData(final ImDrawData drawData) { public void renderDrawData(final ImDrawData drawData) {
if (drawData.getCmdListsCount() <= 0) { if (drawData.getCmdListsCount() <= 0) {
@@ -22,6 +22,7 @@ import imgui.flag.ImGuiNavInput;
import imgui.flag.ImGuiViewportFlags; import imgui.flag.ImGuiViewportFlags;
import org.lwjgl.PointerBuffer; import org.lwjgl.PointerBuffer;
import org.lwjgl.glfw.GLFWCharCallback; import org.lwjgl.glfw.GLFWCharCallback;
import org.lwjgl.glfw.GLFWCursorEnterCallback;
import org.lwjgl.glfw.GLFWErrorCallback; import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWKeyCallback; import org.lwjgl.glfw.GLFWKeyCallback;
import org.lwjgl.glfw.GLFWMonitorCallback; import org.lwjgl.glfw.GLFWMonitorCallback;
@@ -29,6 +30,7 @@ import org.lwjgl.glfw.GLFWMouseButtonCallback;
import org.lwjgl.glfw.GLFWNativeWin32; import org.lwjgl.glfw.GLFWNativeWin32;
import org.lwjgl.glfw.GLFWScrollCallback; import org.lwjgl.glfw.GLFWScrollCallback;
import org.lwjgl.glfw.GLFWVidMode; import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.glfw.GLFWWindowFocusCallback;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.FloatBuffer; import java.nio.FloatBuffer;
@@ -93,19 +95,27 @@ public class ImGuiImplGlfw {
private final float[] monitorContentScaleY = new float[1]; private final float[] monitorContentScaleY = new float[1];
// GLFW callbacks // GLFW callbacks
private GLFWWindowFocusCallback prevUserCallbackWindowFocus = null;
private GLFWMouseButtonCallback prevUserCallbackMouseButton = null; private GLFWMouseButtonCallback prevUserCallbackMouseButton = null;
private GLFWScrollCallback prevUserCallbackScroll = null; private GLFWScrollCallback prevUserCallbackScroll = null;
private GLFWKeyCallback prevUserCallbackKey = null; private GLFWKeyCallback prevUserCallbackKey = null;
private GLFWCharCallback prevUserCallbackChar = null; private GLFWCharCallback prevUserCallbackChar = null;
private GLFWMonitorCallback prevUserCallbackMonitor = null; private GLFWMonitorCallback prevUserCallbackMonitor = null;
private GLFWCursorEnterCallback prevUserCallbackCursorEnter = null;
// Internal data // Internal data
private boolean callbacksInstalled = false; private boolean callbacksInstalled = false;
private boolean wantUpdateMonitors = true; private boolean wantUpdateMonitors = true;
private double time = 0.0; private double time = 0.0;
private long mouseWindowPtr;
/** /**
* Method to set the {@link GLFWMouseButtonCallback}. * Method to set the {@link GLFWMouseButtonCallback}.
*
* @param windowId pointer to the window
* @param button clicked mouse button
* @param action click action type
* @param mods click modifiers
*/ */
public void mouseButtonCallback(final long windowId, final int button, final int action, final int mods) { public void mouseButtonCallback(final long windowId, final int button, final int action, final int mods) {
if (prevUserCallbackMouseButton != null && windowId == windowPtr) { if (prevUserCallbackMouseButton != null && windowId == windowPtr) {
@@ -119,6 +129,10 @@ public class ImGuiImplGlfw {
/** /**
* Method to set the {@link GLFWScrollCallback}. * Method to set the {@link GLFWScrollCallback}.
*
* @param windowId pointer to the window
* @param xOffset scroll offset by x-axis
* @param yOffset scroll offset by y-axis
*/ */
public void scrollCallback(final long windowId, final double xOffset, final double yOffset) { public void scrollCallback(final long windowId, final double xOffset, final double yOffset) {
if (prevUserCallbackScroll != null && windowId == windowPtr) { if (prevUserCallbackScroll != null && windowId == windowPtr) {
@@ -132,6 +146,12 @@ public class ImGuiImplGlfw {
/** /**
* Method to set the {@link GLFWKeyCallback}. * Method to set the {@link GLFWKeyCallback}.
*
* @param windowId pointer to the window
* @param key pressed key
* @param scancode key scancode
* @param action press action
* @param mods press modifiers
*/ */
public void keyCallback(final long windowId, final int key, final int scancode, final int action, final int mods) { public void keyCallback(final long windowId, final int key, final int scancode, final int action, final int mods) {
if (prevUserCallbackKey != null && windowId == windowPtr) { if (prevUserCallbackKey != null && windowId == windowPtr) {
@@ -156,8 +176,44 @@ public class ImGuiImplGlfw {
io.setKeySuper(io.getKeysDown(GLFW_KEY_LEFT_SUPER) || io.getKeysDown(GLFW_KEY_RIGHT_SUPER)); io.setKeySuper(io.getKeysDown(GLFW_KEY_LEFT_SUPER) || io.getKeysDown(GLFW_KEY_RIGHT_SUPER));
} }
/**
* Method to set the {@link GLFWWindowFocusCallback}.
*
* @param windowId pointer to the window
* @param focused is window focused
*/
public void windowFocusCallback(final long windowId, final boolean focused) {
if (prevUserCallbackWindowFocus != null && windowId == windowPtr) {
prevUserCallbackWindowFocus.invoke(windowId, focused);
}
ImGui.getIO().addFocusEvent(focused);
}
/**
* Method to set the {@link GLFWCursorEnterCallback}.
*
* @param windowId pointer to the window
* @param entered is cursor entered
*/
public void cursorEnterCallback(final long windowId, final boolean entered) {
if (prevUserCallbackCursorEnter != null && windowId == windowPtr) {
prevUserCallbackCursorEnter.invoke(windowId, entered);
}
if (entered) {
mouseWindowPtr = windowId;
}
if (!entered && mouseWindowPtr == windowId) {
mouseWindowPtr = 0;
}
}
/** /**
* Method to set the {@link GLFWCharCallback}. * Method to set the {@link GLFWCharCallback}.
*
* @param windowId pointer to the window
* @param c pressed char
*/ */
public void charCallback(final long windowId, final int c) { public void charCallback(final long windowId, final int c) {
if (prevUserCallbackChar != null && windowId == windowPtr) { if (prevUserCallbackChar != null && windowId == windowPtr) {
@@ -170,6 +226,9 @@ public class ImGuiImplGlfw {
/** /**
* Method to set the {@link GLFWMonitorCallback}. * Method to set the {@link GLFWMonitorCallback}.
*
* @param windowId pointer to the window
* @param event monitor event type (ignored)
*/ */
public void monitorCallback(final long windowId, final int event) { public void monitorCallback(final long windowId, final int event) {
wantUpdateMonitors = true; wantUpdateMonitors = true;
@@ -179,6 +238,10 @@ public class ImGuiImplGlfw {
* Method to do an initialization of the {@link ImGuiImplGlfw} state. It SHOULD be called before calling the {@link ImGuiImplGlfw#newFrame()} method. * Method to do an initialization of the {@link ImGuiImplGlfw} state. It SHOULD be called before calling the {@link ImGuiImplGlfw#newFrame()} method.
* <p> * <p>
* Method takes two arguments, which should be a valid GLFW window pointer and a boolean indicating whether or not to install callbacks. * Method takes two arguments, which should be a valid GLFW window pointer and a boolean indicating whether or not to install callbacks.
*
* @param windowId pointer to the window
* @param installCallbacks should window callbacks be installed
* @return true if everything initialized
*/ */
public boolean init(final long windowId, final boolean installCallbacks) { public boolean init(final long windowId, final boolean installCallbacks) {
this.windowPtr = windowId; this.windowPtr = windowId;
@@ -247,6 +310,8 @@ public class ImGuiImplGlfw {
if (installCallbacks) { if (installCallbacks) {
callbacksInstalled = true; callbacksInstalled = true;
prevUserCallbackWindowFocus = glfwSetWindowFocusCallback(windowId, this::windowFocusCallback);
prevUserCallbackCursorEnter = glfwSetCursorEnterCallback(windowId, this::cursorEnterCallback);
prevUserCallbackMouseButton = glfwSetMouseButtonCallback(windowId, this::mouseButtonCallback); prevUserCallbackMouseButton = glfwSetMouseButtonCallback(windowId, this::mouseButtonCallback);
prevUserCallbackScroll = glfwSetScrollCallback(windowId, this::scrollCallback); prevUserCallbackScroll = glfwSetScrollCallback(windowId, this::scrollCallback);
prevUserCallbackKey = glfwSetKeyCallback(windowId, this::keyCallback); prevUserCallbackKey = glfwSetKeyCallback(windowId, this::keyCallback);
@@ -278,11 +343,6 @@ public class ImGuiImplGlfw {
*/ */
public void newFrame() { public void newFrame() {
final ImGuiIO io = ImGui.getIO(); final ImGuiIO io = ImGui.getIO();
if (!io.getFonts().isBuilt()) {
throw new IllegalStateException(
"Font atlas not built! It is generally built by the renderer back-end. Missing call to renderer init() method? e.g. ImGuiImplGl3.init()"
);
}
glfwGetWindowSize(windowPtr, winWidth, winHeight); glfwGetWindowSize(windowPtr, winWidth, winHeight);
glfwGetFramebufferSize(windowPtr, fbWidth, fbHeight); glfwGetFramebufferSize(windowPtr, fbWidth, fbHeight);
@@ -313,6 +373,8 @@ public class ImGuiImplGlfw {
shutdownPlatformInterface(); shutdownPlatformInterface();
if (callbacksInstalled) { if (callbacksInstalled) {
glfwSetWindowFocusCallback(windowPtr, prevUserCallbackWindowFocus);
glfwSetCursorEnterCallback(windowPtr, prevUserCallbackCursorEnter);
glfwSetMouseButtonCallback(windowPtr, prevUserCallbackMouseButton); glfwSetMouseButtonCallback(windowPtr, prevUserCallbackMouseButton);
glfwSetScrollCallback(windowPtr, prevUserCallbackScroll); glfwSetScrollCallback(windowPtr, prevUserCallbackScroll);
glfwSetKeyCallback(windowPtr, prevUserCallbackKey); glfwSetKeyCallback(windowPtr, prevUserCallbackKey);
@@ -362,26 +424,34 @@ public class ImGuiImplGlfw {
final boolean focused = glfwGetWindowAttrib(windowPtr, GLFW_FOCUSED) != 0; final boolean focused = glfwGetWindowAttrib(windowPtr, GLFW_FOCUSED) != 0;
final long mouseWindowPtr = (this.mouseWindowPtr == windowPtr || focused) ? windowPtr : 0;
// Update mouse buttons
if (focused) { if (focused) {
if (io.getWantSetMousePos()) {
glfwSetCursorPos(windowPtr, mousePosBackup.x - viewport.getPosX(), mousePosBackup.y - viewport.getPosY());
} else {
glfwGetCursorPos(windowPtr, mouseX, mouseY);
if (io.hasConfigFlags(ImGuiConfigFlags.ViewportsEnable)) {
// Multi-viewport mode: mouse position in OS absolute coordinates (io.MousePos is (0,0) when the mouse is on the upper-left of the primary monitor)
glfwGetWindowPos(windowPtr, windowX, windowY);
io.setMousePos((float) mouseX[0] + windowX[0], (float) mouseY[0] + windowY[0]);
} else {
// Single viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is on the upper-left corner of the app window)
io.setMousePos((float) mouseX[0], (float) mouseY[0]);
}
}
for (int i = 0; i < ImGuiMouseButton.COUNT; i++) { for (int i = 0; i < ImGuiMouseButton.COUNT; i++) {
io.setMouseDown(i, glfwGetMouseButton(windowPtr, i) != 0); io.setMouseDown(i, glfwGetMouseButton(windowPtr, i) != 0);
} }
} }
// Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
// (When multi-viewports are enabled, all Dear ImGui positions are same as OS positions)
if (io.getWantSetMousePos() && focused) {
glfwSetCursorPos(windowPtr, mousePosBackup.x - viewport.getPosX(), mousePosBackup.y - viewport.getPosY());
}
// Set Dear ImGui mouse position from OS position
if (mouseWindowPtr != 0) {
glfwGetCursorPos(mouseWindowPtr, mouseX, mouseY);
if (io.hasConfigFlags(ImGuiConfigFlags.ViewportsEnable)) {
// Multi-viewport mode: mouse position in OS absolute coordinates (io.MousePos is (0,0) when the mouse is on the upper-left of the primary monitor)
glfwGetWindowPos(windowPtr, windowX, windowY);
io.setMousePos((float) mouseX[0] + windowX[0], (float) mouseY[0] + windowY[0]);
} else {
// Single viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is on the upper-left corner of the app window)
io.setMousePos((float) mouseX[0], (float) mouseY[0]);
}
}
} }
} }