Skip to content

Commit 1198908

Browse files
tonihelepspeed42
authored andcommitted
Lwjgl3 restart input handle (#1268)
* Reinit inputs on context restart * Added test issue from issue #1013 * Verify that the inputs are already initialized
1 parent fecd018 commit 1198908

File tree

4 files changed

+210
-32
lines changed

4 files changed

+210
-32
lines changed
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/*
2+
* Copyright (c) 2009-2020 jMonkeyEngine
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are
7+
* met:
8+
*
9+
* * Redistributions of source code must retain the above copyright
10+
* notice, this list of conditions and the following disclaimer.
11+
*
12+
* * Redistributions in binary form must reproduce the above copyright
13+
* notice, this list of conditions and the following disclaimer in the
14+
* documentation and/or other materials provided with the distribution.
15+
*
16+
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17+
* may be used to endorse or promote products derived from this software
18+
* without specific prior written permission.
19+
*
20+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22+
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24+
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25+
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26+
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27+
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28+
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29+
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31+
*/
32+
package jme3test.niftygui;
33+
34+
import com.jme3.app.SimpleApplication;
35+
import com.jme3.material.Material;
36+
import com.jme3.niftygui.NiftyJmeDisplay;
37+
import com.jme3.scene.Geometry;
38+
import com.jme3.scene.shape.Box;
39+
import de.lessvoid.nifty.Nifty;
40+
import de.lessvoid.nifty.builder.LayerBuilder;
41+
import de.lessvoid.nifty.builder.PanelBuilder;
42+
import de.lessvoid.nifty.builder.ScreenBuilder;
43+
import de.lessvoid.nifty.controls.button.builder.ButtonBuilder;
44+
import de.lessvoid.nifty.screen.Screen;
45+
import de.lessvoid.nifty.screen.ScreenController;
46+
47+
public class TestIssue1013 extends SimpleApplication implements ScreenController {
48+
49+
public static void main(String[] args) {
50+
new TestIssue1013().start();
51+
}
52+
53+
private NiftyJmeDisplay niftyDisplay;
54+
55+
@Override
56+
public void simpleInitApp() {
57+
58+
// this box here always renders
59+
Box b = new Box(1, 1, 1);
60+
Geometry geom = new Geometry("Box", b);
61+
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
62+
mat.setTexture("ColorMap", assetManager.loadTexture("/com/jme3/app/Monkey.png"));
63+
geom.setMaterial(mat);
64+
rootNode.attachChild(geom);
65+
66+
niftyDisplay = NiftyJmeDisplay.newNiftyJmeDisplay(assetManager, inputManager, audioRenderer, guiViewPort);
67+
68+
Nifty nifty = niftyDisplay.getNifty();
69+
nifty.loadStyleFile("nifty-default-styles.xml");
70+
nifty.loadControlFile("nifty-default-controls.xml");
71+
72+
ScreenController ctrl = this;
73+
74+
new ScreenBuilder("start") {
75+
{
76+
controller(ctrl);
77+
layer(new LayerBuilder() {
78+
{
79+
childLayoutVertical();
80+
panel(new PanelBuilder() {
81+
{
82+
childLayoutCenter();
83+
width("100%");
84+
height("50%");
85+
backgroundColor("#ff0000");
86+
}
87+
});
88+
control(new ButtonBuilder("RestartButton", "Restart Context") {
89+
{
90+
alignCenter();
91+
valignCenter();
92+
height("32px");
93+
width("480px");
94+
interactOnClick("restartContext()");
95+
}
96+
});
97+
}
98+
});
99+
}
100+
}.build(nifty);
101+
102+
guiViewPort.addProcessor(niftyDisplay);
103+
nifty.gotoScreen("start");
104+
105+
flyCam.setDragToRotate(true);
106+
}
107+
108+
@Override
109+
public void bind(Nifty nifty, Screen screen) {
110+
}
111+
112+
@Override
113+
public void onStartScreen() {
114+
}
115+
116+
@Override
117+
public void onEndScreen() {
118+
}
119+
120+
public void restartContext() {
121+
// even without changing settings, stuff breaks!
122+
restart();
123+
// ...and re-adding the processor doesn't help at all
124+
guiViewPort.addProcessor(niftyDisplay);
125+
}
126+
127+
}

jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwKeyInput.java

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,33 @@ public GlfwKeyInput(final LwjglWindow context) {
8383

8484
@Override
8585
public void initialize() {
86+
if (!context.isRenderable()) {
87+
return;
88+
}
89+
initCallbacks();
90+
91+
initialized = true;
92+
logger.fine("Keyboard created.");
93+
}
8694

95+
/**
96+
* Re-initializes the key input context window specific callbacks
97+
*/
98+
public void resetContext() {
8799
if (!context.isRenderable()) {
88100
return;
89101
}
90102

103+
closeCallbacks();
104+
initCallbacks();
105+
}
106+
107+
private void closeCallbacks() {
108+
keyCallback.close();
109+
charCallback.close();
110+
}
111+
112+
private void initCallbacks() {
91113
glfwSetKeyCallback(context.getWindowHandle(), keyCallback = new GLFWKeyCallback() {
92114
@Override
93115
public void invoke(final long window, final int key, final int scancode, final int action, final int mods) {
@@ -122,9 +144,6 @@ public void invoke(final long window, final int codepoint) {
122144
keyInputEvents.add(released);
123145
}
124146
});
125-
126-
initialized = true;
127-
logger.fine("Keyboard created.");
128147
}
129148

130149
public int getKeyCount() {
@@ -149,8 +168,7 @@ public void destroy() {
149168
return;
150169
}
151170

152-
keyCallback.close();
153-
charCallback.close();
171+
closeCallbacks();
154172
logger.fine("Keyboard destroyed.");
155173
}
156174

jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwMouseInput.java

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,30 @@ private void onMouseButton(final long window, final int button, final int action
176176

177177
@Override
178178
public void initialize() {
179+
initCallbacks();
179180

181+
if (listener != null) {
182+
sendFirstMouseEvent();
183+
}
184+
185+
setCursorVisible(cursorVisible);
186+
logger.fine("Mouse created.");
187+
initialized = true;
188+
}
189+
190+
/**
191+
* Re-initializes the mouse input context window specific callbacks
192+
*/
193+
public void resetContext() {
194+
if (!context.isRenderable()) {
195+
return;
196+
}
197+
198+
closeCallbacks();
199+
initCallbacks();
200+
}
201+
202+
private void initCallbacks() {
180203
final long window = context.getWindowHandle();
181204

182205
try (MemoryStack stack = MemoryStack.stackPush()) {
@@ -219,14 +242,6 @@ public void invoke(final long window, final int width, final int height) {
219242
currentWidth = width;
220243
}
221244
});
222-
223-
if(listener != null) {
224-
sendFirstMouseEvent();
225-
}
226-
227-
setCursorVisible(cursorVisible);
228-
logger.fine("Mouse created.");
229-
initialized = true;
230245
}
231246

232247
private void initCurrentMousePosition(long window) {
@@ -295,9 +310,7 @@ public void destroy() {
295310
return;
296311
}
297312

298-
cursorPosCallback.close();
299-
scrollCallback.close();
300-
mouseButtonCallback.close();
313+
closeCallbacks();
301314

302315
currentCursor = null;
303316
currentCursorDelays = null;
@@ -313,6 +326,12 @@ public void destroy() {
313326
logger.fine("Mouse destroyed.");
314327
}
315328

329+
private void closeCallbacks() {
330+
cursorPosCallback.close();
331+
scrollCallback.close();
332+
mouseButtonCallback.close();
333+
}
334+
316335
@Override
317336
public void setCursorVisible(boolean visible) {
318337
cursorVisible = visible;

jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,11 @@ public void invoke(final long window, final boolean focus) {
295295
showWindow();
296296

297297
allowSwapBuffers = settings.isSwapBuffers();
298+
299+
// Create OpenCL
300+
if (settings.isOpenCLSupport()) {
301+
initOpenCL(window);
302+
}
298303
}
299304

300305
protected void showWindow() {
@@ -303,6 +308,8 @@ protected void showWindow() {
303308

304309
/**
305310
* Set custom icons to the window of this application.
311+
*
312+
* @param settings settings for getting the icons
306313
*/
307314
protected void setWindowIcon(final AppSettings settings) {
308315

@@ -409,7 +416,6 @@ protected void destroyContext() {
409416
window = NULL;
410417
}
411418

412-
glfwTerminate();
413419
} catch (final Exception ex) {
414420
listener.handleError("Failed to destroy context", ex);
415421
}
@@ -429,6 +435,8 @@ public void create(boolean waitFor) {
429435

430436
/**
431437
* Does LWJGL display initialization in the OpenGL thread
438+
*
439+
* @return returns {@code true} if the context initialization was successful
432440
*/
433441
protected boolean initInThread() {
434442
try {
@@ -455,13 +463,6 @@ protected boolean initInThread() {
455463

456464
created.set(true);
457465
super.internalCreate();
458-
459-
//create OpenCL
460-
//Must be done here because the window handle is needed
461-
if (settings.isOpenCLSupport()) {
462-
initOpenCL(window);
463-
}
464-
465466
} catch (Exception ex) {
466467
try {
467468
if (window != NULL) {
@@ -486,14 +487,7 @@ protected boolean initInThread() {
486487
protected void runLoop() {
487488
// If a restart is required, lets recreate the context.
488489
if (needRestart.getAndSet(false)) {
489-
try {
490-
destroyContext();
491-
createContext(settings);
492-
} catch (Exception ex) {
493-
LOGGER.log(Level.SEVERE, "Failed to set display settings!", ex);
494-
}
495-
496-
LOGGER.fine("Display restarted.");
490+
restartContext();
497491
}
498492

499493
if (!created.get()) {
@@ -549,6 +543,25 @@ protected void runLoop() {
549543
glfwPollEvents();
550544
}
551545

546+
private void restartContext() {
547+
try {
548+
destroyContext();
549+
createContext(settings);
550+
} catch (Exception ex) {
551+
LOGGER.log(Level.SEVERE, "Failed to set display settings!", ex);
552+
}
553+
554+
// We need to reinit the mouse and keyboard input as they are tied to a window handle
555+
if (keyInput != null && keyInput.isInitialized()) {
556+
keyInput.resetContext();
557+
}
558+
if (mouseInput != null && mouseInput.isInitialized()) {
559+
mouseInput.resetContext();
560+
}
561+
562+
LOGGER.fine("Display restarted.");
563+
}
564+
552565
private void setFrameRateLimit(int frameRateLimit) {
553566
this.frameRateLimit = frameRateLimit;
554567
frameSleepTime = 1000.0 / this.frameRateLimit;
@@ -562,6 +575,7 @@ protected void deinitInThread() {
562575

563576
destroyContext();
564577
super.internalDestroy();
578+
glfwTerminate();
565579

566580
LOGGER.fine("Display destroyed.");
567581
}

0 commit comments

Comments
 (0)