Created
November 21, 2014 00:42
-
-
Save Unh0lyTigg/cd301e502094b287d4ad to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import static org.lwjgl.opengl.GL11.*; | |
import static org.lwjgl.system.MemoryUtil.NULL; | |
import static org.lwjgl.system.glfw.GLFW.*; | |
import java.awt.Dimension; | |
import java.awt.GraphicsConfiguration; | |
import java.awt.GraphicsDevice; | |
import java.awt.GraphicsEnvironment; | |
import java.awt.Point; | |
import java.nio.ByteBuffer; | |
//import java.io.File; | |
import java.util.ArrayList; | |
import java.util.List; | |
import org.lwjgl.PointerBuffer; | |
import org.lwjgl.opengl.GL; | |
import org.lwjgl.opengl.GLContext; | |
//import org.lwjgl.system.MemoryUtil; | |
import org.lwjgl.system.glfw.ErrorCallback; | |
import org.lwjgl.system.glfw.GLFWvidmode; | |
import org.lwjgl.system.glfw.WindowCallback; | |
import org.lwjgl.system.glfw.WindowCallbackAdapter; | |
public class Window { | |
private long windowId; | |
private String title; | |
private Callback callback = new Callback(this); | |
private int width, height; | |
private int x, y; | |
private boolean visible = false; | |
private static boolean isSetup = false; | |
public static void setupGLFW() { | |
if (isSetup) | |
return; | |
glfwSetErrorCallback(ErrorCallback.Util.getDefault()); | |
if (glfwInit() != GL_TRUE) | |
throw new IllegalStateException("Unable to initialize GLFW"); | |
glfwDefaultWindowHints(); | |
glfwWindowHint(GLFW_VISIBLE, GL_FALSE); | |
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE); | |
} | |
public static void setupGlOrtho(int width, int height) { | |
if (GL.getCurrent() == null) | |
return; | |
glViewport(0, 0, width, height); | |
glMatrixMode(GL_PROJECTION); | |
glLoadIdentity(); | |
glOrtho(0, width, height, 0, 1, -1); | |
glMatrixMode(GL_MODELVIEW); | |
} | |
public Window(String title, int width, int height) { | |
windowId = glfwCreateWindow(width, height, title, NULL, NULL); | |
if (windowId == NULL) | |
throw new IllegalStateException("Failed to create GLFW window"); | |
WindowCallback.set(windowId, callback); | |
this.width = width; | |
this.height = height; | |
this.title = title; | |
} | |
public void setSwapInterval(int interval) { | |
glfwSwapInterval(interval); | |
} | |
public void swapBuffers() { | |
glfwSwapBuffers(windowId); | |
} | |
public boolean isClosedRequested() { | |
return glfwWindowShouldClose(windowId) == GL_TRUE; | |
} | |
public GLContext setCurrentContext() { | |
glfwMakeContextCurrent(windowId); | |
return GLContext.createFromCurrent(); | |
} | |
public boolean isResizable() { | |
return glfwGetWindowAttrib(windowId, GLFW_RESIZABLE) == GL_TRUE; | |
} | |
public void setSize(int width, int height) { | |
glfwSetWindowSize(windowId, width, height); | |
} | |
public void setSize(Dimension size) { | |
setSize(size.width, size.height); | |
} | |
public Dimension getSize() { | |
return new Dimension(width, height); | |
} | |
public int getWidth() { | |
return width; | |
} | |
public int getHeight() { | |
return height; | |
} | |
public Point getLocation() { | |
return new Point(x, y); | |
} | |
public int getX() { | |
return x; | |
} | |
public int getY() { | |
return y; | |
} | |
public void setLocation(int x, int y) { | |
glfwSetWindowPos(windowId, x, y); | |
} | |
public void setLocation(Point p) { | |
setLocation(p.x, p.y); | |
} | |
public void setVisible(boolean visible) { | |
if (visible) | |
glfwShowWindow(windowId); | |
else | |
glfwHideWindow(windowId); | |
this.visible = visible; | |
} | |
public boolean isVisible() { | |
return visible; | |
} | |
public void setTitle(String title) { | |
this.title = title; | |
glfwSetWindowTitle(windowId, title); | |
} | |
public String getTitle() { | |
return title; | |
} | |
public void addRefreshCallback(RefreshCallback callback) { | |
if (callback == null) | |
return; | |
this.callback.add(callback); | |
} | |
public void addPositionCallback(PositionCallback callback) { | |
if (callback == null) | |
return; | |
this.callback.add(callback); | |
} | |
public void addWindowStateCallback(WindowStateCallback callback) { | |
if (callback == null) | |
return; | |
this.callback.add(callback); | |
} | |
public void addMouseCallback(MouseCallback callback) { | |
if (callback == null) | |
return; | |
this.callback.add(callback); | |
} | |
public void addKeyCallback(KeyCallback callback) { | |
if (callback == null) | |
return; | |
this.callback.add(callback); | |
} | |
public void destroy() { | |
glfwDestroyWindow(windowId); | |
} | |
public void centerOnMonitor(int monitorIndex) { | |
GraphicsEnvironment e = GraphicsEnvironment.getLocalGraphicsEnvironment(); | |
GraphicsDevice[] devices = e.getScreenDevices(); | |
PointerBuffer monitors = glfwGetMonitors(); | |
long monitor = monitors.get(monitorIndex); | |
ByteBuffer vidmode = glfwGetVideoMode(monitor); | |
GraphicsConfiguration config = devices[monitorIndex].getDefaultConfiguration(); | |
int xInt = config.getBounds().x; | |
int yInt = config.getBounds().y; | |
int xPos = xInt + ((GLFWvidmode.width(vidmode) - width) / 2); | |
int yPos = yInt + ((GLFWvidmode.height(vidmode) - height) / 2); | |
glfwSetWindowPos(windowId, xPos, yPos); | |
} | |
private class Callback extends WindowCallbackAdapter { | |
private Window window; | |
private boolean focused = false; | |
private boolean shouldCallDragIfMove = false; | |
private Object lock = new Object(); | |
private List<RefreshCallback> refreshers = new ArrayList<RefreshCallback>(); | |
private List<PositionCallback> posCallbacks = new ArrayList<PositionCallback>(); | |
private List<WindowStateCallback> wsCallbacks = new ArrayList<WindowStateCallback>(); | |
private List<MouseCallback> mouseCallbacks = new ArrayList<MouseCallback>(); | |
private List<KeyCallback> keyCallbacks = new ArrayList<KeyCallback>(); | |
protected void add(RefreshCallback callback) { | |
synchronized(lock) { | |
refreshers.add(callback); | |
} | |
} | |
protected void add(PositionCallback callback) { | |
synchronized(lock) { | |
posCallbacks.add(callback); | |
} | |
} | |
protected void add(WindowStateCallback callback) { | |
synchronized(lock) { | |
wsCallbacks.add(callback); | |
} | |
} | |
protected void add(MouseCallback callback) { | |
synchronized(lock) { | |
mouseCallbacks.add(callback); | |
} | |
} | |
protected void add(KeyCallback callback) { | |
synchronized(lock) { | |
keyCallbacks.add(callback); | |
} | |
} | |
protected Callback(Window window) { | |
this.window = window; | |
} | |
@Override | |
public void windowSize(long window, int width, int height) { | |
if (window != this.window.windowId) | |
return; | |
this.window.width = width; | |
this.window.height = height; | |
synchronized(lock) { | |
for (WindowStateCallback c : wsCallbacks) | |
c.windowResized(this.window, width, height); | |
} | |
} | |
@Override | |
public void cursorEnter(long window, int entered) { | |
if (window != this.window.windowId) | |
return; | |
synchronized(lock) { | |
if (entered == GL_TRUE) { | |
for (MouseCallback c : mouseCallbacks) | |
c.mouseEntered(this.window); | |
} else if (entered == GL_FALSE) { | |
for (MouseCallback c : mouseCallbacks) | |
c.mouseExited(this.window); | |
} | |
} | |
} | |
@Override | |
public void cursorPos(long window, double xpos, double ypos) { | |
if (window != this.window.windowId) | |
return; | |
synchronized(lock) { | |
for (MouseCallback c : mouseCallbacks) | |
c.mouseMoved(this.window, xpos, ypos, shouldCallDragIfMove); | |
} | |
} | |
@Override | |
public void key(long window, int key, int scancode, int action, int mods) { | |
if (window != this.window.windowId) | |
return; | |
synchronized(lock) { | |
if (action == GLFW_PRESS) { | |
for (KeyCallback c : keyCallbacks) | |
c.keyPressed(this.window, key, scancode, mods); | |
} else if (action == GLFW_RELEASE) { | |
for (KeyCallback c : keyCallbacks) | |
c.keyReleased(this.window, key, scancode, mods); | |
} else if (action == GLFW_REPEAT) { | |
for (KeyCallback c : keyCallbacks) | |
c.keyRepeated(this.window, key, scancode, mods); | |
} | |
} | |
} | |
@Override | |
public void mouseButton(long window, int button, int action, int mods) { | |
if (window != this.window.windowId) | |
return; | |
boolean synth = !focused && (action == GLFW_RELEASE); | |
synchronized(lock) { | |
if (action == GLFW_PRESS) { | |
shouldCallDragIfMove = true; | |
for (MouseCallback c : mouseCallbacks) | |
c.mouseButtonPressed(this.window, button, mods); | |
} else if (action == GLFW_RELEASE) { | |
shouldCallDragIfMove = false; | |
for (MouseCallback c : mouseCallbacks) | |
c.mouseButtonReleased(this.window, button, mods, synth); | |
} | |
} | |
} | |
// @Override | |
// public void drop(long window, int count, long names) { | |
// if (window != this.window.windowId) | |
// return; | |
// synchronized(lock) { | |
// | |
// } | |
// } | |
@Override | |
public void scroll(long window, double xoffset, double yoffset) { | |
if (window != this.window.windowId) | |
return; | |
synchronized(lock) { | |
for (MouseCallback c : mouseCallbacks) | |
c.mouseScrolled(this.window, xoffset, yoffset); | |
} | |
} | |
@Override | |
public void windowClose(long window) { | |
if (window != this.window.windowId) | |
return; | |
synchronized(lock) { | |
for (WindowStateCallback c : wsCallbacks) | |
c.windowClosed(this.window); | |
} | |
} | |
@Override | |
public void windowFocus(long window, int focused) { | |
if (window != this.window.windowId) | |
return; | |
synchronized(lock) { | |
if (focused == GL_FALSE) { | |
this.focused = false; | |
for (WindowStateCallback c : wsCallbacks) | |
c.windowFocusLost(this.window); | |
} else if (focused == GL_TRUE) { | |
this.focused = true; | |
for (WindowStateCallback c : wsCallbacks) | |
c.windowFocusGained(this.window); | |
} | |
} | |
} | |
@Override | |
public void windowIconify(long window, int iconified) { | |
if (window != this.window.windowId) | |
return; | |
synchronized(lock) { | |
if (iconified == GL_FALSE) { | |
for (WindowStateCallback c : wsCallbacks) | |
c.windowIconified(this.window); | |
} else if (iconified == GL_TRUE) { | |
for (WindowStateCallback c : wsCallbacks) | |
c.windowRestored(this.window); | |
} | |
} | |
} | |
@Override | |
public void windowPos(long window, int xpos, int ypos) { | |
if (window != this.window.windowId) | |
return; | |
synchronized(lock) { | |
for (PositionCallback c : posCallbacks) | |
c.windowPositionChanged(this.window, xpos, ypos); | |
} | |
} | |
@Override | |
public void windowRefresh(long window) { | |
if (window != this.window.windowId) | |
return; | |
synchronized(lock) { | |
for (RefreshCallback c : refreshers) | |
c.windowRefreshed(this.window); | |
} | |
} | |
} | |
public static interface RefreshCallback { | |
public static class Adapter implements RefreshCallback { | |
public void windowRefreshed(Window window) {} | |
} | |
public void windowRefreshed(Window window); | |
} | |
public static interface PositionCallback { | |
public static class Adapter implements PositionCallback { | |
public void windowPositionChanged(Window window, int x, int y) {} | |
} | |
public void windowPositionChanged(Window window, int x, int y); | |
} | |
public static interface WindowStateCallback { | |
public static class Adapter implements WindowStateCallback { | |
public void windowIconified(Window window) {} | |
public void windowRestored(Window window) {} | |
public void windowFocusGained(Window window) {} | |
public void windowFocusLost(Window window) {} | |
public void windowClosed(Window window) {} | |
public void windowResized(Window window, int width, int height) {} | |
} | |
public static WindowStateCallback GL_RELOAD_ORTHO = new Adapter() { | |
@Override | |
public void windowResized(Window window, int width, int height) { | |
setupGlOrtho(width, height); | |
} | |
}; | |
public void windowIconified(Window window); | |
public void windowRestored(Window window); | |
public void windowFocusGained(Window window); | |
public void windowFocusLost(Window window); | |
public void windowClosed(Window window); | |
public void windowResized(Window window, int width, int height); | |
} | |
public static interface MouseCallback { | |
public static class Adapter implements MouseCallback { | |
public void mouseEntered(Window window) {} | |
public void mouseExited(Window window) {} | |
public void mouseMoved(Window window, double x, double y, boolean dragged) {} | |
public void mouseButtonPressed(Window window, int button, int mods) {} | |
public void mouseButtonReleased(Window window, int button, int mods, boolean synth) {} | |
public void mouseScrolled(Window window, double xOffset, double yOffset) {} | |
} | |
public void mouseEntered(Window window); | |
public void mouseExited(Window window); | |
public void mouseMoved(Window window, double x, double y, boolean dragged); | |
public void mouseButtonPressed(Window window, int button, int mods); | |
public void mouseButtonReleased(Window window, int button, int mods, boolean synth); | |
public void mouseScrolled(Window window, double xOffset, double yOffset); | |
} | |
public static interface KeyCallback { | |
public static class Adapter implements KeyCallback { | |
public void keyPressed(Window window, int key, int scancode, int mods) {} | |
public void keyReleased(Window window, int key, int scancode, int mods) {} | |
public void keyRepeated(Window window, int key, int scancode, int mods) {} | |
} | |
public static KeyCallback ESC_CLOSES_WINDOW = new Adapter() { | |
@Override | |
public void keyReleased(Window window, int key, int scancode, int mods) { | |
if (key == GLFW_KEY_ESCAPE) | |
glfwSetWindowShouldClose(window.windowId, GL_TRUE); | |
} | |
}; | |
public void keyPressed(Window window, int key, int scancode, int mods); | |
public void keyReleased(Window window, int key, int scancode, int mods); | |
public void keyRepeated(Window window, int key, int scancode, int mods); | |
} | |
// // Currently not used, dev needs to understand how to get Strings from raw memory (through ByteBuffer and MemoryUtil) first. | |
// public static interface FileDropCallback { | |
// public void filesDropped(Window window, File[] files); | |
// } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment