* Big refactoring of LWJGL display system, mainly to support updating the main loop without a render context or input devices being available.
* Added test that demonstrates above functionality, by starting Application without attaching the canvas, and then constantly attaching and detaching canvas from a frame. * Deleted deprecated methods in JmeContext * Deleted deprecated class LwjglJoyInput * Audio renderer will not attempt to initialize OpenAL twice if already initialized git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7078 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
parent
eaeb1de436
commit
61aea1e2c5
@ -300,12 +300,16 @@ public class Application implements SystemListener {
|
|||||||
return cam;
|
return cam;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the application as a display.
|
||||||
|
*/
|
||||||
public void start(){
|
public void start(){
|
||||||
start(JmeContext.Type.Display);
|
start(JmeContext.Type.Display);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the application. Creating a display and running the main loop.
|
* Starts the application. Creating a rendering context and executing
|
||||||
|
* the main loop in a separate thread.
|
||||||
*/
|
*/
|
||||||
public void start(JmeContext.Type contextType){
|
public void start(JmeContext.Type contextType){
|
||||||
if (context != null && context.isCreated()){
|
if (context != null && context.isCreated()){
|
||||||
@ -423,6 +427,10 @@ public class Application implements SystemListener {
|
|||||||
context.destroy(false);
|
context.destroy(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enqueues a task/callable object to execute in the jME3
|
||||||
|
* rendering thread.
|
||||||
|
*/
|
||||||
public <V> Future<V> enqueue(Callable<V> callable) {
|
public <V> Future<V> enqueue(Callable<V> callable) {
|
||||||
AppTask<V> task = new AppTask<V>(callable);
|
AppTask<V> task = new AppTask<V>(callable);
|
||||||
taskQueue.add(task);
|
taskQueue.add(task);
|
||||||
@ -495,6 +503,4 @@ public class Application implements SystemListener {
|
|||||||
return viewPort;
|
return viewPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -249,7 +249,9 @@ public abstract class SimpleApplication extends Application {
|
|||||||
|
|
||||||
// render states
|
// render states
|
||||||
stateManager.render(renderManager);
|
stateManager.render(renderManager);
|
||||||
|
if (context.isRenderable()){
|
||||||
renderManager.render(tpf);
|
renderManager.render(tpf);
|
||||||
|
}
|
||||||
simpleRender(renderManager);
|
simpleRender(renderManager);
|
||||||
stateManager.postRender();
|
stateManager.postRender();
|
||||||
}
|
}
|
||||||
@ -257,7 +259,6 @@ public abstract class SimpleApplication extends Application {
|
|||||||
public void setDisplayFps(boolean show) {
|
public void setDisplayFps(boolean show) {
|
||||||
showFps = show;
|
showFps = show;
|
||||||
fpsText.setCullHint(show ? CullHint.Never : CullHint.Always);
|
fpsText.setCullHint(show ? CullHint.Never : CullHint.Always);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDisplayStatView(boolean show) {
|
public void setDisplayStatView(boolean show) {
|
||||||
|
@ -108,7 +108,6 @@ public class RenderManager {
|
|||||||
public RenderManager(Renderer renderer) {
|
public RenderManager(Renderer renderer) {
|
||||||
this.renderer = renderer;
|
this.renderer = renderer;
|
||||||
this.shader = renderer.getCaps().contains(Caps.GLSL100);
|
this.shader = renderer.getCaps().contains(Caps.GLSL100);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ViewPort getPreView(String viewName) {
|
public ViewPort getPreView(String viewName) {
|
||||||
|
@ -48,16 +48,19 @@ public interface JmeContext {
|
|||||||
public enum Type {
|
public enum Type {
|
||||||
/**
|
/**
|
||||||
* A display can represent a windowed or a fullscreen-exclusive display.
|
* A display can represent a windowed or a fullscreen-exclusive display.
|
||||||
* If windowed, the graphics are rendered to a new onscreen surface
|
* If windowed, the graphics are rendered to a new on-screen surface
|
||||||
* enclosed in a system defined by the operating system. Implementations
|
* enclosed in a window defined by the operating system. Implementations
|
||||||
* are encourged to not use AWT or Swing to create the OpenGL display
|
* are encouraged to not use AWT or Swing to create the OpenGL display
|
||||||
* but rather use native operating system functions to set up a native
|
* but rather use native operating system functions to set up a native
|
||||||
* display with the windowing system.
|
* display with the windowing system.
|
||||||
*/
|
*/
|
||||||
Display,
|
Display,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* A canvas type context makes a rendering surface available as an
|
||||||
|
* AWT {@link java.awt.Canvas} object that can be embedded in a Swing/AWT
|
||||||
|
* frame. To retrieve the Canvas object, you should cast the context
|
||||||
|
* to {@link JmeCanvasContext}.
|
||||||
*/
|
*/
|
||||||
Canvas,
|
Canvas,
|
||||||
|
|
||||||
@ -139,18 +142,19 @@ public interface JmeContext {
|
|||||||
*/
|
*/
|
||||||
public boolean isCreated();
|
public boolean isCreated();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return True if the context contains a valid render surface,
|
||||||
|
* if any of the rendering methods in {@link Renderer} are called
|
||||||
|
* while this is <code>false</code>, then the result is undefined.
|
||||||
|
*/
|
||||||
|
public boolean isRenderable();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param enabled If enabled, the context will automatically flush
|
* @param enabled If enabled, the context will automatically flush
|
||||||
* frames to the video card (swap buffers) after an update cycle.
|
* frames to the video card (swap buffers) after an update cycle.
|
||||||
*/
|
*/
|
||||||
public void setAutoFlushFrames(boolean enabled);
|
public void setAutoFlushFrames(boolean enabled);
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the context and makes it active.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public void create();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the context and makes it active.
|
* Creates the context and makes it active.
|
||||||
*
|
*
|
||||||
@ -164,12 +168,6 @@ public interface JmeContext {
|
|||||||
*/
|
*/
|
||||||
public void restart();
|
public void restart();
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroys the context completely, making it inactive.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public void destroy();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroys the context completely, making it inactive.
|
* Destroys the context completely, making it inactive.
|
||||||
*
|
*
|
||||||
|
@ -218,4 +218,9 @@ public class NullContext implements JmeContext, Runnable {
|
|||||||
return timer;
|
return timer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isRenderable() {
|
||||||
|
return true; // Doesn't really matter if true or false. Either way
|
||||||
|
// RenderManager won't render anything.
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -154,7 +154,9 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
|
|
||||||
public void initInThread(){
|
public void initInThread(){
|
||||||
try{
|
try{
|
||||||
|
if (!AL.isCreated()){
|
||||||
AL.create();
|
AL.create();
|
||||||
|
}
|
||||||
}catch (OpenALException ex){
|
}catch (OpenALException ex){
|
||||||
logger.log(Level.SEVERE, "Failed to load audio library", ex);
|
logger.log(Level.SEVERE, "Failed to load audio library", ex);
|
||||||
audioDisabled = true;
|
audioDisabled = true;
|
||||||
|
@ -1,181 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2009-2010 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 com.jme3.input.InputManager;
|
|
||||||
import com.jme3.input.JoyInput;
|
|
||||||
import com.jme3.input.Joystick;
|
|
||||||
import com.jme3.input.RawInputListener;
|
|
||||||
import com.jme3.input.event.JoyAxisEvent;
|
|
||||||
import com.jme3.input.event.JoyButtonEvent;
|
|
||||||
import com.jme3.system.lwjgl.LwjglTimer;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
import org.lwjgl.LWJGLException;
|
|
||||||
import org.lwjgl.Sys;
|
|
||||||
import org.lwjgl.input.Controller;
|
|
||||||
import org.lwjgl.input.Controllers;
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
class LwjglJoyInput implements JoyInput {
|
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(LwjglKeyInput.class.getName());
|
|
||||||
|
|
||||||
private RawInputListener listener;
|
|
||||||
private boolean enabled = false;
|
|
||||||
|
|
||||||
public void initialize() {
|
|
||||||
try {
|
|
||||||
Controllers.create();
|
|
||||||
if (Controllers.getControllerCount() == 0 || !Controllers.isCreated()){
|
|
||||||
logger.warning("Joysticks disabled.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
logger.info("Joysticks created.");
|
|
||||||
enabled = true;
|
|
||||||
} catch (LWJGLException ex) {
|
|
||||||
logger.log(Level.SEVERE, "Failed to create joysticks", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getJoyCount() {
|
|
||||||
return Controllers.getControllerCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getJoyName(int joyIndex) {
|
|
||||||
return Controllers.getController(joyIndex).getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getAxesCount(int joyIndex) {
|
|
||||||
return Controllers.getController(joyIndex).getAxisCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getButtonCount(int joyIndex) {
|
|
||||||
return Controllers.getController(joyIndex).getButtonCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void printController(Controller c){
|
|
||||||
System.out.println("Name: "+c.getName());
|
|
||||||
System.out.println("Index: "+c.getIndex());
|
|
||||||
System.out.println("Button Count: "+c.getButtonCount());
|
|
||||||
System.out.println("Axis Count: "+c.getAxisCount());
|
|
||||||
|
|
||||||
int buttons = c.getButtonCount();
|
|
||||||
for (int b = 0; b < buttons; b++) {
|
|
||||||
System.out.println("Button " + b + " = " + c.getButtonName(b));
|
|
||||||
}
|
|
||||||
|
|
||||||
int axis = c.getAxisCount();
|
|
||||||
for (int b = 0; b < axis; b++) {
|
|
||||||
System.out.println("Axis " + b + " = " + c.getAxisName(b));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void update() {
|
|
||||||
if (!enabled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Controllers.poll();
|
|
||||||
while (Controllers.next()){
|
|
||||||
Controller c = Controllers.getEventSource();
|
|
||||||
if (Controllers.isEventAxis()){
|
|
||||||
int realAxis = Controllers.getEventControlIndex();
|
|
||||||
JoyAxisEvent evt = new JoyAxisEvent(c.getIndex(),
|
|
||||||
realAxis,
|
|
||||||
c.getAxisValue(realAxis));
|
|
||||||
listener.onJoyAxisEvent(evt);
|
|
||||||
}else if (Controllers.isEventPovX()){
|
|
||||||
JoyAxisEvent evt = new JoyAxisEvent(c.getIndex(),
|
|
||||||
JoyInput.AXIS_POV_X,
|
|
||||||
c.getPovX());
|
|
||||||
listener.onJoyAxisEvent(evt);
|
|
||||||
}else if (Controllers.isEventPovY()){
|
|
||||||
JoyAxisEvent evt = new JoyAxisEvent(c.getIndex(),
|
|
||||||
JoyInput.AXIS_POV_Y,
|
|
||||||
c.getPovY());
|
|
||||||
listener.onJoyAxisEvent(evt);
|
|
||||||
}else if (Controllers.isEventButton()){
|
|
||||||
int btn = Controllers.getEventControlIndex();
|
|
||||||
JoyButtonEvent evt = new JoyButtonEvent(c.getIndex(),
|
|
||||||
btn,
|
|
||||||
c.isButtonPressed(btn));
|
|
||||||
listener.onJoyButtonEvent(evt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Controllers.clearEvents();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void destroy() {
|
|
||||||
if (!enabled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Controllers.destroy();
|
|
||||||
logger.info("Joysticks destroyed.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isInitialized() {
|
|
||||||
if (!enabled)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return Controllers.isCreated();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setInputListener(RawInputListener listener) {
|
|
||||||
this.listener = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getInputTimeNanos() {
|
|
||||||
return Sys.getTime() * LwjglTimer.LWJGL_TIME_TO_NANOS;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setJoyRumble(int joyId, float amount){
|
|
||||||
}
|
|
||||||
|
|
||||||
public Joystick[] loadJoysticks(InputManager inputManager) {
|
|
||||||
int count = Controllers.getControllerCount();
|
|
||||||
Joystick[] joysticks = new Joystick[count];
|
|
||||||
for (int i = 0; i < count; i++){
|
|
||||||
Controller c = Controllers.getController(i);
|
|
||||||
Joystick j = new Joystick(inputManager,
|
|
||||||
this,
|
|
||||||
i,
|
|
||||||
c.getName(),
|
|
||||||
c.getButtonCount(),
|
|
||||||
c.getAxisCount(),
|
|
||||||
-1,-1);
|
|
||||||
joysticks[i] = j;
|
|
||||||
}
|
|
||||||
return joysticks;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -35,6 +35,7 @@ package com.jme3.input.lwjgl;
|
|||||||
import com.jme3.input.KeyInput;
|
import com.jme3.input.KeyInput;
|
||||||
import com.jme3.input.event.KeyInputEvent;
|
import com.jme3.input.event.KeyInputEvent;
|
||||||
import com.jme3.input.RawInputListener;
|
import com.jme3.input.RawInputListener;
|
||||||
|
import com.jme3.system.lwjgl.LwjglAbstractDisplay;
|
||||||
import com.jme3.system.lwjgl.LwjglTimer;
|
import com.jme3.system.lwjgl.LwjglTimer;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
@ -46,9 +47,18 @@ public class LwjglKeyInput implements KeyInput {
|
|||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(LwjglKeyInput.class.getName());
|
private static final Logger logger = Logger.getLogger(LwjglKeyInput.class.getName());
|
||||||
|
|
||||||
|
private LwjglAbstractDisplay context;
|
||||||
|
|
||||||
private RawInputListener listener;
|
private RawInputListener listener;
|
||||||
|
|
||||||
|
public LwjglKeyInput(LwjglAbstractDisplay context){
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
|
if (!context.isRenderable())
|
||||||
|
return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Keyboard.create();
|
Keyboard.create();
|
||||||
Keyboard.enableRepeatEvents(true);
|
Keyboard.enableRepeatEvents(true);
|
||||||
@ -58,15 +68,14 @@ public class LwjglKeyInput implements KeyInput {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isKeyDown(int key){
|
|
||||||
return Keyboard.isKeyDown(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getKeyCount(){
|
public int getKeyCount(){
|
||||||
return Keyboard.KEYBOARD_SIZE;
|
return Keyboard.KEYBOARD_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update() {
|
public void update() {
|
||||||
|
if (!context.isRenderable())
|
||||||
|
return;
|
||||||
|
|
||||||
Keyboard.poll();
|
Keyboard.poll();
|
||||||
while (Keyboard.next()){
|
while (Keyboard.next()){
|
||||||
int keyCode = Keyboard.getEventKey();
|
int keyCode = Keyboard.getEventKey();
|
||||||
@ -81,6 +90,9 @@ public class LwjglKeyInput implements KeyInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
|
if (!context.isRenderable())
|
||||||
|
return;
|
||||||
|
|
||||||
Keyboard.destroy();
|
Keyboard.destroy();
|
||||||
logger.info("Keyboard destroyed.");
|
logger.info("Keyboard destroyed.");
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ import com.jme3.input.event.MouseButtonEvent;
|
|||||||
import com.jme3.input.event.MouseMotionEvent;
|
import com.jme3.input.event.MouseMotionEvent;
|
||||||
import com.jme3.input.MouseInput;
|
import com.jme3.input.MouseInput;
|
||||||
import com.jme3.input.RawInputListener;
|
import com.jme3.input.RawInputListener;
|
||||||
|
import com.jme3.system.lwjgl.LwjglAbstractDisplay;
|
||||||
import com.jme3.system.lwjgl.LwjglTimer;
|
import com.jme3.system.lwjgl.LwjglTimer;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
@ -48,6 +49,8 @@ public class LwjglMouseInput implements MouseInput {
|
|||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(LwjglMouseInput.class.getName());
|
private static final Logger logger = Logger.getLogger(LwjglMouseInput.class.getName());
|
||||||
|
|
||||||
|
private LwjglAbstractDisplay context;
|
||||||
|
|
||||||
private RawInputListener listener;
|
private RawInputListener listener;
|
||||||
|
|
||||||
private boolean supportHardwareCursor = false;
|
private boolean supportHardwareCursor = false;
|
||||||
@ -55,11 +58,21 @@ public class LwjglMouseInput implements MouseInput {
|
|||||||
|
|
||||||
private int curX, curY, curWheel;
|
private int curX, curY, curWheel;
|
||||||
|
|
||||||
|
public LwjglMouseInput(LwjglAbstractDisplay context){
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
|
if (!context.isRenderable())
|
||||||
|
return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Mouse.create();
|
Mouse.create();
|
||||||
logger.info("Mouse created.");
|
logger.info("Mouse created.");
|
||||||
supportHardwareCursor = (Cursor.getCapabilities() & Cursor.CURSOR_ONE_BIT_TRANSPARENCY) != 0;
|
supportHardwareCursor = (Cursor.getCapabilities() & Cursor.CURSOR_ONE_BIT_TRANSPARENCY) != 0;
|
||||||
|
|
||||||
|
// Recall state that was set before initialization
|
||||||
|
Mouse.setGrabbed(!cursorVisible);
|
||||||
} catch (LWJGLException ex) {
|
} catch (LWJGLException ex) {
|
||||||
logger.log(Level.SEVERE, "Error while creating mouse", ex);
|
logger.log(Level.SEVERE, "Error while creating mouse", ex);
|
||||||
}
|
}
|
||||||
@ -74,6 +87,9 @@ public class LwjglMouseInput implements MouseInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void update() {
|
public void update() {
|
||||||
|
if (!context.isRenderable())
|
||||||
|
return;
|
||||||
|
|
||||||
while (Mouse.next()){
|
while (Mouse.next()){
|
||||||
int btn = Mouse.getEventButton();
|
int btn = Mouse.getEventButton();
|
||||||
|
|
||||||
@ -109,13 +125,19 @@ public class LwjglMouseInput implements MouseInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
|
if (!context.isRenderable())
|
||||||
|
return;
|
||||||
|
|
||||||
Mouse.destroy();
|
Mouse.destroy();
|
||||||
logger.info("Mouse destroyed.");
|
logger.info("Mouse destroyed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCursorVisible(boolean visible){
|
public void setCursorVisible(boolean visible){
|
||||||
Mouse.setGrabbed(!visible);
|
|
||||||
cursorVisible = visible;
|
cursorVisible = visible;
|
||||||
|
if (!context.isRenderable())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Mouse.setGrabbed(!visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setInputListener(RawInputListener listener) {
|
public void setInputListener(RawInputListener listener) {
|
||||||
|
@ -47,16 +47,13 @@ import java.util.logging.Logger;
|
|||||||
import org.lwjgl.LWJGLException;
|
import org.lwjgl.LWJGLException;
|
||||||
import org.lwjgl.Sys;
|
import org.lwjgl.Sys;
|
||||||
import org.lwjgl.opengl.Display;
|
import org.lwjgl.opengl.Display;
|
||||||
import org.lwjgl.opengl.GL11;
|
|
||||||
import org.lwjgl.opengl.GL20;
|
|
||||||
import org.lwjgl.opengl.GLContext;
|
|
||||||
import org.lwjgl.opengl.OpenGLException;
|
import org.lwjgl.opengl.OpenGLException;
|
||||||
import org.lwjgl.opengl.Util;
|
import org.lwjgl.opengl.Util;
|
||||||
|
|
||||||
|
|
||||||
public abstract class LwjglAbstractDisplay extends LwjglContext implements Runnable {
|
public abstract class LwjglAbstractDisplay extends LwjglContext implements Runnable {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(LwjglDisplay.class.getName());
|
private static final Logger logger = Logger.getLogger(LwjglAbstractDisplay.class.getName());
|
||||||
|
|
||||||
protected AtomicBoolean needClose = new AtomicBoolean(false);
|
protected AtomicBoolean needClose = new AtomicBoolean(false);
|
||||||
protected boolean wasActive = false;
|
protected boolean wasActive = false;
|
||||||
protected int frameRate = 0;
|
protected int frameRate = 0;
|
||||||
@ -84,6 +81,8 @@ public abstract class LwjglAbstractDisplay extends LwjglContext implements Runna
|
|||||||
*/
|
*/
|
||||||
protected abstract void createContext(AppSettings settings) throws LWJGLException;
|
protected abstract void createContext(AppSettings settings) throws LWJGLException;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does LWJGL display initialization in the OpenGL thread
|
* Does LWJGL display initialization in the OpenGL thread
|
||||||
*/
|
*/
|
||||||
@ -97,42 +96,22 @@ public abstract class LwjglAbstractDisplay extends LwjglContext implements Runna
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For canvas, this wont happen until its initialized.
|
||||||
createContext(settings);
|
createContext(settings);
|
||||||
// String rendererStr = settings.getString("Renderer");
|
if (renderable.get()) // assumes createContext will set this flag
|
||||||
|
printContextInitInfo();
|
||||||
logger.info("Display created.");
|
|
||||||
logger.log(Level.FINE, "Running on thread: {0}", Thread.currentThread().getName());
|
|
||||||
|
|
||||||
logger.log(Level.INFO, "Adapter: {0}", Display.getAdapter());
|
|
||||||
logger.log(Level.INFO, "Driver Version: {0}", Display.getVersion());
|
|
||||||
|
|
||||||
String vendor = GL11.glGetString(GL11.GL_VENDOR);
|
|
||||||
logger.log(Level.INFO, "Vendor: {0}", vendor);
|
|
||||||
|
|
||||||
String version = GL11.glGetString(GL11.GL_VERSION);
|
|
||||||
logger.log(Level.INFO, "OpenGL Version: {0}", version);
|
|
||||||
|
|
||||||
String renderer = GL11.glGetString(GL11.GL_RENDERER);
|
|
||||||
logger.log(Level.INFO, "Renderer: {0}", renderer);
|
|
||||||
|
|
||||||
if (GLContext.getCapabilities().OpenGL20){
|
|
||||||
String shadingLang = GL11.glGetString(GL20.GL_SHADING_LANGUAGE_VERSION);
|
|
||||||
logger.log(Level.INFO, "GLSL Ver: {0}", shadingLang);
|
|
||||||
}
|
|
||||||
|
|
||||||
created.set(true);
|
created.set(true);
|
||||||
} catch (Exception ex){
|
} catch (Exception ex){
|
||||||
listener.handleError("Failed to create display", ex);
|
try {
|
||||||
} finally {
|
|
||||||
// TODO: It is possible to avoid "Failed to find pixel format"
|
|
||||||
// error here by creating a default display.
|
|
||||||
|
|
||||||
if (!created.get()){
|
|
||||||
if (Display.isCreated())
|
if (Display.isCreated())
|
||||||
Display.destroy();
|
Display.destroy();
|
||||||
|
} catch (Exception ex2){
|
||||||
return; // if we failed to create display, do not continue
|
logger.log(Level.WARNING, null, ex2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
listener.handleError("Failed to create display", ex);
|
||||||
|
return; // if we failed to create display, do not continue
|
||||||
}
|
}
|
||||||
super.internalCreate();
|
super.internalCreate();
|
||||||
listener.initialize();
|
listener.initialize();
|
||||||
@ -156,6 +135,8 @@ public abstract class LwjglAbstractDisplay extends LwjglContext implements Runna
|
|||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
|
|
||||||
listener.update();
|
listener.update();
|
||||||
|
|
||||||
|
if (renderable.get()){
|
||||||
assert checkGLError();
|
assert checkGLError();
|
||||||
|
|
||||||
// calls swap buffers, etc.
|
// calls swap buffers, etc.
|
||||||
@ -171,11 +152,12 @@ public abstract class LwjglAbstractDisplay extends LwjglContext implements Runna
|
|||||||
} catch (Throwable ex){
|
} catch (Throwable ex){
|
||||||
listener.handleError("Error while swapping buffers", ex);
|
listener.handleError("Error while swapping buffers", ex);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (frameRate > 0)
|
if (frameRate > 0)
|
||||||
Display.sync(frameRate);
|
Display.sync(frameRate);
|
||||||
|
|
||||||
if (autoFlush)
|
if (renderable.get() && autoFlush)
|
||||||
renderer.onFrame();
|
renderer.onFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,18 +187,20 @@ public abstract class LwjglAbstractDisplay extends LwjglContext implements Runna
|
|||||||
logger.log(Level.INFO, "Using LWJGL {0}", Sys.getVersion());
|
logger.log(Level.INFO, "Using LWJGL {0}", Sys.getVersion());
|
||||||
initInThread();
|
initInThread();
|
||||||
while (true){
|
while (true){
|
||||||
|
if (renderable.get()){
|
||||||
if (Display.isCloseRequested())
|
if (Display.isCloseRequested())
|
||||||
listener.requestClose(false);
|
listener.requestClose(false);
|
||||||
|
|
||||||
if (wasActive != Display.isActive()){
|
if (wasActive != Display.isActive()) {
|
||||||
if (!wasActive){
|
if (!wasActive) {
|
||||||
listener.gainFocus();
|
listener.gainFocus();
|
||||||
wasActive = true;
|
wasActive = true;
|
||||||
}else{
|
} else {
|
||||||
listener.loseFocus();
|
listener.loseFocus();
|
||||||
wasActive = false;
|
wasActive = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
runLoop();
|
runLoop();
|
||||||
|
|
||||||
@ -227,15 +211,24 @@ public abstract class LwjglAbstractDisplay extends LwjglContext implements Runna
|
|||||||
}
|
}
|
||||||
|
|
||||||
public JoyInput getJoyInput() {
|
public JoyInput getJoyInput() {
|
||||||
return new JInputJoyInput();
|
if (joyInput == null){
|
||||||
|
joyInput = new JInputJoyInput();
|
||||||
|
}
|
||||||
|
return joyInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MouseInput getMouseInput() {
|
public MouseInput getMouseInput() {
|
||||||
return new LwjglMouseInput();
|
if (mouseInput == null){
|
||||||
|
mouseInput = new LwjglMouseInput(this);
|
||||||
|
}
|
||||||
|
return mouseInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeyInput getKeyInput() {
|
public KeyInput getKeyInput() {
|
||||||
return new LwjglKeyInput();
|
if (keyInput == null){
|
||||||
|
keyInput = new LwjglKeyInput(this);
|
||||||
|
}
|
||||||
|
return keyInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAutoFlushFrames(boolean enabled){
|
public void setAutoFlushFrames(boolean enabled){
|
||||||
|
@ -36,6 +36,8 @@ import com.jme3.system.AppSettings;
|
|||||||
import com.jme3.system.JmeCanvasContext;
|
import com.jme3.system.JmeCanvasContext;
|
||||||
import com.jme3.system.JmeContext.Type;
|
import com.jme3.system.JmeContext.Type;
|
||||||
import java.awt.Canvas;
|
import java.awt.Canvas;
|
||||||
|
import java.util.concurrent.BrokenBarrierException;
|
||||||
|
import java.util.concurrent.CyclicBarrier;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
@ -54,68 +56,67 @@ public class LwjglCanvas extends LwjglAbstractDisplay implements JmeCanvasContex
|
|||||||
private int width;
|
private int width;
|
||||||
private int height;
|
private int height;
|
||||||
|
|
||||||
private AtomicBoolean reinitReq = new AtomicBoolean(false);
|
private final AtomicBoolean needRestoreCanvas = new AtomicBoolean(false);
|
||||||
private final Object reinitReqLock = new Object();
|
private final AtomicBoolean needDestroyCanvas = new AtomicBoolean(false);
|
||||||
|
private final CyclicBarrier actionRequiredBarrier = new CyclicBarrier(2);
|
||||||
private AtomicBoolean reinitAuth = new AtomicBoolean(false);
|
|
||||||
private final Object reinitAuthLock = new Object();
|
|
||||||
|
|
||||||
private Thread renderThread;
|
private Thread renderThread;
|
||||||
|
private boolean runningFirstTime = true;
|
||||||
private boolean mouseWasGrabbed = false;
|
private boolean mouseWasGrabbed = false;
|
||||||
// private Pbuffer dummyCtx;
|
private boolean mouseActive, keyboardActive, joyActive;
|
||||||
|
|
||||||
public LwjglCanvas(){
|
public LwjglCanvas(){
|
||||||
super();
|
super();
|
||||||
|
|
||||||
canvas = new Canvas(){
|
canvas = new Canvas(){
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addNotify(){
|
public void addNotify(){
|
||||||
super.addNotify();
|
super.addNotify();
|
||||||
if (renderThread == null || renderThread.getState() == Thread.State.TERMINATED){
|
|
||||||
if (renderThread != null && renderThread.getState() == Thread.State.TERMINATED){
|
if (renderThread != null && renderThread.getState() == Thread.State.TERMINATED)
|
||||||
logger.log(Level.INFO, "EDT: Creating OGL thread. Was terminated.");
|
return; // already destroyed.
|
||||||
}else{
|
|
||||||
|
if (renderThread == null){
|
||||||
logger.log(Level.INFO, "EDT: Creating OGL thread.");
|
logger.log(Level.INFO, "EDT: Creating OGL thread.");
|
||||||
}
|
|
||||||
renderThread = new Thread(LwjglCanvas.this, "LWJGL Renderer Thread");
|
renderThread = new Thread(LwjglCanvas.this, "LWJGL Renderer Thread");
|
||||||
renderThread.start();
|
renderThread.start();
|
||||||
}else{
|
}else if (needClose.get()){
|
||||||
if (needClose.get())
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
logger.log(Level.INFO, "EDT: Sending re-init authorization..");
|
|
||||||
|
|
||||||
// reinitializing canvas
|
|
||||||
synchronized (reinitAuthLock){
|
|
||||||
reinitAuth.set(true);
|
|
||||||
reinitAuthLock.notifyAll();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.log(Level.INFO, "EDT: Notifying OGL that canvas is visible..");
|
||||||
|
needRestoreCanvas.set(true);
|
||||||
|
|
||||||
|
// NOTE: no need to wait for OGL to initialize the canvas,
|
||||||
|
// it can happen at any time.
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeNotify(){
|
public void removeNotify(){
|
||||||
if (needClose.get()){
|
if (needClose.get()){
|
||||||
logger.log(Level.INFO, "EDT: Close requested. Not re-initing.");
|
logger.log(Level.INFO, "EDT: Application is stopped. Not restoring canvas.");
|
||||||
|
super.removeNotify();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// request to put context into reinit mode
|
// We must tell GL context to shutdown and wait for it to
|
||||||
// this waits until reinit is authorized
|
// shutdown, otherwise, issues will occur.
|
||||||
logger.log(Level.INFO, "EDT: Sending re-init request..");
|
logger.log(Level.INFO, "EDT: Sending destroy request..");
|
||||||
synchronized (reinitReqLock){
|
needDestroyCanvas.set(true);
|
||||||
reinitReq.set(true);
|
|
||||||
while (reinitReq.get()){
|
|
||||||
try {
|
try {
|
||||||
reinitReqLock.wait();
|
actionRequiredBarrier.await();
|
||||||
} catch (InterruptedException ex) {
|
} catch (InterruptedException ex) {
|
||||||
logger.log(Level.SEVERE, "EDT: Interrupted! ", ex);
|
logger.log(Level.SEVERE, "EDT: Interrupted! ", ex);
|
||||||
|
} catch (BrokenBarrierException ex){
|
||||||
|
logger.log(Level.SEVERE, "EDT: Broken barrier! ", ex);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// NOTE: reinitReq is now false.
|
logger.log(Level.INFO, "EDT: Acknowledged receipt of destroy request!");
|
||||||
}
|
// GL context is dead at this point
|
||||||
logger.log(Level.INFO, "EDT: Acknowledged receipt of re-init request!");
|
|
||||||
|
// Reset barrier for future use
|
||||||
|
actionRequiredBarrier.reset();
|
||||||
|
|
||||||
super.removeNotify();
|
super.removeNotify();
|
||||||
}
|
}
|
||||||
@ -131,6 +132,12 @@ public class LwjglCanvas extends LwjglAbstractDisplay implements JmeCanvasContex
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void create(boolean waitFor){
|
public void create(boolean waitFor){
|
||||||
|
if (renderThread == null){
|
||||||
|
logger.log(Level.INFO, "MAIN: Creating OGL thread.");
|
||||||
|
|
||||||
|
renderThread = new Thread(LwjglCanvas.this, "LWJGL Renderer Thread");
|
||||||
|
renderThread.start();
|
||||||
|
}
|
||||||
// do not do anything.
|
// do not do anything.
|
||||||
// superclass's create() will be called at initInThread()
|
// superclass's create() will be called at initInThread()
|
||||||
if (waitFor)
|
if (waitFor)
|
||||||
@ -151,18 +158,48 @@ public class LwjglCanvas extends LwjglAbstractDisplay implements JmeCanvasContex
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void runLoop(){
|
protected void runLoop(){
|
||||||
boolean reinitNeeded;
|
if (needDestroyCanvas.getAndSet(false)){
|
||||||
synchronized (reinitReqLock){
|
// Destroy canvas
|
||||||
reinitNeeded = reinitReq.get();
|
logger.log(Level.INFO, "OGL: Received destroy request! Complying..");
|
||||||
|
try {
|
||||||
|
listener.loseFocus();
|
||||||
|
pauseCanvas();
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
// Required to avoid deadlock if an exception occurs
|
||||||
|
actionRequiredBarrier.await();
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
logger.log(Level.SEVERE, "OGL: Interrupted! ", ex);
|
||||||
|
} catch (BrokenBarrierException ex) {
|
||||||
|
logger.log(Level.SEVERE, "OGL: Broken barrier! ", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else if (needRestoreCanvas.getAndSet(false)){
|
||||||
|
// Put canvas back online
|
||||||
|
logger.log(Level.INFO, "OGL: Canvas is now visible! Re-initializing..");
|
||||||
|
restoreCanvas();
|
||||||
|
listener.gainFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reinitNeeded){
|
if (width != canvas.getWidth() || height != canvas.getHeight()){
|
||||||
logger.log(Level.INFO, "OGL: Re-init request received!");
|
width = canvas.getWidth();
|
||||||
listener.loseFocus();
|
height = canvas.getHeight();
|
||||||
|
if (listener != null)
|
||||||
|
listener.reshape(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
boolean mouseActive = Mouse.isCreated();
|
super.runLoop();
|
||||||
boolean keyboardActive = Keyboard.isCreated();
|
}
|
||||||
boolean joyActive = Controllers.isCreated();
|
|
||||||
|
private void pauseCanvas(){
|
||||||
|
mouseActive = Mouse.isCreated();
|
||||||
|
keyboardActive = Keyboard.isCreated();
|
||||||
|
joyActive = Controllers.isCreated();
|
||||||
|
|
||||||
|
if (mouseActive && Mouse.isGrabbed()){
|
||||||
|
Mouse.setGrabbed(false);
|
||||||
|
mouseWasGrabbed = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (mouseActive)
|
if (mouseActive)
|
||||||
Mouse.destroy();
|
Mouse.destroy();
|
||||||
@ -171,86 +208,14 @@ public class LwjglCanvas extends LwjglAbstractDisplay implements JmeCanvasContex
|
|||||||
if (joyActive)
|
if (joyActive)
|
||||||
Controllers.destroy();
|
Controllers.destroy();
|
||||||
|
|
||||||
pauseCanvas();
|
|
||||||
|
|
||||||
synchronized (reinitReqLock){
|
|
||||||
reinitReq.set(false);
|
|
||||||
reinitReqLock.notifyAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
// we got the reinit request, now we wait for reinit to happen..
|
|
||||||
logger.log(Level.INFO, "OGL: Waiting for re-init authorization..");
|
|
||||||
synchronized (reinitAuthLock){
|
|
||||||
while (!reinitAuth.get()){
|
|
||||||
try {
|
|
||||||
reinitAuthLock.wait();
|
|
||||||
if (Thread.interrupted())
|
|
||||||
throw new InterruptedException();
|
|
||||||
} catch (InterruptedException ex) {
|
|
||||||
if (needClose.get()){
|
|
||||||
logger.log(Level.INFO, "OGL: Re-init aborted. Closing display..");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.log(Level.SEVERE, "OGL: Interrupted! ", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// NOTE: reinitAuth becamse true, now set it to false.
|
|
||||||
reinitAuth.set(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.log(Level.INFO, "OGL: Re-init authorization received. Re-initializing..");
|
|
||||||
restoreCanvas();
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (mouseActive){
|
|
||||||
Mouse.create();
|
|
||||||
}
|
|
||||||
if (keyboardActive){
|
|
||||||
Keyboard.create();
|
|
||||||
}
|
|
||||||
if (joyActive){
|
|
||||||
Controllers.create();
|
|
||||||
}
|
|
||||||
} catch (LWJGLException ex){
|
|
||||||
listener.handleError("Failed to re-init input", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (width != canvas.getWidth() || height != canvas.getHeight()){
|
|
||||||
width = canvas.getWidth();
|
|
||||||
height = canvas.getHeight();
|
|
||||||
if (listener != null)
|
|
||||||
listener.reshape(width, height);
|
|
||||||
}
|
|
||||||
super.runLoop();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void destroy(boolean waitFor){
|
|
||||||
needClose.set(true);
|
|
||||||
if (renderThread != null && renderThread.isAlive()){
|
|
||||||
renderThread.interrupt();
|
|
||||||
// make sure it really does get interrupted
|
|
||||||
synchronized(reinitAuthLock){
|
|
||||||
reinitAuthLock.notifyAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (waitFor)
|
|
||||||
waitFor(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void pauseCanvas(){
|
|
||||||
if (Mouse.isCreated() && Mouse.isGrabbed()){
|
|
||||||
Mouse.setGrabbed(false);
|
|
||||||
mouseWasGrabbed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.log(Level.INFO, "OGL: Destroying display (temporarily)");
|
logger.log(Level.INFO, "OGL: Destroying display (temporarily)");
|
||||||
Display.destroy();
|
Display.destroy();
|
||||||
|
|
||||||
|
renderable.set(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called if canvas was removed and then restored unexpectedly
|
* Called to restore the canvas.
|
||||||
*/
|
*/
|
||||||
private void restoreCanvas(){
|
private void restoreCanvas(){
|
||||||
logger.log(Level.INFO, "OGL: Waiting for canvas to become displayable..");
|
logger.log(Level.INFO, "OGL: Waiting for canvas to become displayable..");
|
||||||
@ -261,8 +226,12 @@ public class LwjglCanvas extends LwjglAbstractDisplay implements JmeCanvasContex
|
|||||||
logger.log(Level.SEVERE, "OGL: Interrupted! ", ex);
|
logger.log(Level.SEVERE, "OGL: Interrupted! ", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer.resetGLObjects();
|
renderer.resetGLObjects();
|
||||||
logger.log(Level.INFO, "OGL: Creating display..");
|
logger.log(Level.INFO, "OGL: Creating display..");
|
||||||
|
|
||||||
|
// Set renderable to true, since canvas is now displayable.
|
||||||
|
renderable.set(true);
|
||||||
createContext(settings);
|
createContext(settings);
|
||||||
|
|
||||||
logger.log(Level.INFO, "OGL: Waiting for display to become active..");
|
logger.log(Level.INFO, "OGL: Waiting for display to become active..");
|
||||||
@ -276,26 +245,33 @@ public class LwjglCanvas extends LwjglAbstractDisplay implements JmeCanvasContex
|
|||||||
logger.log(Level.INFO, "OGL: Display is active!");
|
logger.log(Level.INFO, "OGL: Display is active!");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (mouseWasGrabbed){
|
if (mouseActive){
|
||||||
Mouse.create();
|
Mouse.create();
|
||||||
|
if (mouseWasGrabbed){
|
||||||
Mouse.setGrabbed(true);
|
Mouse.setGrabbed(true);
|
||||||
mouseWasGrabbed = false;
|
mouseWasGrabbed = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (keyboardActive){
|
||||||
|
Keyboard.create();
|
||||||
|
}
|
||||||
|
logger.log(Level.INFO, "OGL: Input has been reinitialized");
|
||||||
|
} catch (LWJGLException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Failed to re-init input", ex);
|
||||||
|
}
|
||||||
|
|
||||||
SwingUtilities.invokeLater(new Runnable(){
|
SwingUtilities.invokeLater(new Runnable(){
|
||||||
public void run(){
|
public void run(){
|
||||||
canvas.requestFocus();
|
canvas.requestFocus();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (LWJGLException ex) {
|
|
||||||
logger.log(Level.SEVERE, "restoreCanvas()", ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
listener.gainFocus();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void createContext(AppSettings settings) {
|
protected void createContext(AppSettings settings) {
|
||||||
|
if (!renderable.get())
|
||||||
|
return;
|
||||||
|
|
||||||
frameRate = settings.getFrameRate();
|
frameRate = settings.getFrameRate();
|
||||||
Display.setVSyncEnabled(settings.isVSync());
|
Display.setVSyncEnabled(settings.isVSync());
|
||||||
|
|
||||||
@ -308,6 +284,11 @@ public class LwjglCanvas extends LwjglAbstractDisplay implements JmeCanvasContex
|
|||||||
settings.getSamples());
|
settings.getSamples());
|
||||||
Display.create(pf);
|
Display.create(pf);
|
||||||
Display.makeCurrent();
|
Display.makeCurrent();
|
||||||
|
|
||||||
|
if (runningFirstTime){
|
||||||
|
initContextFirstTime();
|
||||||
|
runningFirstTime = false;
|
||||||
|
}
|
||||||
}catch (LWJGLException ex){
|
}catch (LWJGLException ex){
|
||||||
listener.handleError("Failed to parent canvas to display", ex);
|
listener.handleError("Failed to parent canvas to display", ex);
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,9 @@
|
|||||||
|
|
||||||
package com.jme3.system.lwjgl;
|
package com.jme3.system.lwjgl;
|
||||||
|
|
||||||
|
import com.jme3.input.lwjgl.JInputJoyInput;
|
||||||
|
import com.jme3.input.lwjgl.LwjglKeyInput;
|
||||||
|
import com.jme3.input.lwjgl.LwjglMouseInput;
|
||||||
import com.jme3.renderer.Renderer;
|
import com.jme3.renderer.Renderer;
|
||||||
import com.jme3.renderer.lwjgl.LwjglGL1Renderer;
|
import com.jme3.renderer.lwjgl.LwjglGL1Renderer;
|
||||||
import com.jme3.renderer.lwjgl.LwjglRenderer;
|
import com.jme3.renderer.lwjgl.LwjglRenderer;
|
||||||
@ -40,6 +43,12 @@ import com.jme3.system.SystemListener;
|
|||||||
import com.jme3.system.JmeContext;
|
import com.jme3.system.JmeContext;
|
||||||
import com.jme3.system.Timer;
|
import com.jme3.system.Timer;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import org.lwjgl.opengl.ContextAttribs;
|
||||||
|
import org.lwjgl.opengl.Display;
|
||||||
|
import org.lwjgl.opengl.GL11;
|
||||||
|
import org.lwjgl.opengl.GL20;
|
||||||
import org.lwjgl.opengl.GLContext;
|
import org.lwjgl.opengl.GLContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,11 +56,17 @@ import org.lwjgl.opengl.GLContext;
|
|||||||
*/
|
*/
|
||||||
public abstract class LwjglContext implements JmeContext {
|
public abstract class LwjglContext implements JmeContext {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(LwjglContext.class.getName());
|
||||||
|
|
||||||
protected AtomicBoolean created = new AtomicBoolean(false);
|
protected AtomicBoolean created = new AtomicBoolean(false);
|
||||||
|
protected AtomicBoolean renderable = new AtomicBoolean(false);
|
||||||
protected final Object createdLock = new Object();
|
protected final Object createdLock = new Object();
|
||||||
|
|
||||||
protected AppSettings settings = new AppSettings(true);
|
protected AppSettings settings = new AppSettings(true);
|
||||||
protected Renderer renderer;
|
protected Renderer renderer;
|
||||||
|
protected LwjglKeyInput keyInput;
|
||||||
|
protected LwjglMouseInput mouseInput;
|
||||||
|
protected JInputJoyInput joyInput;
|
||||||
protected Timer timer;
|
protected Timer timer;
|
||||||
protected SystemListener listener;
|
protected SystemListener listener;
|
||||||
|
|
||||||
@ -59,9 +74,72 @@ public abstract class LwjglContext implements JmeContext {
|
|||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void printContextInitInfo(){
|
||||||
|
logger.log(Level.FINE, "Running on thread: {0}", Thread.currentThread().getName());
|
||||||
|
|
||||||
|
logger.log(Level.INFO, "Adapter: {0}", Display.getAdapter());
|
||||||
|
logger.log(Level.INFO, "Driver Version: {0}", Display.getVersion());
|
||||||
|
|
||||||
|
String vendor = GL11.glGetString(GL11.GL_VENDOR);
|
||||||
|
logger.log(Level.INFO, "Vendor: {0}", vendor);
|
||||||
|
|
||||||
|
String version = GL11.glGetString(GL11.GL_VERSION);
|
||||||
|
logger.log(Level.INFO, "OpenGL Version: {0}", version);
|
||||||
|
|
||||||
|
String renderGl = GL11.glGetString(GL11.GL_RENDERER);
|
||||||
|
logger.log(Level.INFO, "Renderer: {0}", renderGl);
|
||||||
|
|
||||||
|
if (GLContext.getCapabilities().OpenGL20){
|
||||||
|
String shadingLang = GL11.glGetString(GL20.GL_SHADING_LANGUAGE_VERSION);
|
||||||
|
logger.log(Level.INFO, "GLSL Ver: {0}", shadingLang);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ContextAttribs createContextAttribs(){
|
||||||
|
if (settings.getBoolean("GraphicsDebug") || settings.getRenderer().equals(AppSettings.LWJGL_OPENGL3)){
|
||||||
|
ContextAttribs attr;
|
||||||
|
if (settings.getRenderer().equals(AppSettings.LWJGL_OPENGL3)){
|
||||||
|
attr = new ContextAttribs(3, 3);
|
||||||
|
attr = attr.withProfileCore(true).withForwardCompatible(true).withProfileCompatibility(false);
|
||||||
|
}else{
|
||||||
|
attr = new ContextAttribs();
|
||||||
|
}
|
||||||
|
if (settings.getBoolean("GraphicsDebug")){
|
||||||
|
attr = attr.withDebug(true);
|
||||||
|
}
|
||||||
|
return attr;
|
||||||
|
}else{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void initContextFirstTime(){
|
||||||
|
assert renderable.get();
|
||||||
|
|
||||||
|
// Init renderer
|
||||||
|
if (renderer instanceof LwjglRenderer){
|
||||||
|
((LwjglRenderer)renderer).initialize();
|
||||||
|
}else if (renderer instanceof LwjglGL1Renderer){
|
||||||
|
((LwjglGL1Renderer)renderer).initialize();
|
||||||
|
}else{
|
||||||
|
assert false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init input
|
||||||
|
if (keyInput != null)
|
||||||
|
keyInput.initialize();
|
||||||
|
|
||||||
|
if (mouseInput != null)
|
||||||
|
mouseInput.initialize();
|
||||||
|
|
||||||
|
if (joyInput != null)
|
||||||
|
joyInput.initialize();
|
||||||
|
}
|
||||||
|
|
||||||
public void internalDestroy(){
|
public void internalDestroy(){
|
||||||
renderer = null;
|
renderer = null;
|
||||||
timer = null;
|
timer = null;
|
||||||
|
renderable.set(false);
|
||||||
synchronized (createdLock){
|
synchronized (createdLock){
|
||||||
created.set(false);
|
created.set(false);
|
||||||
createdLock.notifyAll();
|
createdLock.notifyAll();
|
||||||
@ -73,10 +151,8 @@ public abstract class LwjglContext implements JmeContext {
|
|||||||
if (settings.getRenderer().equals(AppSettings.LWJGL_OPENGL2)
|
if (settings.getRenderer().equals(AppSettings.LWJGL_OPENGL2)
|
||||||
|| settings.getRenderer().equals(AppSettings.LWJGL_OPENGL3)){
|
|| settings.getRenderer().equals(AppSettings.LWJGL_OPENGL3)){
|
||||||
renderer = new LwjglRenderer();
|
renderer = new LwjglRenderer();
|
||||||
((LwjglRenderer)renderer).initialize();
|
|
||||||
}else if (settings.getRenderer().equals(AppSettings.LWJGL_OPENGL1)){
|
}else if (settings.getRenderer().equals(AppSettings.LWJGL_OPENGL1)){
|
||||||
renderer = new LwjglGL1Renderer();
|
renderer = new LwjglGL1Renderer();
|
||||||
((LwjglGL1Renderer)renderer).initialize();
|
|
||||||
}else{
|
}else{
|
||||||
throw new UnsupportedOperationException("Unsupported renderer: " + settings.getRenderer());
|
throw new UnsupportedOperationException("Unsupported renderer: " + settings.getRenderer());
|
||||||
}
|
}
|
||||||
@ -84,6 +160,10 @@ public abstract class LwjglContext implements JmeContext {
|
|||||||
created.set(true);
|
created.set(true);
|
||||||
createdLock.notifyAll();
|
createdLock.notifyAll();
|
||||||
}
|
}
|
||||||
|
if (renderable.get())
|
||||||
|
initContextFirstTime();
|
||||||
|
else
|
||||||
|
assert getType() == Type.Canvas;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void create(){
|
public void create(){
|
||||||
@ -109,6 +189,10 @@ public abstract class LwjglContext implements JmeContext {
|
|||||||
return created.get();
|
return created.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isRenderable(){
|
||||||
|
return renderable.get();
|
||||||
|
}
|
||||||
|
|
||||||
public void setSettings(AppSettings settings) {
|
public void setSettings(AppSettings settings) {
|
||||||
this.settings.copyFrom(settings);
|
this.settings.copyFrom(settings);
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,7 @@ import java.util.logging.Logger;
|
|||||||
import org.lwjgl.opengl.ARBMultisample;
|
import org.lwjgl.opengl.ARBMultisample;
|
||||||
import org.lwjgl.opengl.ContextAttribs;
|
import org.lwjgl.opengl.ContextAttribs;
|
||||||
import org.lwjgl.opengl.GL11;
|
import org.lwjgl.opengl.GL11;
|
||||||
|
import org.lwjgl.opengl.GLContext;
|
||||||
import org.lwjgl.opengl.PixelFormat;
|
import org.lwjgl.opengl.PixelFormat;
|
||||||
|
|
||||||
public class LwjglDisplay extends LwjglAbstractDisplay {
|
public class LwjglDisplay extends LwjglAbstractDisplay {
|
||||||
@ -118,28 +119,66 @@ public class LwjglDisplay extends LwjglAbstractDisplay {
|
|||||||
Display.setVSyncEnabled(settings.isVSync());
|
Display.setVSyncEnabled(settings.isVSync());
|
||||||
|
|
||||||
if (!created.get() || pixelFormatChanged){
|
if (!created.get() || pixelFormatChanged){
|
||||||
if (settings.getBoolean("GraphicsDebug") || settings.getRenderer().equals(AppSettings.LWJGL_OPENGL3)){
|
ContextAttribs attr = createContextAttribs();
|
||||||
ContextAttribs attr;
|
if (attr != null){
|
||||||
if (settings.getRenderer().equals(AppSettings.LWJGL_OPENGL3)){
|
|
||||||
attr = new ContextAttribs(3, 3);
|
|
||||||
attr = attr.withProfileCore(true).withForwardCompatible(true).withProfileCompatibility(false);
|
|
||||||
}else{
|
|
||||||
attr = new ContextAttribs();
|
|
||||||
}
|
|
||||||
if (settings.getBoolean("GraphicsDebug")){
|
|
||||||
attr = attr.withDebug(true);
|
|
||||||
}
|
|
||||||
Display.create(pixelFormat, attr);
|
Display.create(pixelFormat, attr);
|
||||||
}else{
|
}else{
|
||||||
Display.create(pixelFormat);
|
Display.create(pixelFormat);
|
||||||
}
|
}
|
||||||
|
renderable.set(true);
|
||||||
|
|
||||||
if (pixelFormatChanged && pixelFormat.getSamples() > 1){
|
if (pixelFormatChanged && pixelFormat.getSamples() > 1
|
||||||
|
&& GLContext.getCapabilities().GL_ARB_multisample){
|
||||||
GL11.glEnable(ARBMultisample.GL_MULTISAMPLE_ARB);
|
GL11.glEnable(ARBMultisample.GL_MULTISAMPLE_ARB);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void create(boolean waitFor){
|
||||||
|
if (created.get()){
|
||||||
|
logger.warning("create() called when display is already created!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
new Thread(this, "LWJGL Renderer Thread").start();
|
||||||
|
if (waitFor)
|
||||||
|
waitFor(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void runLoop(){
|
||||||
|
// This method is overriden to do restart
|
||||||
|
if (needRestart.getAndSet(false)){
|
||||||
|
try{
|
||||||
|
createContext(settings);
|
||||||
|
}catch (LWJGLException ex){
|
||||||
|
logger.log(Level.SEVERE, "Failed to set display settings!", ex);
|
||||||
|
}
|
||||||
|
listener.reshape(settings.getWidth(), settings.getHeight());
|
||||||
|
logger.info("Display restarted.");
|
||||||
|
}
|
||||||
|
|
||||||
|
super.runLoop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restart() {
|
||||||
|
if (created.get()){
|
||||||
|
needRestart.set(true);
|
||||||
|
}else{
|
||||||
|
logger.warning("Display is not created, cannot restart window.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type getType() {
|
||||||
|
return Type.Display;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title){
|
||||||
|
if (created.get())
|
||||||
|
Display.setTitle(title);
|
||||||
|
}
|
||||||
|
|
||||||
private ByteBuffer[] imagesToByteBuffers(BufferedImage[] images) {
|
private ByteBuffer[] imagesToByteBuffers(BufferedImage[] images) {
|
||||||
ByteBuffer[] out = new ByteBuffer[images.length];
|
ByteBuffer[] out = new ByteBuffer[images.length];
|
||||||
for (int i = 0; i < images.length; i++) {
|
for (int i = 0; i < images.length; i++) {
|
||||||
@ -176,49 +215,4 @@ public class LwjglDisplay extends LwjglAbstractDisplay {
|
|||||||
return ByteBuffer.wrap(imageBuffer);
|
return ByteBuffer.wrap(imageBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void create(boolean waitFor){
|
|
||||||
if (created.get()){
|
|
||||||
logger.warning("create() called when display is already created!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
new Thread(this, "LWJGL Renderer Thread").start();
|
|
||||||
if (waitFor)
|
|
||||||
waitFor(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void runLoop(){
|
|
||||||
if (needRestart.getAndSet(false)){
|
|
||||||
try{
|
|
||||||
createContext(settings);
|
|
||||||
}catch (LWJGLException ex){
|
|
||||||
logger.log(Level.SEVERE, "Failed to set display settings!", ex);
|
|
||||||
}
|
|
||||||
listener.reshape(settings.getWidth(), settings.getHeight());
|
|
||||||
logger.info("Display restarted.");
|
|
||||||
}
|
|
||||||
|
|
||||||
super.runLoop();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void restart() {
|
|
||||||
if (created.get()){
|
|
||||||
needRestart.set(true);
|
|
||||||
}else{
|
|
||||||
logger.warning("Display is not created, cannot restart window.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Type getType() {
|
|
||||||
return Type.Display;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTitle(String title){
|
|
||||||
if (created.get())
|
|
||||||
Display.setTitle(title);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -42,15 +42,11 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import org.lwjgl.LWJGLException;
|
import org.lwjgl.LWJGLException;
|
||||||
import org.lwjgl.Sys;
|
import org.lwjgl.Sys;
|
||||||
import org.lwjgl.opengl.GL11;
|
|
||||||
import org.lwjgl.opengl.GL20;
|
|
||||||
import org.lwjgl.opengl.GLContext;
|
|
||||||
import org.lwjgl.opengl.OpenGLException;
|
import org.lwjgl.opengl.OpenGLException;
|
||||||
import org.lwjgl.opengl.Pbuffer;
|
import org.lwjgl.opengl.Pbuffer;
|
||||||
import org.lwjgl.opengl.PixelFormat;
|
import org.lwjgl.opengl.PixelFormat;
|
||||||
import org.lwjgl.opengl.Util;
|
import org.lwjgl.opengl.Util;
|
||||||
|
|
||||||
|
|
||||||
public class LwjglOffscreenBuffer extends LwjglContext implements Runnable {
|
public class LwjglOffscreenBuffer extends LwjglContext implements Runnable {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(LwjglOffscreenBuffer.class.getName());
|
private static final Logger logger = Logger.getLogger(LwjglOffscreenBuffer.class.getName());
|
||||||
@ -74,6 +70,12 @@ public class LwjglOffscreenBuffer extends LwjglContext implements Runnable {
|
|||||||
width = settings.getWidth();
|
width = settings.getWidth();
|
||||||
height = settings.getHeight();
|
height = settings.getHeight();
|
||||||
try{
|
try{
|
||||||
|
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
|
||||||
|
public void uncaughtException(Thread thread, Throwable thrown) {
|
||||||
|
listener.handleError("Uncaught exception thrown in "+thread.toString(), thrown);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
//String rendererStr = settings.getString("Renderer");
|
//String rendererStr = settings.getString("Renderer");
|
||||||
// if (rendererStr.startsWith("LWJGL-OpenGL3")){
|
// if (rendererStr.startsWith("LWJGL-OpenGL3")){
|
||||||
// ContextAttribs attribs;
|
// ContextAttribs attribs;
|
||||||
@ -86,35 +88,15 @@ public class LwjglOffscreenBuffer extends LwjglContext implements Runnable {
|
|||||||
// attribs.withDebug(false);
|
// attribs.withDebug(false);
|
||||||
// Display.create(pf, attribs);
|
// Display.create(pf, attribs);
|
||||||
// }else{
|
// }else{
|
||||||
pbuffer = new Pbuffer(width, height, pixelFormat, null);
|
pbuffer = new Pbuffer(width, height, pixelFormat, null, null, createContextAttribs());
|
||||||
// }
|
// }
|
||||||
|
|
||||||
pbuffer.makeCurrent();
|
pbuffer.makeCurrent();
|
||||||
|
|
||||||
|
renderable.set(true);
|
||||||
|
|
||||||
logger.info("Offscreen buffer created.");
|
logger.info("Offscreen buffer created.");
|
||||||
logger.log(Level.FINE, "Running on thread: {0}", Thread.currentThread().getName());
|
printContextInitInfo();
|
||||||
|
|
||||||
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
|
|
||||||
public void uncaughtException(Thread thread, Throwable thrown) {
|
|
||||||
listener.handleError("Uncaught exception thrown in "+thread.toString(), thrown);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
String vendor = GL11.glGetString(GL11.GL_VENDOR);
|
|
||||||
logger.log(Level.INFO, "Vendor: {0}", vendor);
|
|
||||||
|
|
||||||
String version = GL11.glGetString(GL11.GL_VERSION);
|
|
||||||
logger.log(Level.INFO, "OpenGL Version: {0}", version);
|
|
||||||
|
|
||||||
String renderer = GL11.glGetString(GL11.GL_RENDERER);
|
|
||||||
logger.log(Level.INFO, "Renderer: {0}", renderer);
|
|
||||||
|
|
||||||
if (GLContext.getCapabilities().OpenGL20){
|
|
||||||
String shadingLang = GL11.glGetString(GL20.GL_SHADING_LANGUAGE_VERSION);
|
|
||||||
logger.log(Level.INFO, "GLSL Ver: {0}", shadingLang);
|
|
||||||
}
|
|
||||||
|
|
||||||
created.set(true);
|
|
||||||
} catch (LWJGLException ex){
|
} catch (LWJGLException ex){
|
||||||
listener.handleError("Failed to create display", ex);
|
listener.handleError("Failed to create display", ex);
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -14,7 +14,7 @@ import javax.swing.JFrame;
|
|||||||
|
|
||||||
public class TestSafeCanvas extends SimpleApplication {
|
public class TestSafeCanvas extends SimpleApplication {
|
||||||
|
|
||||||
public static void main(String[] args){
|
public static void main(String[] args) throws InterruptedException{
|
||||||
AppSettings settings = new AppSettings(true);
|
AppSettings settings = new AppSettings(true);
|
||||||
settings.setWidth(640);
|
settings.setWidth(640);
|
||||||
settings.setHeight(480);
|
settings.setHeight(480);
|
||||||
@ -28,6 +28,10 @@ public class TestSafeCanvas extends SimpleApplication {
|
|||||||
Canvas canvas = context.getCanvas();
|
Canvas canvas = context.getCanvas();
|
||||||
canvas.setSize(settings.getWidth(), settings.getHeight());
|
canvas.setSize(settings.getWidth(), settings.getHeight());
|
||||||
|
|
||||||
|
app.startCanvas(true);
|
||||||
|
|
||||||
|
Thread.sleep(3000);
|
||||||
|
|
||||||
JFrame frame = new JFrame("Test");
|
JFrame frame = new JFrame("Test");
|
||||||
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
|
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
|
||||||
frame.addWindowListener(new WindowAdapter() {
|
frame.addWindowListener(new WindowAdapter() {
|
||||||
@ -40,6 +44,14 @@ public class TestSafeCanvas extends SimpleApplication {
|
|||||||
frame.pack();
|
frame.pack();
|
||||||
frame.setLocationRelativeTo(null);
|
frame.setLocationRelativeTo(null);
|
||||||
frame.setVisible(true);
|
frame.setVisible(true);
|
||||||
|
|
||||||
|
Thread.sleep(3000);
|
||||||
|
|
||||||
|
frame.getContentPane().remove(canvas);
|
||||||
|
|
||||||
|
Thread.sleep(3000);
|
||||||
|
|
||||||
|
frame.getContentPane().add(canvas);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
x
Reference in New Issue
Block a user