279 lines
7.8 KiB
Java
279 lines
7.8 KiB
Java
package com.gnarly.engine.display;
|
|
|
|
import static org.lwjgl.glfw.GLFW.*;
|
|
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_PROFILE;
|
|
import static org.lwjgl.glfw.GLFW.GLFW_PRESS;
|
|
import static org.lwjgl.glfw.GLFW.GLFW_RESIZABLE;
|
|
import static org.lwjgl.glfw.GLFW.GLFW_TRUE;
|
|
import static org.lwjgl.glfw.GLFW.glfwCreateWindow;
|
|
import static org.lwjgl.glfw.GLFW.glfwGetCursorPos;
|
|
import static org.lwjgl.glfw.GLFW.glfwGetKey;
|
|
import static org.lwjgl.glfw.GLFW.glfwGetMouseButton;
|
|
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.glfwSetScrollCallback;
|
|
import static org.lwjgl.glfw.GLFW.glfwSetWindowPos;
|
|
import static org.lwjgl.glfw.GLFW.glfwSetWindowShouldClose;
|
|
import static org.lwjgl.glfw.GLFW.glfwSetWindowSizeCallback;
|
|
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.GL.createCapabilities;
|
|
import static org.lwjgl.opengl.GL11.GL_BLEND;
|
|
import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
|
|
import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT;
|
|
import static org.lwjgl.opengl.GL11.GL_DEPTH_TEST;
|
|
import static org.lwjgl.opengl.GL11.GL_ONE_MINUS_SRC_ALPHA;
|
|
import static org.lwjgl.opengl.GL11.GL_SRC_ALPHA;
|
|
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
|
|
import static org.lwjgl.opengl.GL11.glBlendFunc;
|
|
import static org.lwjgl.opengl.GL11.glClear;
|
|
import static org.lwjgl.opengl.GL11.glClearColor;
|
|
import static org.lwjgl.opengl.GL11.glEnable;
|
|
import static org.lwjgl.opengl.GL11.glViewport;
|
|
import static org.lwjgl.opengl.GL30.*;
|
|
import static org.lwjgl.system.MemoryUtil.NULL;
|
|
|
|
import org.joml.Vector3f;
|
|
import org.lwjgl.glfw.GLFWCharCallback;
|
|
import org.lwjgl.glfw.GLFWCharModsCallback;
|
|
import org.lwjgl.glfw.GLFWErrorCallback;
|
|
import org.lwjgl.glfw.GLFWKeyCallback;
|
|
import org.lwjgl.glfw.GLFWScrollCallback;
|
|
import org.lwjgl.glfw.GLFWVidMode;
|
|
import org.lwjgl.glfw.GLFWWindowSizeCallback;
|
|
|
|
public class Window {
|
|
|
|
public static final byte
|
|
UNPRESSED = 0,
|
|
RELEASED = 1,
|
|
PRESSED = 2,
|
|
HELD = 3;
|
|
|
|
private long window;
|
|
|
|
private GLFWVidMode vidMode;
|
|
|
|
private int xOff, yOff, vWidth, vHeight;
|
|
|
|
private double scrollX, scrollY;
|
|
|
|
private StringBuilder input;
|
|
|
|
private boolean resized;
|
|
|
|
byte[] keys = new byte[GLFW_KEY_LAST];
|
|
|
|
public Window(int width, int height, boolean vSync, boolean resizable, String title) {
|
|
init(width, height, vSync, resizable, title);
|
|
}
|
|
|
|
public Window(boolean vSync) {
|
|
init(0, 0, vSync, false, null);
|
|
}
|
|
|
|
private void init(int width, int height, boolean vSync, boolean resizable, String title) {
|
|
glfwSetErrorCallback(GLFWErrorCallback.createPrint(System.err));
|
|
|
|
if(!glfwInit()) {
|
|
System.err.println("GLFW failed to initialize!");
|
|
System.exit(-1);
|
|
}
|
|
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
|
|
|
glfwWindowHint(GLFW_RESIZABLE, resizable ? GLFW_TRUE : GLFW_FALSE);
|
|
|
|
vidMode = glfwGetVideoMode(glfwGetPrimaryMonitor());
|
|
if(width == 0 || height == 0 || width >= vidMode.width() || height >= vidMode.height()) {
|
|
width = vidMode.width();
|
|
height = vidMode.height();
|
|
window = glfwCreateWindow(width, height, "", glfwGetPrimaryMonitor(), NULL);
|
|
}
|
|
else {
|
|
window = glfwCreateWindow(width, height, title, NULL, NULL);
|
|
glfwSetWindowPos(window, (vidMode.width() - width) / 2, (vidMode.height() - height) / 2);
|
|
}
|
|
|
|
glfwMakeContextCurrent(window);
|
|
createCapabilities();
|
|
|
|
glfwSwapInterval(vSync ? 1 : 0);
|
|
|
|
glfwSetWindowSizeCallback(window, new GLFWWindowSizeCallback() {
|
|
public void invoke(long window, int width, int height) {
|
|
resized = true;
|
|
glViewport(0, 0, width, height);
|
|
}
|
|
});
|
|
|
|
glfwSetScrollCallback(window, new GLFWScrollCallback() {
|
|
public void invoke(long window, double x, double y) {
|
|
scrollX = x;
|
|
scrollY = y;
|
|
}
|
|
});
|
|
|
|
input = new StringBuilder();
|
|
glfwSetCharModsCallback(window, new GLFWCharModsCallback() {
|
|
public void invoke(long window, int key, int mods) {
|
|
input.append((char) key);
|
|
}
|
|
});
|
|
glfwSetKeyCallback(window, new GLFWKeyCallback() {
|
|
public void invoke(long window, int key, int scancode, int action, int mods) {
|
|
if(action != GLFW_RELEASE) {
|
|
if(glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) != GLFW_PRESS && glfwGetKey(window, GLFW_KEY_RIGHT_CONTROL) != GLFW_PRESS && glfwGetKey(window, GLFW_KEY_LEFT_ALT) != GLFW_PRESS && glfwGetKey(window, GLFW_KEY_RIGHT_ALT) != GLFW_PRESS) {
|
|
switch (key) {
|
|
case GLFW_KEY_ENTER:
|
|
input.append((char) 10);
|
|
break;
|
|
case GLFW_KEY_BACKSPACE:
|
|
input.append((char) 8);
|
|
break;
|
|
case GLFW_KEY_DELETE:
|
|
input.append((char) 127);
|
|
break;
|
|
case GLFW_KEY_LEFT:
|
|
input.append((char) 1);
|
|
break;
|
|
case GLFW_KEY_RIGHT:
|
|
input.append((char) 2);
|
|
break;
|
|
case GLFW_KEY_UP:
|
|
input.append((char) 3);
|
|
break;
|
|
case GLFW_KEY_DOWN:
|
|
input.append((char) 4);
|
|
break;
|
|
case GLFW_KEY_TAB:
|
|
input.append((char) 9);
|
|
break;
|
|
}
|
|
}
|
|
if(keys[key] < PRESSED)
|
|
keys[key] = PRESSED;
|
|
else
|
|
keys[key] = HELD;
|
|
}
|
|
else {
|
|
if(keys[key] > RELEASED)
|
|
keys[key] = RELEASED;
|
|
else
|
|
keys[key] = UNPRESSED;
|
|
}
|
|
}
|
|
});
|
|
|
|
float vWidth = 0, vHeight = 0;
|
|
while(vWidth < vidMode.width() && vHeight < vidMode.height()) {
|
|
vWidth += 1;
|
|
vHeight += 9 /16f;
|
|
}
|
|
|
|
xOff = (int) ((vidMode.width() - vWidth) / 2);
|
|
yOff = (int) ((vidMode.height() - vHeight) / 2);
|
|
this.vWidth = (int) vWidth;
|
|
this.vHeight = (int) vHeight;
|
|
bind();
|
|
|
|
glClearColor(0, 0, 0, 1);
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
glEnable(GL_BLEND);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
}
|
|
|
|
public void update() {
|
|
for (int i = 0; i < keys.length; i++) {
|
|
if(keys[i] == PRESSED)
|
|
++keys[i];
|
|
else if(keys[i] == RELEASED)
|
|
--keys[i];
|
|
}
|
|
scrollX = 0;
|
|
scrollY = 0;
|
|
resized = false;
|
|
input.delete(0, input.length());
|
|
glfwPollEvents();
|
|
}
|
|
|
|
public void clear() {
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
}
|
|
|
|
public void swap() {
|
|
glfwSwapBuffers(window);
|
|
}
|
|
|
|
public void setVSync(boolean vSync) {
|
|
glfwSwapInterval(vSync ? 1 : 0);
|
|
}
|
|
|
|
public void close() {
|
|
glfwSetWindowShouldClose(window, true);
|
|
}
|
|
|
|
public boolean shouldClose() {
|
|
return glfwWindowShouldClose(window);
|
|
}
|
|
|
|
public String getInput() {
|
|
return input.toString();
|
|
}
|
|
|
|
public byte getKey(int keyCode) {
|
|
return keys[keyCode];
|
|
}
|
|
|
|
public Vector3f getMouseCoords(Camera camera) {
|
|
double[] x = new double[1], y = new double[1];
|
|
glfwGetCursorPos(window, x, y);
|
|
Vector3f ret = new Vector3f((float) x[0] - xOff, (float) y[0] - yOff, 0);
|
|
ret.mul(camera.getWidth() / vWidth, camera.getHeight() / vHeight, 1);
|
|
return ret;
|
|
}
|
|
|
|
public boolean mousePressed(int button) {
|
|
return glfwGetMouseButton(window, button) == GLFW_PRESS;
|
|
}
|
|
|
|
public int getWidth() {
|
|
return vWidth;
|
|
}
|
|
|
|
public int getHeight() {
|
|
return vHeight;
|
|
}
|
|
|
|
public boolean wasResized() {
|
|
return resized;
|
|
}
|
|
|
|
public float getScrollX() {
|
|
return (float) scrollX;
|
|
}
|
|
|
|
public float getScrollY() {
|
|
return (float) scrollY;
|
|
}
|
|
|
|
public void bind() {
|
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
glViewport(xOff, yOff, vWidth, vHeight);
|
|
}
|
|
}
|