LWJGL3 improvements
* Added key remapping for GLFW key constants * Rename AppSettings.getGammaCorrection() to isGammaCorrection() * Use LWJGL3 artifacts from maven * Minor compatibility changes for LWJGL 3.0.0b * Fixed some minor bugs in LwjglWindow
This commit is contained in:
parent
6cb691592d
commit
2ca55c8b3a
@ -36,6 +36,11 @@ package com.jme3.input;
|
||||
*/
|
||||
public interface KeyInput extends Input {
|
||||
|
||||
/**
|
||||
* unmapped key.
|
||||
*/
|
||||
public static final int KEY_UNKNOWN = 0x00;
|
||||
|
||||
/**
|
||||
* escape key.
|
||||
*/
|
||||
@ -518,17 +523,17 @@ public interface KeyInput extends Input {
|
||||
* delete key.
|
||||
*/
|
||||
public static final int KEY_DELETE = 0xD3;
|
||||
|
||||
|
||||
/**
|
||||
* Left "Windows" key on PC keyboards, left "Option" key on Mac keyboards.
|
||||
*/
|
||||
public static final int KEY_LMETA = 0xDB;
|
||||
|
||||
|
||||
/**
|
||||
* Right "Windows" key on PC keyboards, right "Option" key on Mac keyboards.
|
||||
*/
|
||||
public static final int KEY_RMETA = 0xDC;
|
||||
|
||||
|
||||
public static final int KEY_APPS = 0xDD;
|
||||
/**
|
||||
* power key.
|
||||
@ -539,4 +544,8 @@ public interface KeyInput extends Input {
|
||||
*/
|
||||
public static final int KEY_SLEEP = 0xDF;
|
||||
|
||||
/**
|
||||
* the last key.
|
||||
*/
|
||||
public static final int KEY_LAST = 0xE0;
|
||||
}
|
||||
|
@ -34,10 +34,11 @@ package com.jme3.input;
|
||||
import static com.jme3.input.KeyInput.*;
|
||||
|
||||
public class KeyNames {
|
||||
|
||||
|
||||
private static final String[] KEY_NAMES = new String[0xFF];
|
||||
|
||||
|
||||
static {
|
||||
KEY_NAMES[KEY_UNKNOWN] = "Unknown";
|
||||
KEY_NAMES[KEY_0] = "0";
|
||||
KEY_NAMES[KEY_1] = "1";
|
||||
KEY_NAMES[KEY_2] = "2";
|
||||
@ -48,7 +49,7 @@ public class KeyNames {
|
||||
KEY_NAMES[KEY_7] = "7";
|
||||
KEY_NAMES[KEY_8] = "8";
|
||||
KEY_NAMES[KEY_9] = "9";
|
||||
|
||||
|
||||
KEY_NAMES[KEY_Q] = "Q";
|
||||
KEY_NAMES[KEY_W] = "W";
|
||||
KEY_NAMES[KEY_E] = "E";
|
||||
@ -75,7 +76,7 @@ public class KeyNames {
|
||||
KEY_NAMES[KEY_B] = "B";
|
||||
KEY_NAMES[KEY_N] = "N";
|
||||
KEY_NAMES[KEY_M] = "M";
|
||||
|
||||
|
||||
KEY_NAMES[KEY_F1] = "F1";
|
||||
KEY_NAMES[KEY_F2] = "F2";
|
||||
KEY_NAMES[KEY_F3] = "F3";
|
||||
@ -91,7 +92,7 @@ public class KeyNames {
|
||||
KEY_NAMES[KEY_F13] = "F13";
|
||||
KEY_NAMES[KEY_F14] = "F14";
|
||||
KEY_NAMES[KEY_F15] = "F15";
|
||||
|
||||
|
||||
KEY_NAMES[KEY_NUMPAD0] = "Numpad 0";
|
||||
KEY_NAMES[KEY_NUMPAD1] = "Numpad 1";
|
||||
KEY_NAMES[KEY_NUMPAD2] = "Numpad 2";
|
||||
@ -102,25 +103,26 @@ public class KeyNames {
|
||||
KEY_NAMES[KEY_NUMPAD7] = "Numpad 7";
|
||||
KEY_NAMES[KEY_NUMPAD8] = "Numpad 8";
|
||||
KEY_NAMES[KEY_NUMPAD9] = "Numpad 9";
|
||||
|
||||
|
||||
KEY_NAMES[KEY_NUMPADEQUALS] = "Numpad =";
|
||||
KEY_NAMES[KEY_NUMPADENTER] = "Numpad Enter";
|
||||
KEY_NAMES[KEY_NUMPADCOMMA] = "Numpad .";
|
||||
KEY_NAMES[KEY_NUMPADCOMMA] = "Numpad ,";
|
||||
KEY_NAMES[KEY_DIVIDE] = "Numpad /";
|
||||
|
||||
|
||||
KEY_NAMES[KEY_SUBTRACT] = "Numpad -";
|
||||
KEY_NAMES[KEY_DECIMAL] = "Numpad .";
|
||||
|
||||
KEY_NAMES[KEY_LMENU] = "Left Alt";
|
||||
KEY_NAMES[KEY_RMENU] = "Right Alt";
|
||||
|
||||
|
||||
KEY_NAMES[KEY_LCONTROL] = "Left Ctrl";
|
||||
KEY_NAMES[KEY_RCONTROL] = "Right Ctrl";
|
||||
|
||||
|
||||
KEY_NAMES[KEY_LSHIFT] = "Left Shift";
|
||||
KEY_NAMES[KEY_RSHIFT] = "Right Shift";
|
||||
|
||||
|
||||
KEY_NAMES[KEY_LMETA] = "Left Option";
|
||||
KEY_NAMES[KEY_RMETA] = "Right Option";
|
||||
|
||||
|
||||
KEY_NAMES[KEY_MINUS] = "-";
|
||||
KEY_NAMES[KEY_EQUALS] = "=";
|
||||
KEY_NAMES[KEY_LBRACKET] = "[";
|
||||
@ -137,37 +139,37 @@ public class KeyNames {
|
||||
KEY_NAMES[KEY_COLON] = ":";
|
||||
KEY_NAMES[KEY_UNDERLINE] = "_";
|
||||
KEY_NAMES[KEY_AT] = "@";
|
||||
|
||||
|
||||
KEY_NAMES[KEY_APPS] = "Apps";
|
||||
KEY_NAMES[KEY_POWER] = "Power";
|
||||
KEY_NAMES[KEY_SLEEP] = "Sleep";
|
||||
|
||||
|
||||
KEY_NAMES[KEY_STOP] = "Stop";
|
||||
KEY_NAMES[KEY_ESCAPE] = "Esc";
|
||||
KEY_NAMES[KEY_RETURN] = "Enter";
|
||||
KEY_NAMES[KEY_SPACE] = "Space";
|
||||
KEY_NAMES[KEY_BACK] = "Backspace";
|
||||
KEY_NAMES[KEY_TAB] = "Tab";
|
||||
|
||||
|
||||
KEY_NAMES[KEY_SYSRQ] = "SysRq";
|
||||
KEY_NAMES[KEY_PAUSE] = "Pause";
|
||||
|
||||
|
||||
KEY_NAMES[KEY_HOME] = "Home";
|
||||
KEY_NAMES[KEY_PGUP] = "Page Up";
|
||||
KEY_NAMES[KEY_PGDN] = "Page Down";
|
||||
KEY_NAMES[KEY_END] = "End";
|
||||
KEY_NAMES[KEY_INSERT] = "Insert";
|
||||
KEY_NAMES[KEY_DELETE] = "Delete";
|
||||
|
||||
|
||||
KEY_NAMES[KEY_UP] = "Up";
|
||||
KEY_NAMES[KEY_LEFT] = "Left";
|
||||
KEY_NAMES[KEY_RIGHT] = "Right";
|
||||
KEY_NAMES[KEY_DOWN] = "Down";
|
||||
|
||||
|
||||
KEY_NAMES[KEY_NUMLOCK] = "Num Lock";
|
||||
KEY_NAMES[KEY_CAPITAL] = "Caps Lock";
|
||||
KEY_NAMES[KEY_SCROLL] = "Scroll Lock";
|
||||
|
||||
|
||||
KEY_NAMES[KEY_KANA] = "Kana";
|
||||
KEY_NAMES[KEY_CONVERT] = "Convert";
|
||||
KEY_NAMES[KEY_NOCONVERT] = "No Convert";
|
||||
@ -177,8 +179,8 @@ public class KeyNames {
|
||||
KEY_NAMES[KEY_AX] = "Ax";
|
||||
KEY_NAMES[KEY_UNLABELED] = "Unlabeled";
|
||||
}
|
||||
|
||||
public String getName(int keyId){
|
||||
|
||||
public static String getName(int keyId) {
|
||||
return KEY_NAMES[keyId];
|
||||
}
|
||||
}
|
||||
|
@ -963,7 +963,7 @@ public final class AppSettings extends HashMap<String, Object> {
|
||||
return getString("SettingsDialogImage");
|
||||
}
|
||||
|
||||
public boolean getGammaCorrection() {
|
||||
public boolean isGammaCorrection() {
|
||||
return getBoolean("GammaCorrection");
|
||||
}
|
||||
|
||||
|
@ -360,7 +360,7 @@ public final class SettingsDialog extends JFrame {
|
||||
vsyncBox.setSelected(source.isVSync());
|
||||
|
||||
gammaBox = new JCheckBox(resourceBundle.getString("checkbox.gamma"));
|
||||
gammaBox.setSelected(source.getGammaCorrection());
|
||||
gammaBox.setSelected(source.isGammaCorrection());
|
||||
|
||||
gbc = new GridBagConstraints();
|
||||
gbc.weightx = 0.5;
|
||||
|
@ -54,6 +54,7 @@ import com.jme3.system.AppSettings;
|
||||
import com.jme3.system.JmeContext;
|
||||
import com.jme3.system.NanoTimer;
|
||||
import com.jme3.system.NativeLibraryLoader;
|
||||
import com.jme3.system.NullRenderer;
|
||||
import com.jme3.system.SystemListener;
|
||||
import com.jme3.system.Timer;
|
||||
|
||||
@ -69,9 +70,9 @@ import com.jogamp.opengl.GLContext;
|
||||
public abstract class JoglContext implements JmeContext {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(JoglContext.class.getName());
|
||||
|
||||
|
||||
protected static final String THREAD_NAME = "jME3 Main";
|
||||
|
||||
|
||||
protected AtomicBoolean created = new AtomicBoolean(false);
|
||||
protected AtomicBoolean renderable = new AtomicBoolean(false);
|
||||
protected final Object createdLock = new Object();
|
||||
@ -91,7 +92,7 @@ public abstract class JoglContext implements JmeContext {
|
||||
NativeLibraryLoader.loadNativeLibrary("bulletjme", true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setSystemListener(SystemListener listener){
|
||||
this.listener = listener;
|
||||
@ -101,7 +102,7 @@ public abstract class JoglContext implements JmeContext {
|
||||
public void setSettings(AppSettings settings) {
|
||||
this.settings.copyFrom(settings);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isRenderable(){
|
||||
return renderable.get();
|
||||
@ -160,50 +161,50 @@ public abstract class JoglContext implements JmeContext {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void initContextFirstTime(){
|
||||
if (GLContext.getCurrent().getGLVersionNumber().getMajor() < 2) {
|
||||
throw new RendererException("OpenGL 2.0 or higher is " +
|
||||
throw new RendererException("OpenGL 2.0 or higher is " +
|
||||
"required for jMonkeyEngine");
|
||||
}
|
||||
|
||||
|
||||
if (settings.getRenderer().startsWith("JOGL")) {
|
||||
com.jme3.renderer.opengl.GL gl = new JoglGL();
|
||||
GLExt glext = new JoglGLExt();
|
||||
GLFbo glfbo = new JoglGLFbo();
|
||||
|
||||
|
||||
if (settings.getBoolean("GraphicsDebug")) {
|
||||
gl = new GLDebugDesktop(gl, glext, glfbo);
|
||||
glext = (GLExt) gl;
|
||||
glfbo = (GLFbo) gl;
|
||||
}
|
||||
|
||||
|
||||
if (settings.getBoolean("GraphicsTiming")) {
|
||||
GLTimingState timingState = new GLTimingState();
|
||||
gl = (com.jme3.renderer.opengl.GL) GLTiming.createGLTiming(gl, timingState, GL.class, GL2.class, GL3.class, GL4.class);
|
||||
glext = (GLExt) GLTiming.createGLTiming(glext, timingState, GLExt.class);
|
||||
glfbo = (GLFbo) GLTiming.createGLTiming(glfbo, timingState, GLFbo.class);
|
||||
}
|
||||
|
||||
|
||||
if (settings.getBoolean("GraphicsTrace")) {
|
||||
gl = (com.jme3.renderer.opengl.GL) GLTracer.createDesktopGlTracer(gl, GL.class, GL2.class, GL3.class, GL4.class);
|
||||
glext = (GLExt) GLTracer.createDesktopGlTracer(glext, GLExt.class);
|
||||
glfbo = (GLFbo) GLTracer.createDesktopGlTracer(glfbo, GLFbo.class);
|
||||
}
|
||||
|
||||
|
||||
renderer = new GLRenderer(gl, glext, glfbo);
|
||||
renderer.initialize();
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Unsupported renderer: " + settings.getRenderer());
|
||||
}
|
||||
|
||||
|
||||
if (GLContext.getCurrentGL().isExtensionAvailable("GL_ARB_debug_output") && settings.getBoolean("GraphicsDebug")) {
|
||||
GLContext.getCurrent().enableGLDebugMessage(true);
|
||||
GLContext.getCurrent().addGLDebugListener(new JoglGLDebugOutputHandler());
|
||||
}
|
||||
|
||||
renderer.setMainFrameBufferSrgb(settings.getGammaCorrection());
|
||||
renderer.setLinearizeSrgbImages(settings.getGammaCorrection());
|
||||
|
||||
renderer.setMainFrameBufferSrgb(settings.isGammaCorrection());
|
||||
renderer.setLinearizeSrgbImages(settings.isGammaCorrection());
|
||||
|
||||
// Init input
|
||||
if (keyInput != null) {
|
||||
@ -241,7 +242,7 @@ public abstract class JoglContext implements JmeContext {
|
||||
createdLock.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected int determineMaxSamples(int requestedSamples) {
|
||||
GL gl = GLContext.getCurrentGL();
|
||||
if (gl.hasFullFBOSupport()) {
|
||||
@ -257,7 +258,7 @@ public abstract class JoglContext implements JmeContext {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected int getNumSamplesToUse() {
|
||||
int samples = 0;
|
||||
if (settings.getSamples() > 1){
|
||||
@ -268,7 +269,7 @@ public abstract class JoglContext implements JmeContext {
|
||||
"Couldn''t satisfy antialiasing samples requirement: x{0}. "
|
||||
+ "Video hardware only supports: x{1}",
|
||||
new Object[]{samples, supportedSamples});
|
||||
|
||||
|
||||
samples = supportedSamples;
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,6 @@
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.jme3.system.lwjgl;
|
||||
|
||||
import com.jme3.input.lwjgl.JInputJoyInput;
|
||||
@ -53,6 +52,7 @@ import com.jme3.renderer.opengl.GLTiming;
|
||||
import com.jme3.renderer.opengl.GLTimingState;
|
||||
import com.jme3.renderer.opengl.GLTracer;
|
||||
import com.jme3.system.*;
|
||||
import java.io.File;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.logging.Level;
|
||||
@ -69,7 +69,7 @@ public abstract class LwjglContext implements JmeContext {
|
||||
private static final Logger logger = Logger.getLogger(LwjglContext.class.getName());
|
||||
|
||||
protected static final String THREAD_NAME = "jME3 Main";
|
||||
|
||||
|
||||
protected AtomicBoolean created = new AtomicBoolean(false);
|
||||
protected AtomicBoolean renderable = new AtomicBoolean(false);
|
||||
protected final Object createdLock = new Object();
|
||||
@ -82,18 +82,18 @@ public abstract class LwjglContext implements JmeContext {
|
||||
protected Timer timer;
|
||||
protected SystemListener listener;
|
||||
|
||||
public void setSystemListener(SystemListener listener){
|
||||
public void setSystemListener(SystemListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
protected void printContextInitInfo() {
|
||||
logger.log(Level.INFO, "LWJGL {0} context running on thread {1}\n" +
|
||||
" * Graphics Adapter: {2}\n" +
|
||||
" * Driver Version: {3}\n" +
|
||||
" * Scaling Factor: {4}",
|
||||
new Object[]{ Sys.getVersion(), Thread.currentThread().getName(),
|
||||
Display.getAdapter(), Display.getVersion(),
|
||||
Display.getPixelScaleFactor() });
|
||||
logger.log(Level.INFO, "LWJGL {0} context running on thread {1}\n"
|
||||
+ " * Graphics Adapter: {2}\n"
|
||||
+ " * Driver Version: {3}\n"
|
||||
+ " * Scaling Factor: {4}",
|
||||
new Object[]{Sys.getVersion(), Thread.currentThread().getName(),
|
||||
Display.getAdapter(), Display.getVersion(),
|
||||
Display.getPixelScaleFactor()});
|
||||
}
|
||||
|
||||
protected ContextAttribs createContextAttribs() {
|
||||
@ -113,7 +113,7 @@ public abstract class LwjglContext implements JmeContext {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected int determineMaxSamples(int requestedSamples) {
|
||||
try {
|
||||
// If we already have a valid context, determine samples using current
|
||||
@ -131,13 +131,13 @@ public abstract class LwjglContext implements JmeContext {
|
||||
} catch (LWJGLException ex) {
|
||||
listener.handleError("Failed to check if display is current", ex);
|
||||
}
|
||||
|
||||
|
||||
if ((Pbuffer.getCapabilities() & Pbuffer.PBUFFER_SUPPORTED) == 0) {
|
||||
// No pbuffer, assume everything is supported.
|
||||
return Integer.MAX_VALUE;
|
||||
} else {
|
||||
Pbuffer pb = null;
|
||||
|
||||
|
||||
// OpenGL2 method: Create pbuffer and query samples
|
||||
// from GL_ARB_framebuffer_object or GL_EXT_framebuffer_multisample.
|
||||
try {
|
||||
@ -155,33 +155,40 @@ public abstract class LwjglContext implements JmeContext {
|
||||
} catch (LWJGLException ex) {
|
||||
// Something else failed.
|
||||
return Integer.MAX_VALUE;
|
||||
} finally {
|
||||
} finally {
|
||||
if (pb != null) {
|
||||
pb.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void loadNatives() {
|
||||
if (JmeSystem.isLowPermissions()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String extractPath = NativeLibraryLoader.getExtractionFolder().getAbsolutePath();
|
||||
|
||||
if ("LWJGL".equals(settings.getAudioRenderer())) {
|
||||
NativeLibraryLoader.loadNativeLibrary("openal", true);
|
||||
}
|
||||
if (settings.useJoysticks()) {
|
||||
NativeLibraryLoader.loadNativeLibrary("jinput", true);
|
||||
NativeLibraryLoader.loadNativeLibrary("jinput-dx8", true);
|
||||
System.setProperty("net.java.games.input.librarypath", extractPath);
|
||||
NativeLibraryLoader.loadNativeLibrary("jinput", true, false);
|
||||
NativeLibraryLoader.loadNativeLibrary("jinput-dx8", true, false);
|
||||
}
|
||||
if (NativeLibraryLoader.isUsingNativeBullet()) {
|
||||
NativeLibraryLoader.loadNativeLibrary("bulletjme", true);
|
||||
}
|
||||
NativeLibraryLoader.loadNativeLibrary("lwjgl", true);
|
||||
|
||||
System.setProperty("org.lwjgl.librarypath", extractPath);
|
||||
NativeLibraryLoader.loadNativeLibrary("lwjgl", true, false);
|
||||
}
|
||||
|
||||
|
||||
protected int getNumSamplesToUse() {
|
||||
int samples = 0;
|
||||
if (settings.getSamples() > 1){
|
||||
if (settings.getSamples() > 1) {
|
||||
samples = settings.getSamples();
|
||||
int supportedSamples = determineMaxSamples(samples);
|
||||
if (supportedSamples < samples) {
|
||||
@ -189,62 +196,62 @@ public abstract class LwjglContext implements JmeContext {
|
||||
"Couldn''t satisfy antialiasing samples requirement: x{0}. "
|
||||
+ "Video hardware only supports: x{1}",
|
||||
new Object[]{samples, supportedSamples});
|
||||
|
||||
|
||||
samples = supportedSamples;
|
||||
}
|
||||
}
|
||||
return samples;
|
||||
}
|
||||
|
||||
protected void initContextFirstTime(){
|
||||
protected void initContextFirstTime() {
|
||||
if (!GLContext.getCapabilities().OpenGL20) {
|
||||
throw new RendererException("OpenGL 2.0 or higher is " +
|
||||
"required for jMonkeyEngine");
|
||||
throw new RendererException("OpenGL 2.0 or higher is "
|
||||
+ "required for jMonkeyEngine");
|
||||
}
|
||||
|
||||
|
||||
if (settings.getRenderer().equals(AppSettings.LWJGL_OPENGL2)
|
||||
|| settings.getRenderer().equals(AppSettings.LWJGL_OPENGL3)) {
|
||||
|| settings.getRenderer().equals(AppSettings.LWJGL_OPENGL3)) {
|
||||
GL gl = new LwjglGL();
|
||||
GLExt glext = new LwjglGLExt();
|
||||
GLFbo glfbo;
|
||||
|
||||
|
||||
if (GLContext.getCapabilities().OpenGL30) {
|
||||
glfbo = new LwjglGLFboGL3();
|
||||
} else {
|
||||
glfbo = new LwjglGLFboEXT();
|
||||
}
|
||||
|
||||
|
||||
if (settings.getBoolean("GraphicsDebug")) {
|
||||
gl = new GLDebugDesktop(gl, glext, glfbo);
|
||||
gl = new GLDebugDesktop(gl, glext, glfbo);
|
||||
glext = (GLExt) gl;
|
||||
glfbo = (GLFbo) gl;
|
||||
}
|
||||
|
||||
|
||||
if (settings.getBoolean("GraphicsTiming")) {
|
||||
GLTimingState timingState = new GLTimingState();
|
||||
gl = (GL) GLTiming.createGLTiming(gl, timingState, GL.class, GL2.class, GL3.class, GL4.class);
|
||||
gl = (GL) GLTiming.createGLTiming(gl, timingState, GL.class, GL2.class, GL3.class, GL4.class);
|
||||
glext = (GLExt) GLTiming.createGLTiming(glext, timingState, GLExt.class);
|
||||
glfbo = (GLFbo) GLTiming.createGLTiming(glfbo, timingState, GLFbo.class);
|
||||
}
|
||||
|
||||
|
||||
if (settings.getBoolean("GraphicsTrace")) {
|
||||
gl = (GL) GLTracer.createDesktopGlTracer(gl, GL.class, GL2.class, GL3.class, GL4.class);
|
||||
gl = (GL) GLTracer.createDesktopGlTracer(gl, GL.class, GL2.class, GL3.class, GL4.class);
|
||||
glext = (GLExt) GLTracer.createDesktopGlTracer(glext, GLExt.class);
|
||||
glfbo = (GLFbo) GLTracer.createDesktopGlTracer(glfbo, GLFbo.class);
|
||||
}
|
||||
|
||||
|
||||
renderer = new GLRenderer(gl, glext, glfbo);
|
||||
renderer.initialize();
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Unsupported renderer: " + settings.getRenderer());
|
||||
}
|
||||
|
||||
|
||||
if (GLContext.getCapabilities().GL_ARB_debug_output && settings.getBoolean("GraphicsDebug")) {
|
||||
ARBDebugOutput.glDebugMessageCallbackARB(new ARBDebugOutputCallback(new LwjglGLDebugOutputHandler()));
|
||||
}
|
||||
|
||||
renderer.setMainFrameBufferSrgb(settings.getGammaCorrection());
|
||||
renderer.setLinearizeSrgbImages(settings.getGammaCorrection());
|
||||
|
||||
renderer.setMainFrameBufferSrgb(settings.isGammaCorrection());
|
||||
renderer.setLinearizeSrgbImages(settings.isGammaCorrection());
|
||||
|
||||
// Init input
|
||||
if (keyInput != null) {
|
||||
@ -260,42 +267,42 @@ public abstract class LwjglContext implements JmeContext {
|
||||
}
|
||||
}
|
||||
|
||||
public void internalDestroy(){
|
||||
public void internalDestroy() {
|
||||
renderer = null;
|
||||
timer = null;
|
||||
renderable.set(false);
|
||||
synchronized (createdLock){
|
||||
synchronized (createdLock) {
|
||||
created.set(false);
|
||||
createdLock.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
public void internalCreate(){
|
||||
|
||||
public void internalCreate() {
|
||||
timer = new LwjglTimer();
|
||||
|
||||
synchronized (createdLock){
|
||||
|
||||
synchronized (createdLock) {
|
||||
created.set(true);
|
||||
createdLock.notifyAll();
|
||||
}
|
||||
|
||||
if (renderable.get()){
|
||||
|
||||
if (renderable.get()) {
|
||||
initContextFirstTime();
|
||||
}else{
|
||||
} else {
|
||||
assert getType() == Type.Canvas;
|
||||
}
|
||||
}
|
||||
|
||||
public void create(){
|
||||
public void create() {
|
||||
create(false);
|
||||
}
|
||||
|
||||
public void destroy(){
|
||||
public void destroy() {
|
||||
destroy(false);
|
||||
}
|
||||
|
||||
protected void waitFor(boolean createdVal){
|
||||
synchronized (createdLock){
|
||||
while (created.get() != createdVal){
|
||||
protected void waitFor(boolean createdVal) {
|
||||
synchronized (createdLock) {
|
||||
while (created.get() != createdVal) {
|
||||
try {
|
||||
createdLock.wait();
|
||||
} catch (InterruptedException ex) {
|
||||
@ -304,11 +311,11 @@ public abstract class LwjglContext implements JmeContext {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isCreated(){
|
||||
public boolean isCreated() {
|
||||
return created.get();
|
||||
}
|
||||
|
||||
public boolean isRenderable(){
|
||||
|
||||
public boolean isRenderable() {
|
||||
return renderable.get();
|
||||
}
|
||||
|
||||
@ -316,7 +323,7 @@ public abstract class LwjglContext implements JmeContext {
|
||||
this.settings.copyFrom(settings);
|
||||
}
|
||||
|
||||
public AppSettings getSettings(){
|
||||
public AppSettings getSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
|
@ -2,14 +2,14 @@ if (!hasProperty('mainClass')) {
|
||||
ext.mainClass = ''
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
url "https://oss.sonatype.org/content/repositories/snapshots"
|
||||
}
|
||||
}
|
||||
def lwjglVersion = '3.0.0b'
|
||||
|
||||
dependencies {
|
||||
compile project(':jme3-core')
|
||||
compile project(':jme3-desktop')
|
||||
compile files('lib/lwjgl-3.0.0b-35.jar', 'lib/lwjgl-3.0.0b-35-natives.jar')
|
||||
}
|
||||
|
||||
compile "org.lwjgl:lwjgl:${lwjglVersion}"
|
||||
compile "org.lwjgl:lwjgl-platform:${lwjglVersion}:natives-windows"
|
||||
compile "org.lwjgl:lwjgl-platform:${lwjglVersion}:natives-linux"
|
||||
compile "org.lwjgl:lwjgl-platform:${lwjglVersion}:natives-osx"
|
||||
}
|
Binary file not shown.
Binary file not shown.
@ -32,32 +32,38 @@
|
||||
package com.jme3.audio.lwjgl;
|
||||
|
||||
import com.jme3.audio.openal.ALC;
|
||||
import java.nio.IntBuffer;
|
||||
import org.lwjgl.openal.ALC10;
|
||||
import org.lwjgl.openal.ALContext;
|
||||
import org.lwjgl.openal.ALDevice;
|
||||
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import static org.lwjgl.openal.ALC10.alcGetContextsDevice;
|
||||
import static org.lwjgl.openal.ALC10.alcGetCurrentContext;
|
||||
import org.lwjgl.openal.SOFTPauseDevice;
|
||||
|
||||
public class LwjglALC implements ALC {
|
||||
|
||||
private ALDevice device;
|
||||
private ALContext context;
|
||||
|
||||
private long contextId;
|
||||
private long deviceId;
|
||||
|
||||
public void createALC() {
|
||||
device = ALDevice.create();
|
||||
context = ALContext.create(device);
|
||||
context.makeCurrent();
|
||||
|
||||
contextId = ALC10.alcGetCurrentContext();
|
||||
deviceId = ALC10.alcGetContextsDevice(contextId);
|
||||
}
|
||||
|
||||
public void destroyALC() {
|
||||
if (context != null) {
|
||||
context.destroy();
|
||||
context = null;
|
||||
}
|
||||
|
||||
if (device != null) {
|
||||
device.destroy();
|
||||
device = null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,31 +72,29 @@ public class LwjglALC implements ALC {
|
||||
}
|
||||
|
||||
public String alcGetString(final int parameter) {
|
||||
final long context = alcGetCurrentContext();
|
||||
final long device = alcGetContextsDevice(context);
|
||||
return ALC10.alcGetString(device, parameter);
|
||||
return ALC10.alcGetString(deviceId, parameter);
|
||||
}
|
||||
|
||||
public boolean alcIsExtensionPresent(final String extension) {
|
||||
final long context = alcGetCurrentContext();
|
||||
final long device = alcGetContextsDevice(context);
|
||||
return ALC10.alcIsExtensionPresent(device, extension);
|
||||
return ALC10.alcIsExtensionPresent(deviceId, extension);
|
||||
}
|
||||
|
||||
public void alcGetInteger(final int param, final IntBuffer buffer, final int size) {
|
||||
if (buffer.position() != 0) throw new AssertionError();
|
||||
if (buffer.limit() != size) throw new AssertionError();
|
||||
|
||||
final long context = alcGetCurrentContext();
|
||||
final long device = alcGetContextsDevice(context);
|
||||
final int value = ALC10.alcGetInteger(device, param);
|
||||
//buffer.put(value);
|
||||
if (buffer.position() != 0) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
if (buffer.limit() != size) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
ALC10.alcGetIntegerv(deviceId, param, buffer);
|
||||
}
|
||||
|
||||
public void alcDevicePauseSOFT() {
|
||||
SOFTPauseDevice.alcDevicePauseSOFT(deviceId);
|
||||
}
|
||||
|
||||
public void alcDeviceResumeSOFT() {
|
||||
SOFTPauseDevice.alcDeviceResumeSOFT(deviceId);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -66,7 +66,8 @@ public class GlfwKeyInput implements KeyInput {
|
||||
glfwSetKeyCallback(context.getWindowHandle(), keyCallback = new GLFWKeyCallback() {
|
||||
@Override
|
||||
public void invoke(long window, int key, int scancode, int action, int mods) {
|
||||
final KeyInputEvent evt = new KeyInputEvent(scancode, (char) key, GLFW_PRESS == action, GLFW_REPEAT == action);
|
||||
int jmeKey = GlfwKeyMap.toJmeKeyCode(key);
|
||||
final KeyInputEvent evt = new KeyInputEvent(jmeKey, (char) key, GLFW_PRESS == action, GLFW_REPEAT == action);
|
||||
evt.setTime(getInputTimeNanos());
|
||||
keyInputEvents.add(evt);
|
||||
}
|
||||
|
171
jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwKeyMap.java
Normal file
171
jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwKeyMap.java
Normal file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2015 jMonkeyEngine
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package com.jme3.input.lwjgl;
|
||||
|
||||
import static org.lwjgl.glfw.GLFW.*;
|
||||
import static com.jme3.input.KeyInput.*;
|
||||
|
||||
public class GlfwKeyMap {
|
||||
|
||||
private static final int[] glfwToJmeKeyMap = new int[GLFW_KEY_LAST + 1];
|
||||
|
||||
private static void reg(int jmeKey, int glfwKey) {
|
||||
glfwToJmeKeyMap[glfwKey] = jmeKey;
|
||||
}
|
||||
|
||||
static {
|
||||
reg(KEY_ESCAPE, GLFW_KEY_ESCAPE);
|
||||
reg(KEY_1, GLFW_KEY_1);
|
||||
reg(KEY_2, GLFW_KEY_2);
|
||||
reg(KEY_3, GLFW_KEY_3);
|
||||
reg(KEY_4, GLFW_KEY_4);
|
||||
reg(KEY_5, GLFW_KEY_5);
|
||||
reg(KEY_6, GLFW_KEY_6);
|
||||
reg(KEY_7, GLFW_KEY_7);
|
||||
reg(KEY_8, GLFW_KEY_8);
|
||||
reg(KEY_9, GLFW_KEY_9);
|
||||
reg(KEY_0, GLFW_KEY_0);
|
||||
reg(KEY_MINUS, GLFW_KEY_MINUS);
|
||||
reg(KEY_EQUALS, GLFW_KEY_EQUAL);
|
||||
reg(KEY_BACK, GLFW_KEY_BACKSPACE);
|
||||
reg(KEY_TAB, GLFW_KEY_TAB);
|
||||
reg(KEY_Q, GLFW_KEY_Q);
|
||||
reg(KEY_W, GLFW_KEY_W);
|
||||
reg(KEY_E, GLFW_KEY_E);
|
||||
reg(KEY_R, GLFW_KEY_R);
|
||||
reg(KEY_T, GLFW_KEY_T);
|
||||
reg(KEY_Y, GLFW_KEY_Y);
|
||||
reg(KEY_U, GLFW_KEY_U);
|
||||
reg(KEY_I, GLFW_KEY_I);
|
||||
reg(KEY_O, GLFW_KEY_O);
|
||||
reg(KEY_P, GLFW_KEY_P);
|
||||
reg(KEY_LBRACKET, GLFW_KEY_LEFT_BRACKET);
|
||||
reg(KEY_RBRACKET, GLFW_KEY_RIGHT_BRACKET);
|
||||
reg(KEY_RETURN, GLFW_KEY_ENTER);
|
||||
reg(KEY_LCONTROL, GLFW_KEY_LEFT_CONTROL);
|
||||
reg(KEY_A, GLFW_KEY_A);
|
||||
reg(KEY_S, GLFW_KEY_S);
|
||||
reg(KEY_D, GLFW_KEY_D);
|
||||
reg(KEY_F, GLFW_KEY_F);
|
||||
reg(KEY_G, GLFW_KEY_G);
|
||||
reg(KEY_H, GLFW_KEY_H);
|
||||
reg(KEY_J, GLFW_KEY_J);
|
||||
reg(KEY_K, GLFW_KEY_K);
|
||||
reg(KEY_L, GLFW_KEY_L);
|
||||
reg(KEY_SEMICOLON, GLFW_KEY_SEMICOLON);
|
||||
reg(KEY_APOSTROPHE, GLFW_KEY_APOSTROPHE);
|
||||
reg(KEY_GRAVE, GLFW_KEY_GRAVE_ACCENT);
|
||||
reg(KEY_LSHIFT, GLFW_KEY_LEFT_SHIFT);
|
||||
reg(KEY_BACKSLASH, GLFW_KEY_BACKSLASH);
|
||||
reg(KEY_Z, GLFW_KEY_Z);
|
||||
reg(KEY_X, GLFW_KEY_X);
|
||||
reg(KEY_C, GLFW_KEY_C);
|
||||
reg(KEY_V, GLFW_KEY_V);
|
||||
reg(KEY_B, GLFW_KEY_B);
|
||||
reg(KEY_N, GLFW_KEY_N);
|
||||
reg(KEY_M, GLFW_KEY_M);
|
||||
reg(KEY_COMMA, GLFW_KEY_COMMA);
|
||||
reg(KEY_PERIOD, GLFW_KEY_PERIOD);
|
||||
reg(KEY_SLASH, GLFW_KEY_SLASH);
|
||||
reg(KEY_RSHIFT, GLFW_KEY_RIGHT_SHIFT);
|
||||
reg(KEY_MULTIPLY, GLFW_KEY_KP_MULTIPLY);
|
||||
reg(KEY_LMENU, GLFW_KEY_LEFT_ALT);
|
||||
reg(KEY_SPACE, GLFW_KEY_SPACE);
|
||||
reg(KEY_CAPITAL, GLFW_KEY_CAPS_LOCK);
|
||||
reg(KEY_F1, GLFW_KEY_F1);
|
||||
reg(KEY_F2, GLFW_KEY_F2);
|
||||
reg(KEY_F3, GLFW_KEY_F3);
|
||||
reg(KEY_F4, GLFW_KEY_F4);
|
||||
reg(KEY_F5, GLFW_KEY_F5);
|
||||
reg(KEY_F6, GLFW_KEY_F6);
|
||||
reg(KEY_F7, GLFW_KEY_F7);
|
||||
reg(KEY_F8, GLFW_KEY_F8);
|
||||
reg(KEY_F9, GLFW_KEY_F9);
|
||||
reg(KEY_F10, GLFW_KEY_F10);
|
||||
reg(KEY_NUMLOCK, GLFW_KEY_NUM_LOCK);
|
||||
reg(KEY_SCROLL, GLFW_KEY_SCROLL_LOCK);
|
||||
reg(KEY_NUMPAD7, GLFW_KEY_KP_7);
|
||||
reg(KEY_NUMPAD8, GLFW_KEY_KP_8);
|
||||
reg(KEY_NUMPAD9, GLFW_KEY_KP_9);
|
||||
reg(KEY_SUBTRACT, GLFW_KEY_KP_SUBTRACT);
|
||||
reg(KEY_NUMPAD4, GLFW_KEY_KP_4);
|
||||
reg(KEY_NUMPAD5, GLFW_KEY_KP_5);
|
||||
reg(KEY_NUMPAD6, GLFW_KEY_KP_6);
|
||||
reg(KEY_ADD, GLFW_KEY_KP_ADD);
|
||||
reg(KEY_NUMPAD1, GLFW_KEY_KP_1);
|
||||
reg(KEY_NUMPAD2, GLFW_KEY_KP_2);
|
||||
reg(KEY_NUMPAD3, GLFW_KEY_KP_3);
|
||||
reg(KEY_NUMPAD0, GLFW_KEY_KP_0);
|
||||
reg(KEY_DECIMAL, GLFW_KEY_KP_DECIMAL);
|
||||
reg(KEY_F11, GLFW_KEY_F11);
|
||||
reg(KEY_F12, GLFW_KEY_F12);
|
||||
reg(KEY_F13, GLFW_KEY_F13);
|
||||
reg(KEY_F14, GLFW_KEY_F14);
|
||||
reg(KEY_F15, GLFW_KEY_F15);
|
||||
//reg(KEY_KANA, GLFW_KEY_);
|
||||
//reg(KEY_CONVERT, GLFW_KEY_);
|
||||
//reg(KEY_NOCONVERT, GLFW_KEY_);
|
||||
//reg(KEY_YEN, GLFW_KEY_);
|
||||
//reg(KEY_NUMPADEQUALS, GLFW_KEY_);
|
||||
//reg(KEY_CIRCUMFLEX, GLFW_KEY_);
|
||||
//reg(KEY_AT, GLFW_KEY_);
|
||||
//reg(KEY_COLON, GLFW_KEY_);
|
||||
//reg(KEY_UNDERLINE, GLFW_KEY_);
|
||||
//reg(KEY_KANJI, GLFW_KEY_);
|
||||
//reg(KEY_STOP, GLFW_KEY_);
|
||||
//reg(KEY_AX, GLFW_KEY_);
|
||||
//reg(KEY_UNLABELED, GLFW_KEY_);
|
||||
reg(KEY_NUMPADENTER, GLFW_KEY_KP_ENTER);
|
||||
reg(KEY_RCONTROL, GLFW_KEY_RIGHT_CONTROL);
|
||||
//reg(KEY_NUMPADCOMMA, GLFW_KEY_);
|
||||
reg(KEY_DIVIDE, GLFW_KEY_KP_DIVIDE);
|
||||
reg(KEY_SYSRQ, GLFW_KEY_PRINT_SCREEN);
|
||||
reg(KEY_RMENU, GLFW_KEY_RIGHT_ALT);
|
||||
reg(KEY_PAUSE, GLFW_KEY_PAUSE);
|
||||
reg(KEY_HOME, GLFW_KEY_HOME);
|
||||
reg(KEY_UP, GLFW_KEY_UP);
|
||||
reg(KEY_PRIOR, GLFW_KEY_PAGE_UP);
|
||||
reg(KEY_LEFT, GLFW_KEY_LEFT);
|
||||
reg(KEY_RIGHT, GLFW_KEY_RIGHT);
|
||||
reg(KEY_END, GLFW_KEY_END);
|
||||
reg(KEY_DOWN, GLFW_KEY_DOWN);
|
||||
reg(KEY_NEXT, GLFW_KEY_PAGE_DOWN);
|
||||
reg(KEY_INSERT, GLFW_KEY_INSERT);
|
||||
reg(KEY_DELETE, GLFW_KEY_DELETE);
|
||||
reg(KEY_LMETA, GLFW_KEY_LEFT_SUPER);
|
||||
reg(KEY_RMETA, GLFW_KEY_RIGHT_SUPER);
|
||||
}
|
||||
|
||||
public static int toJmeKeyCode(int glfwKey) {
|
||||
return glfwToJmeKeyMap[glfwKey];
|
||||
}
|
||||
}
|
@ -38,16 +38,22 @@ import com.jme3.input.RawInputListener;
|
||||
import com.jme3.input.event.MouseButtonEvent;
|
||||
import com.jme3.input.event.MouseMotionEvent;
|
||||
import com.jme3.system.lwjgl.LwjglWindow;
|
||||
import com.jme3.util.BufferUtils;
|
||||
import org.lwjgl.glfw.GLFWCursorPosCallback;
|
||||
import org.lwjgl.glfw.GLFWMouseButtonCallback;
|
||||
import org.lwjgl.glfw.GLFWScrollCallback;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static org.lwjgl.glfw.GLFW.*;
|
||||
import org.lwjgl.glfw.GLFWImage;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
/**
|
||||
* Captures mouse input using GLFW callbacks. It then temporarily stores these in event queues which are processed in the
|
||||
@ -74,57 +80,70 @@ public class GlfwMouseInput implements MouseInput {
|
||||
private Queue<MouseMotionEvent> mouseMotionEvents = new LinkedList<MouseMotionEvent>();
|
||||
private Queue<MouseButtonEvent> mouseButtonEvents = new LinkedList<MouseButtonEvent>();
|
||||
|
||||
public GlfwMouseInput(final LwjglWindow context) {
|
||||
private Map<JmeCursor, Long> jmeToGlfwCursorMap = new HashMap<JmeCursor, Long>();
|
||||
|
||||
public GlfwMouseInput(LwjglWindow context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
private void onCursorPos(long window, double xpos, double ypos) {
|
||||
int xDelta;
|
||||
int yDelta;
|
||||
int x = (int) Math.round(xpos);
|
||||
int y = context.getSettings().getHeight() - (int) Math.round(ypos);
|
||||
|
||||
if (mouseX == 0) {
|
||||
mouseX = x;
|
||||
}
|
||||
|
||||
if (mouseY == 0) {
|
||||
mouseY = y;
|
||||
}
|
||||
|
||||
xDelta = x - mouseX;
|
||||
yDelta = y - mouseY;
|
||||
mouseX = x;
|
||||
mouseY = y;
|
||||
|
||||
if (xDelta != 0 || yDelta != 0) {
|
||||
final MouseMotionEvent mouseMotionEvent = new MouseMotionEvent(x, y, xDelta, yDelta, mouseWheel, 0);
|
||||
mouseMotionEvent.setTime(getInputTimeNanos());
|
||||
mouseMotionEvents.add(mouseMotionEvent);
|
||||
}
|
||||
}
|
||||
|
||||
private void onWheelScroll(long window, double xOffset, double yOffset) {
|
||||
mouseWheel += yOffset;
|
||||
final MouseMotionEvent mouseMotionEvent = new MouseMotionEvent(mouseX, mouseY, 0, 0, mouseWheel, (int) Math.round(yOffset));
|
||||
mouseMotionEvent.setTime(getInputTimeNanos());
|
||||
mouseMotionEvents.add(mouseMotionEvent);
|
||||
}
|
||||
|
||||
private void onMouseButton(final long window, final int button, final int action, final int mods) {
|
||||
final MouseButtonEvent mouseButtonEvent = new MouseButtonEvent(convertButton(button), action == GLFW_PRESS, mouseX, mouseY);
|
||||
mouseButtonEvent.setTime(getInputTimeNanos());
|
||||
mouseButtonEvents.add(mouseButtonEvent);
|
||||
}
|
||||
|
||||
public void initialize() {
|
||||
glfwSetCursorPosCallback(context.getWindowHandle(), cursorPosCallback = new GLFWCursorPosCallback() {
|
||||
@Override
|
||||
public void invoke(long window, double xpos, double ypos) {
|
||||
int xDelta;
|
||||
int yDelta;
|
||||
int x = (int) Math.round(xpos);
|
||||
int y = context.getSettings().getHeight() - (int) Math.round(ypos);
|
||||
|
||||
if (mouseX == 0) {
|
||||
mouseX = x;
|
||||
}
|
||||
|
||||
if (mouseY == 0) {
|
||||
mouseY = y;
|
||||
}
|
||||
|
||||
xDelta = x - mouseX;
|
||||
yDelta = y - mouseY;
|
||||
mouseX = x;
|
||||
mouseY = y;
|
||||
|
||||
if (xDelta != 0 || yDelta != 0) {
|
||||
final MouseMotionEvent mouseMotionEvent = new MouseMotionEvent(x, y, xDelta, yDelta, mouseWheel, 0);
|
||||
mouseMotionEvent.setTime(getInputTimeNanos());
|
||||
mouseMotionEvents.add(mouseMotionEvent);
|
||||
}
|
||||
onCursorPos(window, xpos, ypos);
|
||||
}
|
||||
});
|
||||
|
||||
glfwSetScrollCallback(context.getWindowHandle(), scrollCallback = new GLFWScrollCallback() {
|
||||
@Override
|
||||
public void invoke(final long window, final double xOffset, final double yOffset) {
|
||||
mouseWheel += yOffset;
|
||||
|
||||
final MouseMotionEvent mouseMotionEvent = new MouseMotionEvent(mouseX, mouseY, 0, 0, mouseWheel, (int) Math.round(yOffset));
|
||||
mouseMotionEvent.setTime(getInputTimeNanos());
|
||||
mouseMotionEvents.add(mouseMotionEvent);
|
||||
onWheelScroll(window, xOffset, yOffset);
|
||||
}
|
||||
});
|
||||
|
||||
glfwSetMouseButtonCallback(context.getWindowHandle(), mouseButtonCallback = new GLFWMouseButtonCallback() {
|
||||
@Override
|
||||
public void invoke(final long window, final int button, final int action, final int mods) {
|
||||
final MouseButtonEvent mouseButtonEvent = new MouseButtonEvent(convertButton(button), action == GLFW_PRESS, mouseX, mouseY);
|
||||
mouseButtonEvent.setTime(getInputTimeNanos());
|
||||
mouseButtonEvents.add(mouseButtonEvent);
|
||||
onMouseButton(window, button, action, mods);
|
||||
}
|
||||
});
|
||||
|
||||
@ -160,6 +179,10 @@ public class GlfwMouseInput implements MouseInput {
|
||||
scrollCallback.release();
|
||||
mouseButtonCallback.release();
|
||||
|
||||
for (long glfwCursor : jmeToGlfwCursorMap.values()) {
|
||||
glfwDestroyCursor(glfwCursor);
|
||||
}
|
||||
|
||||
logger.fine("Mouse destroyed.");
|
||||
}
|
||||
|
||||
@ -185,31 +208,52 @@ public class GlfwMouseInput implements MouseInput {
|
||||
return (long) (glfwGetTime() * 1000000000);
|
||||
}
|
||||
|
||||
public void setNativeCursor(final JmeCursor jmeCursor) {
|
||||
private long createGlfwCursor(JmeCursor jmeCursor) {
|
||||
GLFWImage glfwImage = new GLFWImage(BufferUtils.createByteBuffer(GLFWImage.SIZEOF));
|
||||
|
||||
// TODO: currently animated cursors are not supported
|
||||
IntBuffer imageData = jmeCursor.getImagesData();
|
||||
ByteBuffer buf = BufferUtils.createByteBuffer(imageData.capacity());
|
||||
buf.asIntBuffer().put(imageData);
|
||||
|
||||
glfwImage.set(jmeCursor.getWidth(), jmeCursor.getHeight(), buf);
|
||||
|
||||
return glfwCreateCursor(glfwImage, jmeCursor.getXHotSpot(), jmeCursor.getYHotSpot());
|
||||
}
|
||||
|
||||
public void setNativeCursor(JmeCursor jmeCursor) {
|
||||
if (jmeCursor != null) {
|
||||
final ByteBuffer byteBuffer = org.lwjgl.BufferUtils.createByteBuffer(jmeCursor.getImagesData().capacity());
|
||||
byteBuffer.asIntBuffer().put(jmeCursor.getImagesData().array());
|
||||
final long cursor = glfwCreateCursor(byteBuffer, jmeCursor.getXHotSpot(), jmeCursor.getYHotSpot());
|
||||
glfwSetCursor(context.getWindowHandle(), cursor);
|
||||
Long glfwCursor = jmeToGlfwCursorMap.get(jmeCursor);
|
||||
|
||||
if (glfwCursor == null) {
|
||||
glfwCursor = createGlfwCursor(jmeCursor);
|
||||
jmeToGlfwCursorMap.put(jmeCursor, glfwCursor);
|
||||
}
|
||||
|
||||
glfwSetCursor(context.getWindowHandle(), glfwCursor);
|
||||
} else {
|
||||
glfwSetCursor(context.getWindowHandle(), MemoryUtil.NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Simply converts the GLFW button code to a JME button code. If there is no match it just returns the GLFW button
|
||||
* code. Bare in mind GLFW supports 8 different mouse buttons.
|
||||
* Simply converts the GLFW button code to a JME button code. If there is no
|
||||
* match it just returns the GLFW button code. Bear in mind GLFW supports 8
|
||||
* different mouse buttons.
|
||||
*
|
||||
* @param glfwButton the raw GLFW button index.
|
||||
* @return the mapped {@link MouseInput} button id.
|
||||
*/
|
||||
private int convertButton(final int glfwButton) {
|
||||
if (glfwButton == GLFW_MOUSE_BUTTON_LEFT) {
|
||||
return MouseInput.BUTTON_LEFT;
|
||||
} else if(glfwButton == GLFW_MOUSE_BUTTON_MIDDLE) {
|
||||
return MouseInput.BUTTON_MIDDLE;
|
||||
} else if(glfwButton == GLFW_MOUSE_BUTTON_RIGHT) {
|
||||
return MouseInput.BUTTON_RIGHT;
|
||||
switch (glfwButton) {
|
||||
case GLFW_MOUSE_BUTTON_LEFT:
|
||||
return MouseInput.BUTTON_LEFT;
|
||||
case GLFW_MOUSE_BUTTON_MIDDLE:
|
||||
return MouseInput.BUTTON_MIDDLE;
|
||||
case GLFW_MOUSE_BUTTON_RIGHT:
|
||||
return MouseInput.BUTTON_RIGHT;
|
||||
default:
|
||||
return glfwButton;
|
||||
}
|
||||
|
||||
return glfwButton;
|
||||
}
|
||||
}
|
||||
|
@ -43,9 +43,7 @@ import com.jme3.renderer.lwjgl.LwjglGLFboEXT;
|
||||
import com.jme3.renderer.lwjgl.LwjglGLFboGL3;
|
||||
import com.jme3.renderer.opengl.*;
|
||||
import com.jme3.system.*;
|
||||
import org.lwjgl.Sys;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
import org.lwjgl.opengl.ARBDebugOutput;
|
||||
import org.lwjgl.opengl.ARBFramebufferObject;
|
||||
import org.lwjgl.opengl.EXTFramebufferMultisample;
|
||||
import org.lwjgl.opengl.GLCapabilities;
|
||||
@ -53,9 +51,10 @@ import org.lwjgl.opengl.GLCapabilities;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_TRUE;
|
||||
import org.lwjgl.opengl.ARBDebugOutput;
|
||||
|
||||
import static org.lwjgl.opengl.GL.createCapabilities;
|
||||
import static org.lwjgl.opengl.GL11.GL_TRUE;
|
||||
import static org.lwjgl.opengl.GL11.glGetInteger;
|
||||
|
||||
/**
|
||||
@ -84,16 +83,16 @@ public abstract class LwjglContext implements JmeContext {
|
||||
}
|
||||
|
||||
protected void printContextInitInfo() {
|
||||
logger.log(Level.INFO, "LWJGL {0} context running on thread {1}\n" +
|
||||
" * Graphics Adapter: GLFW {2}",
|
||||
new Object[]{Sys.getVersion(), Thread.currentThread().getName(), GLFW.glfwGetVersionString()});
|
||||
logger.log(Level.INFO, "LWJGL {0} context running on thread {1}\n"
|
||||
+ " * Graphics Adapter: GLFW {2}",
|
||||
new Object[]{org.lwjgl.Version.getVersion(), Thread.currentThread().getName(), GLFW.glfwGetVersionString()});
|
||||
}
|
||||
|
||||
protected int determineMaxSamples() {
|
||||
// If we already have a valid context, determine samples using current context.
|
||||
if (GLFW.glfwExtensionSupported("GL_ARB_framebuffer_object") == GL_TRUE) {
|
||||
if (GLFW.glfwExtensionSupported("GL_ARB_framebuffer_object") == GLFW_TRUE) {
|
||||
return glGetInteger(ARBFramebufferObject.GL_MAX_SAMPLES);
|
||||
} else if (GLFW.glfwExtensionSupported("GL_EXT_framebuffer_multisample") == GL_TRUE) {
|
||||
} else if (GLFW.glfwExtensionSupported("GL_EXT_framebuffer_multisample") == GLFW_TRUE) {
|
||||
return glGetInteger(EXTFramebufferMultisample.GL_MAX_SAMPLES_EXT);
|
||||
}
|
||||
|
||||
@ -180,11 +179,11 @@ public abstract class LwjglContext implements JmeContext {
|
||||
}
|
||||
|
||||
if (capabilities.GL_ARB_debug_output && settings.getBoolean("GraphicsDebug")) {
|
||||
ARBDebugOutput.glDebugMessageCallbackARB(new LwjglGLDebugOutputHandler(), 0); // User param is zero. Not sure what we could use that for.
|
||||
ARBDebugOutput.glDebugMessageCallbackARB(new LwjglGLDebugOutputHandler(), 0);
|
||||
}
|
||||
|
||||
renderer.setMainFrameBufferSrgb(settings.getGammaCorrection());
|
||||
renderer.setLinearizeSrgbImages(settings.getGammaCorrection());
|
||||
renderer.setMainFrameBufferSrgb(settings.isGammaCorrection());
|
||||
renderer.setLinearizeSrgbImages(settings.isGammaCorrection());
|
||||
|
||||
// Init input
|
||||
if (keyInput != null) {
|
||||
@ -198,7 +197,6 @@ public abstract class LwjglContext implements JmeContext {
|
||||
if (joyInput != null) {
|
||||
joyInput.initialize();
|
||||
}
|
||||
|
||||
renderable.set(true);
|
||||
}
|
||||
|
||||
@ -240,26 +238,32 @@ public abstract class LwjglContext implements JmeContext {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCreated() {
|
||||
return created.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRenderable() {
|
||||
return renderable.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSettings(AppSettings settings) {
|
||||
this.settings.copyFrom(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AppSettings getSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Renderer getRenderer() {
|
||||
return renderer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Timer getTimer() {
|
||||
return timer;
|
||||
}
|
||||
|
@ -43,7 +43,6 @@ import com.jme3.system.AppSettings;
|
||||
import com.jme3.system.JmeContext;
|
||||
import com.jme3.system.JmeSystem;
|
||||
import com.jme3.system.NanoTimer;
|
||||
import org.lwjgl.Sys;
|
||||
import org.lwjgl.glfw.*;
|
||||
|
||||
import java.awt.*;
|
||||
@ -52,6 +51,7 @@ import java.nio.ByteBuffer;
|
||||
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 static org.lwjgl.opengl.GL11.GL_FALSE;
|
||||
@ -72,7 +72,7 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
||||
protected boolean wasActive = false;
|
||||
protected boolean autoFlush = true;
|
||||
protected boolean allowSwapBuffers = false;
|
||||
private long window = -1;
|
||||
private long window = NULL;
|
||||
private final JmeContext.Type type;
|
||||
private int frameRateLimit = -1;
|
||||
private double frameSleepTime;
|
||||
@ -102,7 +102,7 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
||||
* @param title the title to set
|
||||
*/
|
||||
public void setTitle(final String title) {
|
||||
if (created.get() && window != -1) {
|
||||
if (created.get() && window != NULL) {
|
||||
glfwSetWindowTitle(window, title);
|
||||
}
|
||||
}
|
||||
@ -127,45 +127,45 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
||||
glfwSetErrorCallback(errorCallback = new GLFWErrorCallback() {
|
||||
@Override
|
||||
public void invoke(int error, long description) {
|
||||
final String message = Callbacks.errorCallbackDescriptionString(description);
|
||||
final String message = GLFWErrorCallback.getDescription(description);
|
||||
listener.handleError(message, new Exception(message));
|
||||
}
|
||||
});
|
||||
|
||||
if (glfwInit() != GL_TRUE) {
|
||||
if (glfwInit() != GLFW_TRUE) {
|
||||
throw new IllegalStateException("Unable to initialize GLFW");
|
||||
}
|
||||
|
||||
glfwDefaultWindowHints();
|
||||
|
||||
if (settings.getRenderer().equals(AppSettings.LWJGL_OPENGL3)) {
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
|
||||
} else {
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
||||
}
|
||||
|
||||
if (settings.getBoolean("RendererDebug")) {
|
||||
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE);
|
||||
}
|
||||
|
||||
if (settings.isGammaCorrection()) {
|
||||
glfwWindowHint(GLFW_SRGB_CAPABLE, GLFW_TRUE);
|
||||
}
|
||||
|
||||
glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
|
||||
glfwWindowHint(GLFW_RESIZABLE, settings.isResizable() ? GLFW_TRUE : GLFW_FALSE);
|
||||
|
||||
// TODO: Add support for monitor selection
|
||||
long monitor = NULL;
|
||||
|
||||
if (settings.isFullscreen()) {
|
||||
monitor = glfwGetPrimaryMonitor();
|
||||
}
|
||||
|
||||
final ByteBuffer videoMode = glfwGetVideoMode(glfwGetPrimaryMonitor());
|
||||
|
||||
if (settings.getWidth() <= 0 || settings.getHeight() <= 0) {
|
||||
settings.setResolution(GLFWvidmode.width(videoMode), GLFWvidmode.height(videoMode));
|
||||
}
|
||||
|
||||
window = glfwCreateWindow(settings.getWidth(), settings.getHeight(), settings.getTitle(), monitor, NULL);
|
||||
|
||||
if (window == NULL) {
|
||||
throw new RuntimeException("Failed to create the GLFW window");
|
||||
}
|
||||
|
||||
glfwWindowHint(GLFW_RESIZABLE, settings.isResizable() ? GL_TRUE : GL_FALSE);
|
||||
glfwWindowHint(GLFW_DOUBLE_BUFFER, GLFW_TRUE);
|
||||
glfwWindowHint(GLFW_DEPTH_BITS, settings.getDepthBits());
|
||||
glfwWindowHint(GLFW_STENCIL_BITS, settings.getStencilBits());
|
||||
glfwWindowHint(GLFW_SAMPLES, settings.getSamples());
|
||||
glfwWindowHint(GLFW_STEREO, settings.useStereo3D() ? GL_TRUE : GL_FALSE);
|
||||
glfwWindowHint(GLFW_STEREO, settings.useStereo3D() ? GLFW_TRUE : GLFW_FALSE);
|
||||
glfwWindowHint(GLFW_REFRESH_RATE, settings.getFrequency());
|
||||
|
||||
// Not sure how else to support bits per pixel
|
||||
if (settings.getBitsPerPixel() == 24) {
|
||||
glfwWindowHint(GLFW_RED_BITS, 8);
|
||||
glfwWindowHint(GLFW_GREEN_BITS, 8);
|
||||
@ -178,6 +178,34 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
||||
|
||||
glfwWindowHint(GLFW_ALPHA_BITS, settings.getAlphaBits());
|
||||
|
||||
// TODO: Add support for monitor selection
|
||||
long monitor = NULL;
|
||||
|
||||
if (settings.isFullscreen()) {
|
||||
monitor = glfwGetPrimaryMonitor();
|
||||
}
|
||||
|
||||
final GLFWVidMode videoMode = glfwGetVideoMode(glfwGetPrimaryMonitor());
|
||||
|
||||
if (settings.getWidth() <= 0 || settings.getHeight() <= 0) {
|
||||
settings.setResolution(videoMode.width(), videoMode.height());
|
||||
}
|
||||
|
||||
window = glfwCreateWindow(settings.getWidth(), settings.getHeight(), settings.getTitle(), monitor, NULL);
|
||||
|
||||
if (window == NULL) {
|
||||
throw new RuntimeException("Failed to create the GLFW window");
|
||||
}
|
||||
|
||||
// Add a resize callback which delegates to the listener
|
||||
glfwSetWindowSizeCallback(window, windowSizeCallback = new GLFWWindowSizeCallback() {
|
||||
@Override
|
||||
public void invoke(final long window, final int width, final int height) {
|
||||
settings.setResolution(width, height);
|
||||
listener.reshape(width, height);
|
||||
}
|
||||
});
|
||||
|
||||
glfwSetWindowFocusCallback(window, windowFocusCallback = new GLFWWindowFocusCallback() {
|
||||
@Override
|
||||
public void invoke(final long window, final int focused) {
|
||||
@ -197,8 +225,10 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
||||
});
|
||||
|
||||
// Center the window
|
||||
if (!settings.isFullscreen() && Type.Display.equals(type)) {
|
||||
glfwSetWindowPos(window, (GLFWvidmode.width(videoMode) - settings.getWidth()) / 2, (GLFWvidmode.height(videoMode) - settings.getHeight()) / 2);
|
||||
if (!settings.isFullscreen()) {
|
||||
glfwSetWindowPos(window,
|
||||
(videoMode.width() - settings.getWidth()) / 2,
|
||||
(videoMode.height() - settings.getHeight()) / 2);
|
||||
}
|
||||
|
||||
// Make the OpenGL context current
|
||||
@ -216,14 +246,7 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
||||
glfwShowWindow(window);
|
||||
}
|
||||
|
||||
// Add a resize callback which delegates to the listener
|
||||
glfwSetWindowSizeCallback(window, windowSizeCallback = new GLFWWindowSizeCallback() {
|
||||
@Override
|
||||
public void invoke(final long window, final int width, final int height) {
|
||||
settings.setResolution(width, height);
|
||||
listener.reshape(width, height);
|
||||
}
|
||||
});
|
||||
glfwShowWindow(window);
|
||||
|
||||
allowSwapBuffers = settings.isSwapBuffers();
|
||||
|
||||
@ -239,12 +262,24 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
||||
renderer.cleanup();
|
||||
}
|
||||
|
||||
errorCallback.release();
|
||||
windowSizeCallback.release();
|
||||
windowFocusCallback.release();
|
||||
if (errorCallback != null) {
|
||||
errorCallback.release();
|
||||
errorCallback = null;
|
||||
}
|
||||
|
||||
if (window != 0) {
|
||||
if (windowSizeCallback != null) {
|
||||
windowSizeCallback.release();
|
||||
windowSizeCallback = null;
|
||||
}
|
||||
|
||||
if (windowFocusCallback != null) {
|
||||
windowFocusCallback.release();
|
||||
windowFocusCallback = null;
|
||||
}
|
||||
|
||||
if (window != NULL) {
|
||||
glfwDestroyWindow(window);
|
||||
window = NULL;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
listener.handleError("Failed to destroy context", ex);
|
||||
@ -296,8 +331,9 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
||||
super.internalCreate();
|
||||
} catch (Exception ex) {
|
||||
try {
|
||||
if (window != -1) {
|
||||
if (window != NULL) {
|
||||
glfwDestroyWindow(window);
|
||||
window = NULL;
|
||||
}
|
||||
} catch (Exception ex2) {
|
||||
LOGGER.log(Level.WARNING, null, ex2);
|
||||
@ -318,6 +354,7 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
||||
// If a restart is required, lets recreate the context.
|
||||
if (needRestart.getAndSet(false)) {
|
||||
try {
|
||||
destroyContext();
|
||||
createContext(settings);
|
||||
} catch (Exception ex) {
|
||||
LOGGER.log(Level.SEVERE, "Failed to set display settings!", ex);
|
||||
@ -346,8 +383,6 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
glfwPollEvents();
|
||||
|
||||
// Subclasses just call GLObjectManager clean up objects here
|
||||
// it is safe .. for now.
|
||||
if (renderer != null) {
|
||||
@ -377,6 +412,8 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
private void setFrameRateLimit(int frameRateLimit) {
|
||||
@ -389,11 +426,12 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
||||
*/
|
||||
|
||||
protected void deinitInThread() {
|
||||
destroyContext();
|
||||
|
||||
listener.destroy();
|
||||
LOGGER.fine("Display destroyed.");
|
||||
|
||||
destroyContext();
|
||||
super.internalDestroy();
|
||||
|
||||
LOGGER.fine("Display destroyed.");
|
||||
}
|
||||
|
||||
public void run() {
|
||||
@ -403,7 +441,7 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
||||
}
|
||||
|
||||
loadNatives();
|
||||
LOGGER.log(Level.FINE, "Using LWJGL {0}", Sys.getVersion());
|
||||
LOGGER.log(Level.FINE, "Using LWJGL {0}", Version.getVersion());
|
||||
|
||||
if (!initInThread()) {
|
||||
LOGGER.log(Level.SEVERE, "Display initialization failed. Cannot continue.");
|
||||
@ -411,15 +449,16 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (glfwWindowShouldClose(window) == GL_TRUE) {
|
||||
listener.requestClose(false);
|
||||
}
|
||||
|
||||
runLoop();
|
||||
|
||||
if (needClose.get()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (glfwWindowShouldClose(window) == GL_TRUE) {
|
||||
listener.requestClose(false);
|
||||
}
|
||||
}
|
||||
|
||||
deinitInThread();
|
||||
|
Loading…
x
Reference in New Issue
Block a user