added supporting window icons for LWJGL3
This commit is contained in:
parent
903522de91
commit
190f30afe5
@ -43,19 +43,69 @@ import com.jme3.system.AppSettings;
|
||||
import com.jme3.system.JmeContext;
|
||||
import com.jme3.system.JmeSystem;
|
||||
import com.jme3.system.NanoTimer;
|
||||
import org.lwjgl.glfw.*;
|
||||
import com.jme3.util.BufferUtils;
|
||||
|
||||
import org.lwjgl.Version;
|
||||
import org.lwjgl.glfw.GLFWErrorCallback;
|
||||
import org.lwjgl.glfw.GLFWImage;
|
||||
import org.lwjgl.glfw.GLFWVidMode;
|
||||
import org.lwjgl.glfw.GLFWWindowFocusCallback;
|
||||
import org.lwjgl.glfw.GLFWWindowSizeCallback;
|
||||
import org.lwjgl.stb.STBImage;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.lwjgl.Version;
|
||||
|
||||
import static org.lwjgl.glfw.GLFW.*;
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_ALPHA_BITS;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_BLUE_BITS;
|
||||
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_DEPTH_BITS;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_DOUBLEBUFFER;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_FALSE;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_GREEN_BITS;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_OPENGL_CORE_PROFILE;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_OPENGL_DEBUG_CONTEXT;
|
||||
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_RED_BITS;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_REFRESH_RATE;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_RESIZABLE;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_SAMPLES;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_SRGB_CAPABLE;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_STENCIL_BITS;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_STEREO;
|
||||
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.glfwGetPrimaryMonitor;
|
||||
import static org.lwjgl.glfw.GLFW.glfwGetVideoMode;
|
||||
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.glfwSetWindowFocusCallback;
|
||||
import static org.lwjgl.glfw.GLFW.glfwSetWindowIcon;
|
||||
import static org.lwjgl.glfw.GLFW.glfwSetWindowPos;
|
||||
import static org.lwjgl.glfw.GLFW.glfwSetWindowSizeCallback;
|
||||
import static org.lwjgl.glfw.GLFW.glfwSetWindowTitle;
|
||||
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.glfwWindowHint;
|
||||
import static org.lwjgl.glfw.GLFW.glfwWindowShouldClose;
|
||||
import static org.lwjgl.opengl.GL11.GL_FALSE;
|
||||
import static org.lwjgl.opengl.GL11.GL_TRUE;
|
||||
import static org.lwjgl.system.MemoryUtil.NULL;
|
||||
|
||||
/**
|
||||
@ -67,15 +117,10 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(LwjglWindow.class.getName());
|
||||
|
||||
protected AtomicBoolean needClose = new AtomicBoolean(false);
|
||||
protected final AtomicBoolean needClose = new AtomicBoolean(false);
|
||||
protected final AtomicBoolean needRestart = new AtomicBoolean(false);
|
||||
protected boolean wasActive = false;
|
||||
protected boolean autoFlush = true;
|
||||
protected boolean allowSwapBuffers = false;
|
||||
private long window = NULL;
|
||||
|
||||
private final JmeContext.Type type;
|
||||
private int frameRateLimit = -1;
|
||||
private double frameSleepTime;
|
||||
|
||||
private GLFWErrorCallback errorCallback;
|
||||
private GLFWWindowSizeCallback windowSizeCallback;
|
||||
@ -83,6 +128,14 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
||||
|
||||
private Thread mainThread;
|
||||
|
||||
private double frameSleepTime;
|
||||
private long window = NULL;
|
||||
private int frameRateLimit = -1;
|
||||
|
||||
protected boolean wasActive = false;
|
||||
protected boolean autoFlush = true;
|
||||
protected boolean allowSwapBuffers = false;
|
||||
|
||||
public LwjglWindow(final JmeContext.Type type) {
|
||||
if (!JmeContext.Type.Display.equals(type) && !JmeContext.Type.OffscreenSurface.equals(type) && !JmeContext.Type.Canvas.equals(type)) {
|
||||
throw new IllegalArgumentException("Unsupported type '" + type.name() + "' provided");
|
||||
@ -171,7 +224,7 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
||||
glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
|
||||
glfwWindowHint(GLFW_RESIZABLE, settings.isResizable() ? GLFW_TRUE : GLFW_FALSE);
|
||||
|
||||
//glfwWindowHint(GLFW_DOUBLE_BUFFER, GLFW_TRUE);
|
||||
glfwWindowHint(GLFW_DOUBLEBUFFER, GLFW_TRUE);
|
||||
glfwWindowHint(GLFW_DEPTH_BITS, settings.getDepthBits());
|
||||
glfwWindowHint(GLFW_STENCIL_BITS, settings.getStencilBits());
|
||||
glfwWindowHint(GLFW_SAMPLES, settings.getSamples());
|
||||
@ -271,12 +324,91 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
||||
glfwSwapInterval(0);
|
||||
}
|
||||
|
||||
final Object[] icons = settings.getIcons();
|
||||
|
||||
if (icons != null) {
|
||||
|
||||
final GLFWImage[] images = imagesToGLFWImages(icons);
|
||||
final GLFWImage.Buffer iconSet = GLFWImage.malloc(images.length);
|
||||
|
||||
for (int i = images.length - 1; i >= 0; i--) {
|
||||
final GLFWImage image = images[i];
|
||||
iconSet.put(i, image);
|
||||
}
|
||||
|
||||
glfwSetWindowIcon(window, iconSet);
|
||||
|
||||
iconSet.free();
|
||||
|
||||
for (final GLFWImage image : images) {
|
||||
image.free();
|
||||
}
|
||||
}
|
||||
|
||||
glfwShowWindow(window);
|
||||
|
||||
allowSwapBuffers = settings.isSwapBuffers();
|
||||
}
|
||||
|
||||
// TODO: When GLFW 3.2 is released and included in LWJGL 3.x then we should hopefully be able to set the window icon.
|
||||
/**
|
||||
* Convert array of images to array of {@link GLFWImage}.
|
||||
*/
|
||||
private GLFWImage[] imagesToGLFWImages(final Object[] images) {
|
||||
|
||||
final GLFWImage[] out = new GLFWImage[images.length];
|
||||
|
||||
for (int i = 0; i < images.length; i++) {
|
||||
final BufferedImage image = (BufferedImage) images[i];
|
||||
out[i] = imageToGLFWImage(image);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the {@link BufferedImage} to the {@link GLFWImage}.
|
||||
*/
|
||||
private GLFWImage imageToGLFWImage(BufferedImage image) {
|
||||
|
||||
if (image.getType() != BufferedImage.TYPE_INT_ARGB_PRE) {
|
||||
|
||||
final BufferedImage convertedImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB_PRE);
|
||||
final Graphics2D graphics = convertedImage.createGraphics();
|
||||
|
||||
final int targetWidth = image.getWidth();
|
||||
final int targetHeight = image.getHeight();
|
||||
|
||||
graphics.drawImage(image, 0, 0, targetWidth, targetHeight, null);
|
||||
graphics.dispose();
|
||||
|
||||
image = convertedImage;
|
||||
}
|
||||
|
||||
final IntBuffer w = BufferUtils.createIntBuffer(1);
|
||||
final IntBuffer h = BufferUtils.createIntBuffer(1);
|
||||
final IntBuffer comp = BufferUtils.createIntBuffer(1);
|
||||
|
||||
final ByteArrayOutputStream bout = new ByteArrayOutputStream(4096);
|
||||
try {
|
||||
ImageIO.write(image, "png", bout);
|
||||
} catch (final IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
final byte[] bytes = bout.toByteArray();
|
||||
|
||||
final ByteBuffer buffer = BufferUtils.createByteBuffer(bytes.length);
|
||||
buffer.put(bytes);
|
||||
buffer.flip();
|
||||
|
||||
final ByteBuffer pixels = STBImage.stbi_load_from_memory(buffer, h, w, comp, 4);
|
||||
|
||||
BufferUtils.destroyDirectBuffer(buffer);
|
||||
|
||||
final GLFWImage result = GLFWImage.create();
|
||||
result.set(w.get(0), h.get(0), pixels);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -307,7 +439,7 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
||||
glfwDestroyWindow(window);
|
||||
window = NULL;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
} catch (final Exception ex) {
|
||||
listener.handleError("Failed to destroy context", ex);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user