Hello,
If you use startCanvas(), startCanvas(true) or startCanvas(false) instead of createCanvas() no context gets initialized resulting in a NPE.
Only a very small change is needes, basically replace the startCanvas(boolean waitFor) in the Application.java with following:
[java]
public void startCanvas(boolean waitFor) {
if (context == null) {
context = JmeSystem.newContext(settings, JmeContext.Type.Canvas);
context.setSystemListener(this);
}
context.create(waitFor);
}
[/java]
Unfortunatly my auto formatter reformated all the code so the patch is quite long
[patch]
This patch file was generated by NetBeans IDE
It uses platform neutral UTF-8 encoding and n newlines.
— Base (BASE)
+++ Locally Modified (Based On LOCAL)
@@ -53,11 +53,13 @@
import java.util.logging.Logger;
/**
-
- The <code>Application</code> class represents an instance of a
- The <code>Application</code> class represents an instance of a
-
- real-time 3D rendering jME application.
- real-time 3D rendering jME application.
-
- The
- The
-
- <code>Application</code> class represents an instance of a real-time 3D
- <code>Application</code> class represents an instance of a real-time 3D
-
- rendering jME application.
*
- rendering jME application.
-
- An <code>Application</code> provides all the tools that are commonly used in jME3
- An <code>Application</code> provides all the tools that are commonly used in jME3
-
- applications.
- applications.
-
- An
- An
-
- <code>Application</code> provides all the tools that are commonly used in
- <code>Application</code> provides all the tools that are commonly used in
-
- jME3 applications.
*
- jME3 applications.
- jME3 applications should extend this class and call start() to begin the
- application.
@@ -66,21 +68,17 @@
public class Application implements SystemListener {
private static final Logger logger = Logger.getLogger(Application.class.getName());
-
protected AssetManager assetManager;
-
protected AudioRenderer audioRenderer;
protected Renderer renderer;
protected RenderManager renderManager;
protected ViewPort viewPort;
protected ViewPort guiViewPort;
-
protected JmeContext context;
protected AppSettings settings;
protected Timer timer = new NanoTimer();
protected Camera cam;
protected Listener listener;
-
protected boolean inputEnabled = true;
protected boolean pauseOnFocus = true;
protected float speed = 1f;
@@ -91,13 +89,13 @@
protected TouchInput touchInput;
protected InputManager inputManager;
protected AppStateManager stateManager;
-
private final ConcurrentLinkedQueue<AppTask<?>> taskQueue = new ConcurrentLinkedQueue<AppTask<?>>();
/**
-
* Create a new instance of <code>Application</code>.<br />
-
* Create a new instance of<br />
-
* <code>Application</code>.<br />
*/
- public Application(){
- public Application() {
initStateManager();
}
@@ -113,15 +111,12 @@
}
/**
-
* Enable or disable pause on lost focus.<br />
-
* <p><br />
-
* By default, pause on lost focus is enabled.<br />
-
* If enabled, the application will stop updating<br />
-
* when it loses focus or becomes inactive (e.g. alt-tab).<br />
-
* For online or real-time applications, this might not be preferable,<br />
-
* so this feature should be set to disabled. For other applications,<br />
-
* it is best to keep it on so that CPU usage is not used when<br />
-
* not necessary.<br />
-
* Enable or disable pause on lost focus. <p> By default, pause on lost<br />
-
* focus is enabled. If enabled, the application will stop updating when it<br />
-
* loses focus or becomes inactive (e.g. alt-tab). For online or real-time<br />
-
* applications, this might not be preferable, so this feature should be set<br />
-
* to disabled. For other applications, it is best to keep it on so that CPU<br />
-
* usage is not used when not necessary.<br />
*
-
@param pauseOnLostFocus True to enable pause on lost focus, false
- otherwise.
@@ -131,18 +126,19 @@
}
@Deprecated
- public void setAssetManager(AssetManager assetManager){
-
if (this.assetManager != null)<br />
- public void setAssetManager(AssetManager assetManager) {
-
if (this.assetManager != null) {<br />
throw new IllegalStateException("Can only set asset manager"
- " before initialization.");
-
}<br />
this.assetManager = assetManager;
}
- private void initAssetManager(){
- if (settings != null){
+ private void initAssetManager() {
+ if (settings != null) {
String assetCfg = settings.getString("AssetConfigURL");
- if (assetCfg != null){
+ if (assetCfg != null) {
URL url = null;
try {
url = new URL(assetCfg);
@@ -158,7 +154,7 @@
assetManager = JmeSystem.newAssetManager(url);
}
}
- if (assetManager == null){
+ if (assetManager == null) {
assetManager = JmeSystem.newAssetManager(
Thread.currentThread().getContextClassLoader()
.getResource("com/jme3/asset/Desktop.cfg"));
@@ -166,37 +162,36 @@
}
/**
- * Set the display settings to define the display created.
- * <p>
- * Examples of display parameters include display pixel width and height,
- * color bit depth, z-buffer bits, anti-aliasing samples, and update frequency.
- * If this method is called while the application is already running, then
+ * Set the display settings to define the display created. <p> Examples of
+ * display parameters include display pixel width and height, color bit
+ * depth, z-buffer bits, anti-aliasing samples, and update frequency. If
+ * this method is called while the application is already running, then
* {@link #restart() } must be called to apply the settings to the display.
*
* @param settings The settings to set.
*/
- public void setSettings(AppSettings settings){
+ public void setSettings(AppSettings settings) {
this.settings = settings;
- if (context != null && settings.useInput() != inputEnabled){
+ if (context != null && settings.useInput() != inputEnabled) {
// may need to create or destroy input based
// on settings change
inputEnabled = !inputEnabled;
- if (inputEnabled){
+ if (inputEnabled) {
initInput();
- }else{
+ } else {
destroyInput();
}
- }else{
+ } else {
inputEnabled = settings.useInput();
}
}
/**
- * Sets the Timer implementation that will be used for calculating
- * frame times. By default, Application will use the Timer as returned
- * by the current JmeContext implementation.
+ * Sets the Timer implementation that will be used for calculating frame
+ * times. By default, Application will use the Timer as returned by the
+ * current JmeContext implementation.
*/
- public void setTimer(Timer timer){
+ public void setTimer(Timer timer) {
this.timer = timer;
if (timer != null) {
@@ -208,11 +203,11 @@
}
}
- public Timer getTimer(){
+ public Timer getTimer() {
return timer;
}
- private void initDisplay(){
+ private void initDisplay() {
// aquire important objects
// from the context
settings = context.getSettings();
@@ -225,8 +220,8 @@
renderer = context.getRenderer();
}
- private void initAudio(){
- if (settings.getAudioRenderer() != null && context.getType() != Type.Headless){
+ private void initAudio() {
+ if (settings.getAudioRenderer() != null && context.getType() != Type.Headless) {
audioRenderer = JmeSystem.newAudioRenderer(settings);
audioRenderer.initialize();
AudioContext.setAudioRenderer(audioRenderer);
@@ -241,10 +236,10 @@
* projection with 45° field of view, with near and far values 1 and 1000
* units respectively.
*/
- private void initCamera(){
+ private void initCamera() {
cam = new Camera(settings.getWidth(), settings.getHeight());
- cam.setFrustumPerspective(45f, (float)cam.getWidth() / cam.getHeight(), 1f, 1000f);
+ cam.setFrustumPerspective(45f, (float) cam.getWidth() / cam.getHeight(), 1f, 1000f);
cam.setLocation(new Vector3f(0f, 0f, 10f));
cam.lookAt(new Vector3f(0f, 0f, 0f), Vector3f.UNIT_Y);
@@ -261,33 +256,36 @@
}
/**
- * Initializes mouse and keyboard input. Also
- * initializes joystick input if joysticks are enabled in the
- * AppSettings.
+ * Initializes mouse and keyboard input. Also initializes joystick input if
+ * joysticks are enabled in the AppSettings.
*/
- private void initInput(){
+ private void initInput() {
mouseInput = context.getMouseInput();
- if (mouseInput != null)
+ if (mouseInput != null) {
mouseInput.initialize();
+ }
keyInput = context.getKeyInput();
- if (keyInput != null)
+ if (keyInput != null) {
keyInput.initialize();
+ }
touchInput = context.getTouchInput();
- if (touchInput != null)
+ if (touchInput != null) {
touchInput.initialize();
+ }
- if (!settings.getBoolean("DisableJoysticks")){
+ if (!settings.getBoolean("DisableJoysticks")) {
joyInput = context.getJoyInput();
- if (joyInput != null)
+ if (joyInput != null) {
joyInput.initialize();
}
+ }
inputManager = new InputManager(mouseInput, keyInput, joyInput, touchInput);
}
- private void initStateManager(){
+ private void initStateManager() {
stateManager = new AppStateManager(this);
// Always register a ResetStatsState to make sure
@@ -298,14 +296,14 @@
/**
* @return The {@link AssetManager asset manager} for this application.
*/
- public AssetManager getAssetManager(){
+ public AssetManager getAssetManager() {
return assetManager;
}
/**
* @return the {@link InputManager input manager}.
*/
- public InputManager getInputManager(){
+ public InputManager getInputManager() {
return inputManager;
}
@@ -326,7 +324,7 @@
/**
* @return The {@link Renderer renderer} for the application
*/
- public Renderer getRenderer(){
+ public Renderer getRenderer() {
return renderer;
}
@@ -347,14 +345,14 @@
/**
* @return The {@link JmeContext display context} for the application
*/
- public JmeContext getContext(){
+ public JmeContext getContext() {
return context;
}
/**
* @return The {@link Camera camera} for the application
*/
- public Camera getCamera(){
+ public Camera getCamera() {
return cam;
}
@@ -363,22 +361,21 @@
*
* @see #start(com.jme3.system.JmeContext.Type)
*/
- public void start(){
+ public void start() {
start(JmeContext.Type.Display);
}
/**
- * Starts the application.
- * Creating a rendering context and executing
- * the main loop in a separate thread.
+ * Starts the application. Creating a rendering context and executing the
+ * main loop in a separate thread.
*/
- public void start(JmeContext.Type contextType){
- if (context != null && context.isCreated()){
+ public void start(JmeContext.Type contextType) {
+ if (context != null && context.isCreated()) {
logger.warning("start() called when application already created!");
return;
}
- if (settings == null){
+ if (settings == null) {
settings = new AppSettings(true);
}
@@ -389,27 +386,25 @@
}
/**
- * Initializes the application's canvas for use.
- * <p>
- * After calling this method, cast the {@link #getContext() context} to
- * {@link JmeCanvasContext},
- * then acquire the canvas with {@link JmeCanvasContext#getCanvas() }
- * and attach it to an AWT/Swing Frame.
- * The rendering thread will start when the canvas becomes visible on
- * screen, however if you wish to start the context immediately you
- * may call {@link #startCanvas() } to force the rendering thread
- * to start.
+ * Initializes the application's canvas for use. <p> After calling this
+ * method, cast the {@link #getContext() context} to
+ * {@link JmeCanvasContext}, then acquire the canvas with {@link JmeCanvasContext#getCanvas()
+ * }
+ * and attach it to an AWT/Swing Frame. The rendering thread will start when
+ * the canvas becomes visible on screen, however if you wish to start the
+ * context immediately you may call {@link #startCanvas() } to force the
+ * rendering thread to start.
*
* @see JmeCanvasContext
* @see Type#Canvas
*/
- public void createCanvas(){
- if (context != null && context.isCreated()){
+ public void createCanvas() {
+ if (context != null && context.isCreated()) {
logger.warning("createCanvas() called when application already created!");
return;
}
- if (settings == null){
+ if (settings == null) {
settings = new AppSettings(true);
}
@@ -419,89 +414,87 @@
}
/**
- * Starts the rendering thread after createCanvas() has been called.
- * <p>
+ * Starts the rendering thread after createCanvas() has been called. <p>
* Same as calling startCanvas(false)
*
* @see #startCanvas(boolean)
*/
- public void startCanvas(){
+ public void startCanvas() {
startCanvas(false);
}
/**
- * Starts the rendering thread after createCanvas() has been called.
- * <p>
- * Calling this method is optional, the canvas will start automatically
- * when it becomes visible.
+ * Starts the rendering thread after createCanvas() has been called. <p>
+ * Calling this method is optional, the canvas will start automatically when
+ * it becomes visible.
*
- * @param waitFor If true, the current thread will block until the
- * rendering thread is running
+ * @param waitFor If true, the current thread will block until the rendering
+ * thread is running
*/
- public void startCanvas(boolean waitFor){
+ public void startCanvas(boolean waitFor) {
+ if (context == null) {
+ context = JmeSystem.newContext(settings, JmeContext.Type.Canvas);
+ context.setSystemListener(this);
+ }
context.create(waitFor);
}
/**
* Internal use only.
*/
- public void reshape(int w, int h){
+ public void reshape(int w, int h) {
renderManager.notifyReshape(w, h);
}
/**
- * Restarts the context, applying any changed settings.
- * <p>
- * Changes to the {@link AppSettings} of this Application are not
- * applied immediately; calling this method forces the context
- * to restart, applying the new settings.
+ * Restarts the context, applying any changed settings. <p> Changes to the
+ * {@link AppSettings} of this Application are not applied immediately;
+ * calling this method forces the context to restart, applying the new
+ * settings.
*/
- public void restart(){
+ public void restart() {
context.setSettings(settings);
context.restart();
}
/**
- * Requests the context to close, shutting down the main loop
- * and making necessary cleanup operations.
+ * Requests the context to close, shutting down the main loop and making
+ * necessary cleanup operations.
*
* Same as calling stop(false)
*
* @see #stop(boolean)
*/
- public void stop(){
+ public void stop() {
stop(false);
}
/**
- * Requests the context to close, shutting down the main loop
- * and making necessary cleanup operations.
- * After the application has stopped, it cannot be used anymore.
+ * Requests the context to close, shutting down the main loop and making
+ * necessary cleanup operations. After the application has stopped, it
+ * cannot be used anymore.
*/
- public void stop(boolean waitFor){
+ public void stop(boolean waitFor) {
logger.log(Level.FINE, "Closing application: {0}", getClass().getName());
context.destroy(waitFor);
}
/**
- * Do not call manually.
- * Callback from ContextListener.
- * <p>
- * Initializes the <code>Application</code>, by creating a display and
- * default camera. If display settings are not specified, a default
- * 640x480 display is created. Default values are used for the camera;
- * perspective projection with 45° field of view, with near
- * and far values 1 and 1000 units respectively.
+ * Do not call manually. Callback from ContextListener. <p> Initializes the
+ * <code>Application</code>, by creating a display and default camera. If
+ * display settings are not specified, a default 640x480 display is created.
+ * Default values are used for the camera; perspective projection with 45°
+ * field of view, with near and far values 1 and 1000 units respectively.
*/
- public void initialize(){
- if (assetManager == null){
+ public void initialize() {
+ if (assetManager == null) {
initAssetManager();
}
initDisplay();
initCamera();
- if (inputEnabled){
+ if (inputEnabled) {
initInput();
}
initAudio();
@@ -516,13 +509,13 @@
/**
* Internal use only.
*/
- public void handleError(String errMsg, Throwable t){
+ public void handleError(String errMsg, Throwable t) {
// Print error to log.
logger.log(Level.SEVERE, errMsg, t);
// Display error message on screen
if (t != null) {
- JmeSystem.showErrorDialog(errMsg + "n" + t.getClass().getSimpleName() +
- (t.getMessage() != null ? ": " + t.getMessage() : ""));
+ JmeSystem.showErrorDialog(errMsg + "n" + t.getClass().getSimpleName()
+ + (t.getMessage() != null ? ": " + t.getMessage() : ""));
} else {
JmeSystem.showErrorDialog(errMsg);
}
@@ -533,7 +526,7 @@
/**
* Internal use only.
*/
- public void gainFocus(){
+ public void gainFocus() {
if (pauseOnFocus) {
paused = false;
context.setAutoFlushFrames(true);
@@ -546,8 +539,8 @@
/**
* Internal use only.
*/
- public void loseFocus(){
- if (pauseOnFocus){
+ public void loseFocus() {
+ if (pauseOnFocus) {
paused = true;
context.setAutoFlushFrames(false);
}
@@ -556,17 +549,14 @@
/**
* Internal use only.
*/
- public void requestClose(boolean esc){
+ public void requestClose(boolean esc) {
context.destroy(false);
}
/**
- * Enqueues a task/callable object to execute in the jME3
- * rendering thread.
- * <p>
- * Callables are executed right at the beginning of the main loop.
- * They are executed even if the application is currently paused
- * or out of focus.
+ * Enqueues a task/callable object to execute in the jME3 rendering thread.
+ * <p> Callables are executed right at the beginning of the main loop. They
+ * are executed even if the application is currently paused or out of focus.
*/
public <V> Future<V> enqueue(Callable<V> callable) {
AppTask<V> task = new AppTask<V>(callable);
@@ -579,7 +569,7 @@
*/
protected void runQueuedTasks() {
AppTask<?> task;
- while( (task = taskQueue.poll()) != null ) {
+ while ((task = taskQueue.poll()) != null) {
if (!task.isCancelled()) {
task.invoke();
}
@@ -587,64 +577,68 @@
}
/**
- * Do not call manually.
- * Callback from ContextListener.
+ * Do not call manually. Callback from ContextListener.
*/
- public void update(){
+ public void update() {
// Make sure the audio renderer is available to callables
AudioContext.setAudioRenderer(audioRenderer);
runQueuedTasks();
- if (speed == 0 || paused)
+ if (speed == 0 || paused) {
return;
+ }
timer.update();
- if (inputEnabled){
+ if (inputEnabled) {
inputManager.update(timer.getTimePerFrame());
}
- if (audioRenderer != null){
+ if (audioRenderer != null) {
audioRenderer.update(timer.getTimePerFrame());
}
// user code here..
}
- protected void destroyInput(){
- if (mouseInput != null)
+ protected void destroyInput() {
+ if (mouseInput != null) {
mouseInput.destroy();
+ }
- if (keyInput != null)
+ if (keyInput != null) {
keyInput.destroy();
+ }
- if (joyInput != null)
+ if (joyInput != null) {
joyInput.destroy();
+ }
- if (touchInput != null)
+ if (touchInput != null) {
touchInput.destroy();
+ }
inputManager = null;
}
/**
- * Do not call manually.
- * Callback from ContextListener.
+ * Do not call manually. Callback from ContextListener.
*/
- public void destroy(){
+ public void destroy() {
stateManager.cleanup();
destroyInput();
- if (audioRenderer != null)
+ if (audioRenderer != null) {
audioRenderer.cleanup();
+ }
timer.reset();
}
/**
- * @return The GUI viewport. Which is used for the on screen
- * statistics and FPS.
+ * @return The GUI viewport. Which is used for the on screen statistics and
+ * FPS.
*/
public ViewPort getGuiViewPort() {
return guiViewPort;
@@ -653,5 +647,4 @@
public ViewPort getViewPort() {
return viewPort;
}
-
}
[/patch]