package org.toop; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.lwjgl.*; import org.lwjgl.glfw.*; import org.lwjgl.opengl.*; import org.lwjgl.system.*; import java.nio.*; import static org.lwjgl.glfw.Callbacks.*; import static org.lwjgl.glfw.GLFW.*; import static org.lwjgl.opengl.GL11.*; import static org.lwjgl.system.MemoryStack.*; import static org.lwjgl.system.MemoryUtil.*; import static org.lwjgl.stb.STBImage.*; public class Window extends Thread { private static final Logger logger = LogManager.getLogger(Main.class); // The window handle private long window; public void run() { init(); loop(); // Free the window callbacks and destroy the window glfwFreeCallbacks(window); glfwDestroyWindow(window); // Terminate GLFW and free the error callback glfwTerminate(); glfwSetErrorCallback(null).free(); } private void init() { // Set up an error callback. The default implementation // will print the error message in System.err. GLFWErrorCallback.createPrint(System.err).set(); // Initialize GLFW. Most GLFW functions will not work before doing this. if ( !glfwInit() ){ throw new IllegalStateException("Unable to initialize GLFW"); } // Configure GLFW glfwDefaultWindowHints(); // optional, the current window hints are already the default glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // the window will stay hidden after creation glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); // the window will be resizable // Create the window window = glfwCreateWindow(1920, 1080, "ISY Game Selector", NULL, NULL); if ( window == NULL ) throw new RuntimeException("Failed to create the GLFW window"); // Set up a key callback. It will be called every time a key is pressed, repeated or released. glfwSetKeyCallback(window, (window, key, scancode, action, mods) -> { if ( key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE ) { glfwSetWindowShouldClose(window, true); // We will detect this in the rendering loop } }); // Get the thread stack and push a new frame try ( MemoryStack stack = stackPush() ) { IntBuffer pWidth = stack.mallocInt(1); // int* IntBuffer pHeight = stack.mallocInt(1); // int* // Get the window size passed to glfwCreateWindow glfwGetWindowSize(window, pWidth, pHeight); // Get the resolution of the primary monitor GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor()); // Center the window assert vidmode != null; glfwSetWindowPos( window, (vidmode.width() - pWidth.get(0)) / 2, (vidmode.height() - pHeight.get(0)) / 2 ); // Prepare buffers to receive image data IntBuffer width = stack.mallocInt(1); IntBuffer height = stack.mallocInt(1); IntBuffer channels = stack.mallocInt(1); // Load the image String imagePath = "img/icon.png"; ByteBuffer image = stbi_load(imagePath, width, height, channels, 4); // Force RGBA (4 channels) if (image == null) { throw new RuntimeException("Failed to load image: " + stbi_failure_reason()); } // Create GLFWImage GLFWImage icon = GLFWImage.malloc(stack); icon.set(width.get(0), height.get(0), image); // Create a buffer with the icon(s) — can be multiple icons for different sizes GLFWImage.Buffer icons = GLFWImage.malloc(1, stack); icons.put(0, icon); // Set the window icon glfwSetWindowIcon(window, icons); // Free the image data stbi_image_free(image); } // the stack frame is popped automatically // Make the OpenGL context current glfwMakeContextCurrent(window); // Enable v-sync glfwSwapInterval(1); // Make the window visible glfwShowWindow(window); } private void loop() { // This line is critical for LWJGL's interoperation with GLFW's // OpenGL context, or any context that is managed externally. // LWJGL detects the context that is current in the current thread, // creates the GLCapabilities instance and makes the OpenGL // bindings available for use. GL.createCapabilities(); // Set the clear color glClearColor(0.5f, 0.5f, 0.5f, 0.0f); // Run the rendering loop until the user has attempted to close // the window or has pressed the ESCAPE key. while ( !glfwWindowShouldClose(window) ) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer glfwSwapBuffers(window); // swap the color buffers // Poll for window events. The key callback above will only be // invoked during this call. glfwPollEvents(); } } //public static void main(String[] args) { //new Window().run(); //} /** * TODO: Is putting the window on a second thread, safe? * Can't overwrite start(), so a overload is needed. * * @param ignoredKeepEmpty Just input "" an empty string. */ public static void start(String ignoredKeepEmpty){ new Window().start(); } }