/* * The MIT License (MIT) * * Copyright (c) 2014-2017 Sri Harsha Chilakapati * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package com.shc.silenceengine.backend.lwjgl.glfw; import com.shc.silenceengine.backend.lwjgl.glfw.callbacks.IErrorCallback; import com.shc.silenceengine.backend.lwjgl.glfw.callbacks.IJoystickCallback; import com.shc.silenceengine.math.Vector3; import org.lwjgl.BufferUtils; import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFWErrorCallback; import org.lwjgl.glfw.GLFWJoystickCallback; import org.lwjgl.system.MemoryUtil; import java.nio.IntBuffer; import static org.lwjgl.glfw.GLFW.*; import static org.lwjgl.system.MemoryUtil.*; /** * Provides Java-ified versions of the GLFW methods. Use the methods of this class if you want to use the other classes * of this GLFW package. This is because the callbacks you have set will have to be translated to the callbacks that * LWJGL provides which can be sent to the native GLFW library. This abstraction is necessary to allow the more OOP use * of the GLFW library. * * @author Sri Harsha Chilakapati */ public final class GLFW3 { // The error callbacks private static GLFWErrorCallback glfwErrorCallback; private static IErrorCallback errorCallback; // The joystick callbacks private static GLFWJoystickCallback glfwJoystickCallback; private static IJoystickCallback joystickCallback; private static boolean initialized = false; /** * Prevent instantiation for a static utility class. */ private GLFW3() { } /** * Initializes the GLFW3 library. If you are not using the built-in Game class of the SilenceEngine, you should call * this method as soon as you can after loading the LWJGL3 natives. * * @return True if initialised successful, or else False. */ public static boolean init() { if (isInitialized()) return true; boolean state = glfwInit(); // Return immediately in case of error if (!state) return initialized = false; // Error callback that does nothing setErrorCallback(null); glfwErrorCallback = GLFWErrorCallback.create((error, description) -> errorCallback.invoke(error, MemoryUtil.memUTF8(description))); // Joystick callback that does nothing setJoystickCallback(null); glfwJoystickCallback = GLFWJoystickCallback.create((joy, event) -> joystickCallback.invoke(joy, event == GLFW_CONNECTED)); // Register the callback glfwSetErrorCallback(glfwErrorCallback); return initialized = true; } /** * Sets an error callback which will be invoked with an error code and a human readable description of the error * when an error occurred in the GLFW library. * * @param errorCallback The error callback to be invoked when an error occurs in GLFW. */ public static void setErrorCallback(IErrorCallback errorCallback) { if (errorCallback == null) errorCallback = (error, description) -> { }; GLFW3.errorCallback = errorCallback; } /** * Sets an joystick callback which will be invoked when a joystick event occurs. * * @param joystickCallback The joystick callback to be invoked when an event occurs in GLFW. */ public static void setJoystickCallback(IJoystickCallback joystickCallback) { if (joystickCallback == null) joystickCallback = (joystick, connected) -> { }; GLFW3.joystickCallback = joystickCallback; } /** * <p> This function processes only those events that are already in the event queue and then returns immediately. * Processing events will cause the window and input callbacks associated with those events to be called.</p> * * <p> On some platforms, a window move, resize or menu operation will cause event processing to block. This is due * to how event processing is designed on those platforms. You can use the window refresh callback to redraw the * contents of your window when necessary during such operations.</p> * * <p>On some platforms, certain events are sent directly to the application without going through the event queue, * causing callbacks to be called outside of a call to one of the event processing functions. Event processing is * not required for joystick input to work.</p> */ public static void pollEvents() { glfwPollEvents(); } /** * <p> This function puts the calling thread to sleep until at least one event is available in the event queue. Once * one or more events are available, it behaves exactly like glfwPollEvents, i.e. the events in the queue are * processed and the function then returns immediately. Processing events will cause the window and input callbacks * associated with those events to be called.</p> * * <p>Since not all events are associated with callbacks, this function may return without a callback having been * called even if you are monitoring all callbacks.</p> * * <p>On some platforms, a window move, resize or menu operation will cause event processing to block. This is due * to how event processing is designed on those platforms. You can use the window refresh callback to redraw the * contents of your window when necessary during such operations. On some platforms, certain callbacks may be called * outside of a call to one of the event processing functions.</p> * * <p>If no windows exist, this function returns immediately. For synchronization of threads in applications that do * not create windows, use your threading library of choice. Event processing is not required for joystick input to * work.</p> */ public static void waitEvents() { glfwWaitEvents(); } /** * <p> This function posts an empty event from the current thread to the event queue, causing glfwWaitEvents to * return.</p> * * <p> If no windows exist, this function returns immediately. For synchronization of threads in applications that * do not create windows, use your threading library of choice.</p> */ public static void postEmptyEvent() { glfwPostEmptyEvent(); } /** * <p> This function sets the swap interval for the current context, i.e. the number of screen updates to wait from * the time {@link GLFW#glfwSwapBuffers(long)} was called before swapping the buffers and returning. This is * sometimes called vertical synchronization, vertical retrace synchronization or just vsync.</p> * * <p> Contexts that support either of the {@code WGL_EXT_swap_control_tear} and * {@code GLX_EXT_swap_control_tear} extensions also accept negative swap intervals, which allow the driver to * swap even if a frame arrives a little bit late. You can check for the presence of these extensions using {@link * GLFW#glfwExtensionSupported(CharSequence)}. For more information about swap tearing, see the extension * specifications.</p> * * <p> A context must be current on the calling thread. Calling this function without a current context will cause a * {@code GLFW_NO_CURRENT_CONTEXT} error.</p> * * @param i The number of screen updates to wait before swapping the buffers. */ public static void setSwapInterval(int i) { glfwSwapInterval(i); } /** * <p> This function retrieves the major, minor and revision numbers of the GLFW library. It is intended for when * you are using GLFW as a shared library and want to ensure that you are using the minimum required version. It is * included here so you may want to write the GLFW version to a log file.</p> * * <p> The version is returned as a {@link Vector3} object whose components x, y, z represent the major, minor and * revision numbers of the version respectively</p> * * @return The version of the GLFW3 library linked with LWJGL3 as a Vector3 object. */ public static Vector3 getVersion() { IntBuffer version = BufferUtils.createIntBuffer(3); nglfwGetVersion(memAddress(version), memAddress(version) + Integer.BYTES, memAddress(version) + 2 * Integer.BYTES); return new Vector3(version.get(0), version.get(1), version.get(2)); } /** * <p> This function returns the compile-time generated version string of the GLFW library binary. It describes the * version, platform, compiler and any platform-specific compile-time options.</p> * * <p><b>Do not use the version string</b> to parse the GLFW library version. The getVersion() function already * provides the version of the running library binary.</p> * * @return The String representation of the compile-time generated GLFW version string. */ public static String getVersionString() { return glfwGetVersionString(); } /** * <p> This function destroys all remaining windows and cursors, restores any modified gamma ramps and frees any * other allocated resources. Once this function is called, you must again call {@link GLFW3#init()} successfully * before you will be able to use most GLFW functions.</p> * * <p> If GLFW has been successfully initialized, this function should be called before the application exits. If * initialization fails, there is no need to call this function, as it is called by {@link GLFW3#init()} before it * returns failure.</p> */ public static void terminate() { if (!isInitialized()) return; if (glfwErrorCallback != null) glfwErrorCallback.free(); if (glfwJoystickCallback != null) glfwJoystickCallback.free(); glfwTerminate(); initialized = false; } /** * Returns whether GLFW3 has been initialized or not. * * @return True if GLFW3 is initialized with {@link #init()}. False otherwise. */ public static boolean isInitialized() { return initialized; } }