diff --git a/jme3-android/src/main/java/com/jme3/system/android/OGLESContext.java b/jme3-android/src/main/java/com/jme3/system/android/OGLESContext.java index 8d3d28f89c..005a579b7e 100644 --- a/jme3-android/src/main/java/com/jme3/system/android/OGLESContext.java +++ b/jme3-android/src/main/java/com/jme3/system/android/OGLESContext.java @@ -556,17 +556,15 @@ private Rect getSurfaceFrame() { return result; } - @Override - public Monitors getMonitors() - { - // TODO Auto-generated method stub - return null; - } - - @Override - public int getPrimaryMonitor() - { - // TODO Auto-generated method stub - return 0; - } -} + @Override + public Monitors getMonitors() { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getPrimaryMonitor() { + // TODO Auto-generated method stub + return 0; + } + } diff --git a/jme3-core/src/main/java/com/jme3/app/LegacyApplication.java b/jme3-core/src/main/java/com/jme3/app/LegacyApplication.java index 0f172d37f2..e74874b095 100644 --- a/jme3-core/src/main/java/com/jme3/app/LegacyApplication.java +++ b/jme3-core/src/main/java/com/jme3/app/LegacyApplication.java @@ -1,33 +1,27 @@ /* - * Copyright (c) 2009-2022 jMonkeyEngine - * All rights reserved. + * Copyright (c) 2009-2022 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: + * 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 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. + * * 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. + * * 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. + * 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.app; @@ -56,824 +50,792 @@ import java.util.logging.Logger; /** - * The LegacyApplication class represents an instance of a - * real-time 3D rendering jME application. + * The LegacyApplication class represents an instance of a real-time 3D rendering jME + * application. * * An LegacyApplication provides all the tools that are commonly used in jME3 * applications. * - * jME3 applications *SHOULD NOT EXTEND* this class but extend {@link com.jme3.app.SimpleApplication} instead. + * jME3 applications *SHOULD NOT EXTEND* this class but extend + * {@link com.jme3.app.SimpleApplication} instead. * */ public class LegacyApplication implements Application, SystemListener { - private static final Logger logger = Logger.getLogger(LegacyApplication.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 LostFocusBehavior lostFocusBehavior = LostFocusBehavior.ThrottleOnLostFocus; - protected float speed = 1f; - protected boolean paused = false; - protected MouseInput mouseInput; - protected KeyInput keyInput; - protected JoyInput joyInput; - protected TouchInput touchInput; - protected InputManager inputManager; - protected AppStateManager stateManager; - - protected AppProfiler prof; - - private final ConcurrentLinkedQueue> taskQueue = new ConcurrentLinkedQueue<>(); - - /** - * Create a new instance of LegacyApplication. - */ - public LegacyApplication() { - this((AppState[]) null); - } - - /** - * Create a new instance of LegacyApplication, preinitialized - * with the specified set of app states. - * - * @param initialStates app states to pre-attach, or null for none - */ - public LegacyApplication(AppState... initialStates) { - initStateManager(); - - if (initialStates != null) { - for (AppState a : initialStates) { - if (a != null) { - stateManager.attach(a); - } - } - } - } - - /** - * Determine the application's behavior when unfocused. - * - * @return The lost focus behavior of the application. - */ - @Override - public LostFocusBehavior getLostFocusBehavior() { - return lostFocusBehavior; - } - - /** - * Changes the application's behavior when unfocused. - * - * By default, the application will - * {@link LostFocusBehavior#ThrottleOnLostFocus throttle the update loop} - * so as not to use 100% of the CPU when out of focus, e.g. - * alt-tabbed, minimized, or hidden by another window. - * - * @param lostFocusBehavior The new lost focus behavior to use. - * - * @see LostFocusBehavior - */ - @Override - public void setLostFocusBehavior(LostFocusBehavior lostFocusBehavior) { - this.lostFocusBehavior = lostFocusBehavior; - } - - /** - * Returns true if pause on lost focus is enabled, false otherwise. - * - * @return true if pause on lost focus is enabled - * - * @see #getLostFocusBehavior() - */ - @Override - public boolean isPauseOnLostFocus() { - return getLostFocusBehavior() == LostFocusBehavior.PauseOnLostFocus; - } - - /** - * Enable or disable pause on lost focus. - *

- * By default, pause on lost focus is enabled. - * If enabled, the application will stop updating - * when it loses focus or becomes inactive (e.g. alt-tab). - * For online or real-time applications, this might be undesirable, - * so this feature should be disabled. For other applications, - * it is best to keep it enabled so the CPU is not used unnecessarily. - * - * @param pauseOnLostFocus True to enable pause on lost focus, false - * otherwise. - * - * @see #setLostFocusBehavior(com.jme3.app.LostFocusBehavior) - */ - @Override - public void setPauseOnLostFocus(boolean pauseOnLostFocus) { - if (pauseOnLostFocus) { - setLostFocusBehavior(LostFocusBehavior.PauseOnLostFocus); - } else { - setLostFocusBehavior(LostFocusBehavior.Disabled); + private static final Logger logger = Logger.getLogger(LegacyApplication.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 LostFocusBehavior lostFocusBehavior = LostFocusBehavior.ThrottleOnLostFocus; + protected float speed = 1f; + protected boolean paused = false; + protected MouseInput mouseInput; + protected KeyInput keyInput; + protected JoyInput joyInput; + protected TouchInput touchInput; + protected InputManager inputManager; + protected AppStateManager stateManager; + + protected AppProfiler prof; + + private final ConcurrentLinkedQueue> taskQueue = new ConcurrentLinkedQueue<>(); + + /** + * Create a new instance of LegacyApplication. + */ + public LegacyApplication() { + this((AppState[]) null); + } + + /** + * Create a new instance of LegacyApplication, preinitialized with the specified set + * of app states. + * + * @param initialStates app states to pre-attach, or null for none + */ + public LegacyApplication(AppState... initialStates) { + initStateManager(); + + if (initialStates != null) { + for (AppState a : initialStates) { + if (a != null) { + stateManager.attach(a); } - } - - @Deprecated - public void setAssetManager(AssetManager assetManager) { - if (this.assetManager != null) - throw new IllegalStateException("Can only set asset manager" - + " before initialization."); - - this.assetManager = assetManager; - } - - private void initAssetManager() { - URL assetCfgUrl = null; - - if (settings != null) { - String assetCfg = settings.getString("AssetConfigURL"); - if (assetCfg != null) { - try { - assetCfgUrl = new URL(assetCfg); - } catch (MalformedURLException ex) { - } - if (assetCfgUrl == null) { - assetCfgUrl = LegacyApplication.class.getClassLoader().getResource(assetCfg); - if (assetCfgUrl == null) { - logger.log(Level.SEVERE, "Unable to access AssetConfigURL in asset config:{0}", assetCfg); - return; - } - } - } + } + } + } + + /** + * Determine the application's behavior when unfocused. + * + * @return The lost focus behavior of the application. + */ + @Override + public LostFocusBehavior getLostFocusBehavior() { + return lostFocusBehavior; + } + + /** + * Changes the application's behavior when unfocused. + * + * By default, the application will {@link LostFocusBehavior#ThrottleOnLostFocus throttle the + * update loop} so as not to use 100% of the CPU when out of focus, e.g. alt-tabbed, minimized, or + * hidden by another window. + * + * @param lostFocusBehavior The new lost focus behavior to use. + * + * @see LostFocusBehavior + */ + @Override + public void setLostFocusBehavior(LostFocusBehavior lostFocusBehavior) { + this.lostFocusBehavior = lostFocusBehavior; + } + + /** + * Returns true if pause on lost focus is enabled, false otherwise. + * + * @return true if pause on lost focus is enabled + * + * @see #getLostFocusBehavior() + */ + @Override + public boolean isPauseOnLostFocus() { + return getLostFocusBehavior() == LostFocusBehavior.PauseOnLostFocus; + } + + /** + * Enable or disable pause on lost focus. + *

+ * By default, pause on lost focus is enabled. If enabled, the application will stop updating when + * it loses focus or becomes inactive (e.g. alt-tab). For online or real-time applications, this + * might be undesirable, so this feature should be disabled. For other applications, it is best to + * keep it enabled so the CPU is not used unnecessarily. + * + * @param pauseOnLostFocus True to enable pause on lost focus, false otherwise. + * + * @see #setLostFocusBehavior(com.jme3.app.LostFocusBehavior) + */ + @Override + public void setPauseOnLostFocus(boolean pauseOnLostFocus) { + if (pauseOnLostFocus) { + setLostFocusBehavior(LostFocusBehavior.PauseOnLostFocus); + } else { + setLostFocusBehavior(LostFocusBehavior.Disabled); + } + } + + @Deprecated + public void setAssetManager(AssetManager assetManager) { + if (this.assetManager != null) + throw new IllegalStateException("Can only set asset manager" + " before initialization."); + + this.assetManager = assetManager; + } + + private void initAssetManager() { + URL assetCfgUrl = null; + + if (settings != null) { + String assetCfg = settings.getString("AssetConfigURL"); + if (assetCfg != null) { + try { + assetCfgUrl = new URL(assetCfg); + } catch (MalformedURLException ex) { } if (assetCfgUrl == null) { - assetCfgUrl = JmeSystem.getPlatformAssetConfigURL(); - } - if (assetManager == null) { - assetManager = JmeSystem.newAssetManager(assetCfgUrl); - } - } - - /** - * Set the display settings to define the display created. - *

- * 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. - */ - @Override - public void setSettings(AppSettings settings) { - this.settings = settings; - if (context != null && settings.useInput() != inputEnabled) { - // may need to create or destroy input based - // on settings change - inputEnabled = !inputEnabled; - if (inputEnabled) { - initInput(); - } else { - destroyInput(); - } - } 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. - */ - @Override - public void setTimer(Timer timer) { - this.timer = timer; - - if (timer != null) { - timer.reset(); - } - - if (renderManager != null) { - renderManager.setTimer(timer); - } - } - - @Override - public Timer getTimer() { - return timer; - } - - private void initDisplay() { - // acquire important objects - // from the context - settings = context.getSettings(); - - // Only reset the timer if a user has not already provided one - if (timer == null) { - timer = context.getTimer(); - } - - renderer = context.getRenderer(); - } - - private void initAudio() { - if (settings.getAudioRenderer() != null && context.getType() != Type.Headless) { - audioRenderer = JmeSystem.newAudioRenderer(settings); - audioRenderer.initialize(); - AudioContext.setAudioRenderer(audioRenderer); - - listener = new Listener(); - audioRenderer.setListener(listener); - } - } - - /** - * Creates the camera to use for rendering. Default values are perspective - * projection with 45° field of view, with near and far values 1 and 1000 - * units respectively. - */ - private void initCamera() { - cam = new Camera(settings.getWidth(), settings.getHeight()); - - 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); - - renderManager = new RenderManager(renderer); - //Remy - 09/14/2010 set the timer in the renderManager - renderManager.setTimer(timer); - - if (prof != null) { - renderManager.setAppProfiler(prof); - } - - viewPort = renderManager.createMainView("Default", cam); - viewPort.setClearFlags(true, true, true); - - // Create a new cam for the gui - Camera guiCam = new Camera(settings.getWidth(), settings.getHeight()); - guiViewPort = renderManager.createPostView("Gui Default", guiCam); - guiViewPort.setClearFlags(false, false, false); - } - - /** - * Initializes mouse and keyboard input. Also - * initializes joystick input if joysticks are enabled in the - * AppSettings. - */ - private void initInput() { - mouseInput = context.getMouseInput(); - if (mouseInput != null) - mouseInput.initialize(); - - keyInput = context.getKeyInput(); - if (keyInput != null) - keyInput.initialize(); - - touchInput = context.getTouchInput(); - if (touchInput != null) - touchInput.initialize(); - - if (settings.useJoysticks()) { - joyInput = context.getJoyInput(); - if (joyInput != null) - joyInput.initialize(); - } - - inputManager = new InputManager(mouseInput, keyInput, joyInput, touchInput); - } - - private void initStateManager() { - stateManager = new AppStateManager(this); - - // Always register a ResetStatsState to make sure - // that the stats are cleared every frame - stateManager.attach(new ResetStatsState()); - } - - /** - * @return The {@link AssetManager asset manager} for this application. - */ - @Override - public AssetManager getAssetManager() { - return assetManager; - } - - /** - * @return the {@link InputManager input manager}. - */ - @Override - public InputManager getInputManager() { - return inputManager; - } - - /** - * @return the {@link AppStateManager app state manager} - */ - @Override - public AppStateManager getStateManager() { - return stateManager; - } - - /** - * @return the {@link RenderManager render manager} - */ - @Override - public RenderManager getRenderManager() { - return renderManager; - } - - /** - * @return The {@link Renderer renderer} for the application - */ - @Override - public Renderer getRenderer() { - return renderer; - } - - /** - * @return The {@link AudioRenderer audio renderer} for the application - */ - @Override - public AudioRenderer getAudioRenderer() { - return audioRenderer; - } - - /** - * @return The {@link Listener listener} object for audio - */ - @Override - public Listener getListener() { - return listener; - } - - /** - * @return The {@link JmeContext display context} for the application - */ - @Override - public JmeContext getContext() { - return context; - } - - /** - * @return The {@link Camera camera} for the application - */ - @Override - public Camera getCamera() { - return cam; - } - - /** - * Starts the application in {@link Type#Display display} mode. - * - * @see #start(com.jme3.system.JmeContext.Type) - */ - @Override - public void start() { - start(JmeContext.Type.Display, false); - } - - /** - * Starts the application in {@link Type#Display display} mode. - * - * @param waitFor true→wait for the context to be initialized, - * false→don't wait - * @see #start(com.jme3.system.JmeContext.Type) - */ - @Override - public void start(boolean waitFor) { - start(JmeContext.Type.Display, waitFor); - } - - /** - * Starts the application. - * Creating a rendering context and executing - * the main loop in a separate thread. - * - * @param contextType the type of context to create - */ - public void start(JmeContext.Type contextType) { - start(contextType, false); - } - - /** - * Starts the application. - * Creating a rendering context and executing - * the main loop in a separate thread. - * - * @param contextType the type of context to create - * @param waitFor true→wait for the context to be initialized, - * false→don't wait - */ - public void start(JmeContext.Type contextType, boolean waitFor) { - if (context != null && context.isCreated()) { - logger.warning("start() called when application already created!"); + assetCfgUrl = LegacyApplication.class.getClassLoader().getResource(assetCfg); + if (assetCfgUrl == null) { + logger.log(Level.SEVERE, "Unable to access AssetConfigURL in asset config:{0}", + assetCfg); return; + } } - - if (settings == null) { - settings = new AppSettings(true); - } - - logger.log(Level.FINE, "Starting application: {0}", getClass().getName()); - context = JmeSystem.newContext(settings, contextType); - context.setSystemListener(this); - context.create(waitFor); - } - - /** - * Sets an AppProfiler hook that will be called back for - * specific steps within a single update frame. Value defaults - * to null. - * - * @param prof the profiler to use (alias created) or null for none - */ - @Override - public void setAppProfiler(AppProfiler prof) { - this.prof = prof; - if (renderManager != null) { - renderManager.setAppProfiler(prof); - } - } - - /** - * Returns the current AppProfiler hook, or null if none is set. - */ - @Override - public AppProfiler getAppProfiler() { - return prof; - } - - /** - * Initializes the application's canvas for use. - *

- * After calling this method, cast the {@link #getContext()} context to - * JmeCanvasContext, - * then acquire the canvas with 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 Type#Canvas - */ - public void createCanvas() { - if (context != null && context.isCreated()) { - logger.warning("createCanvas() called when application already created!"); - return; - } - - if (settings == null) { - settings = new AppSettings(true); - } - - if (logger.isLoggable(Level.FINE)) { - logger.log(Level.FINE, "Starting application: {0}", getClass().getName()); - } - context = JmeSystem.newContext(settings, JmeContext.Type.Canvas); - context.setSystemListener(this); - } - - /** - * Starts the rendering thread after createCanvas() has been called. - *

- * Same as calling startCanvas(false) - * - * @see #startCanvas(boolean) - */ - public void startCanvas() { - startCanvas(false); - } - - /** - * Starts the rendering thread after createCanvas() has been called. - *

- * 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 - */ - public void startCanvas(boolean waitFor) { - context.create(waitFor); - } - - /** - * Internal use only. - */ - @Override - public void reshape(int w, int h) { - if (renderManager != null) { - renderManager.notifyReshape(w, h); - } - } - - - @Override - public void rescale(float x, float y){ - if (renderManager != null) { - renderManager.notifyRescale(x, y); - } - } - - /** - * Restarts the context, applying any changed settings. - *

- * Changes to the {@link AppSettings} of this Application are not - * applied immediately; calling this method forces the context - * to restart, applying the new settings. - */ - @Override - public void restart() { - context.setSettings(settings); - context.restart(); - } - - /** - * Requests the context to close, shutting down the main loop - * and making necessary cleanup operations. - * - * Same as calling stop(false) - * - * @see #stop(boolean) - */ - @Override - 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. - * - * @param waitFor true→wait for the context to be fully destroyed, - * true→don't wait - */ - @Override - public void stop(boolean waitFor) { - logger.log(Level.FINE, "Closing application: {0}", getClass().getName()); - context.destroy(waitFor); - } - - /** - * Do not call manually. - * Callback from ContextListener. - *

- * Initializes the Application, 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. - */ - @Override - public void initialize() { - if (assetManager == null) { - initAssetManager(); - } - - initDisplay(); - initCamera(); - - if (inputEnabled) { - initInput(); - } - initAudio(); - - // update timer so that the next delta is not too large -// timer.update(); - timer.reset(); - - // user code here - } - - /** - * Internal use only. - */ - @Override - public void handleError(String errMsg, Throwable t) { - // Print error to log. - logger.log(Level.SEVERE, errMsg, t); - // Display error message on screen if not in headless mode - if (context.getType() != JmeContext.Type.Headless) { - if (t != null) { - JmeSystem.handleErrorMessage(errMsg + "\n" + t.getClass().getSimpleName() - + (t.getMessage() != null ? ": " + t.getMessage() : "")); - } else { - JmeSystem.handleErrorMessage(errMsg); - } - } - - stop(); // stop the application - } - - /** - * Internal use only. - */ - @Override - public void gainFocus() { - if (lostFocusBehavior != LostFocusBehavior.Disabled) { - if (lostFocusBehavior == LostFocusBehavior.PauseOnLostFocus) { - paused = false; - } - context.setAutoFlushFrames(true); - if (inputManager != null) { - inputManager.reset(); - } - } - } - - /** - * Internal use only. - */ - @Override - public void loseFocus() { - if (lostFocusBehavior != LostFocusBehavior.Disabled) { - if (lostFocusBehavior == LostFocusBehavior.PauseOnLostFocus) { - paused = true; - } - context.setAutoFlushFrames(false); - } - } - - /** - * Internal use only. - */ - @Override - public void requestClose(boolean esc) { - context.destroy(false); - } - - /** - * Enqueues a task/callable object to execute in the jME3 - * rendering thread. - *

- * 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. - * - * @param type of result returned by the Callable - * @param callable The callable to run in the main jME3 thread - * @return a new instance - */ - @Override - public Future enqueue(Callable callable) { - AppTask task = new AppTask<>(callable); - taskQueue.add(task); - return task; - } - - /** - * Enqueues a runnable object to execute in the jME3 - * rendering thread. - *

- * Runnables are executed right at the beginning of the main loop. - * They are executed even if the application is currently paused - * or out of focus. - * - * @param runnable The runnable to run in the main jME3 thread - */ - @Override - @SuppressWarnings("unchecked") - public void enqueue(Runnable runnable) { - enqueue(new RunnableWrapper(runnable)); - } - - /** - * Runs tasks enqueued via {@link #enqueue(Callable)} - */ - protected void runQueuedTasks() { - AppTask task; - while ((task = taskQueue.poll()) != null) { - if (!task.isCancelled()) { - task.invoke(); - } - } - } - - /** - * Do not call manually. - * Callback from ContextListener. - */ - @Override - public void update() { - // Make sure the audio renderer is available to callables - AudioContext.setAudioRenderer(audioRenderer); - - if (prof != null) - prof.appStep(AppStep.QueuedTasks); - runQueuedTasks(); - - if (speed == 0 || paused) - return; - - timer.update(); - - if (inputEnabled) { - if (prof != null) - prof.appStep(AppStep.ProcessInput); - inputManager.update(timer.getTimePerFrame()); - } - - if (audioRenderer != null) { - if (prof != null) - prof.appStep(AppStep.ProcessAudio); - audioRenderer.update(timer.getTimePerFrame()); - } - - // user code here - } - - protected void destroyInput() { - if (mouseInput != null) - mouseInput.destroy(); - - if (keyInput != null) - keyInput.destroy(); - - if (joyInput != null) - joyInput.destroy(); - - if (touchInput != null) - touchInput.destroy(); - - inputManager = null; - } - - /** - * Do not call manually. - * Callback from ContextListener. - */ - @Override - public void destroy() { - stateManager.cleanup(); - + } + } + if (assetCfgUrl == null) { + assetCfgUrl = JmeSystem.getPlatformAssetConfigURL(); + } + if (assetManager == null) { + assetManager = JmeSystem.newAssetManager(assetCfgUrl); + } + } + + /** + * Set the display settings to define the display created. + *

+ * 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. + */ + @Override + public void setSettings(AppSettings settings) { + this.settings = settings; + if (context != null && settings.useInput() != inputEnabled) { + // may need to create or destroy input based + // on settings change + inputEnabled = !inputEnabled; + if (inputEnabled) { + initInput(); + } else { destroyInput(); - if (audioRenderer != null) - audioRenderer.cleanup(); - - timer.reset(); + } + } else { + inputEnabled = settings.useInput(); } + } - /** - * @return The GUI viewport. Which is used for the on screen - * statistics and FPS. - */ - @Override - public ViewPort getGuiViewPort() { - return guiViewPort; - } + /** + * 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. + */ + @Override + public void setTimer(Timer timer) { + this.timer = timer; - @Override - public ViewPort getViewPort() { - return viewPort; + if (timer != null) { + timer.reset(); } - private class RunnableWrapper implements Callable { - private final Runnable runnable; + if (renderManager != null) { + renderManager.setTimer(timer); + } + } - public RunnableWrapper(Runnable runnable) { - this.runnable = runnable; - } + @Override + public Timer getTimer() { + return timer; + } + + private void initDisplay() { + // acquire important objects + // from the context + settings = context.getSettings(); + + // Only reset the timer if a user has not already provided one + if (timer == null) { + timer = context.getTimer(); + } + + renderer = context.getRenderer(); + } + + private void initAudio() { + if (settings.getAudioRenderer() != null && context.getType() != Type.Headless) { + audioRenderer = JmeSystem.newAudioRenderer(settings); + audioRenderer.initialize(); + AudioContext.setAudioRenderer(audioRenderer); + + listener = new Listener(); + audioRenderer.setListener(listener); + } + } + + /** + * Creates the camera to use for rendering. Default values are perspective projection with 45° + * field of view, with near and far values 1 and 1000 units respectively. + */ + private void initCamera() { + cam = new Camera(settings.getWidth(), settings.getHeight()); + + 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); + + renderManager = new RenderManager(renderer); + // Remy - 09/14/2010 set the timer in the renderManager + renderManager.setTimer(timer); + + if (prof != null) { + renderManager.setAppProfiler(prof); + } + + viewPort = renderManager.createMainView("Default", cam); + viewPort.setClearFlags(true, true, true); + + // Create a new cam for the gui + Camera guiCam = new Camera(settings.getWidth(), settings.getHeight()); + guiViewPort = renderManager.createPostView("Gui Default", guiCam); + guiViewPort.setClearFlags(false, false, false); + } + + /** + * Initializes mouse and keyboard input. Also initializes joystick input if joysticks are enabled + * in the AppSettings. + */ + private void initInput() { + mouseInput = context.getMouseInput(); + if (mouseInput != null) + mouseInput.initialize(); + + keyInput = context.getKeyInput(); + if (keyInput != null) + keyInput.initialize(); + + touchInput = context.getTouchInput(); + if (touchInput != null) + touchInput.initialize(); + + if (settings.useJoysticks()) { + joyInput = context.getJoyInput(); + if (joyInput != null) + joyInput.initialize(); + } + + inputManager = new InputManager(mouseInput, keyInput, joyInput, touchInput); + } + + private void initStateManager() { + stateManager = new AppStateManager(this); + + // Always register a ResetStatsState to make sure + // that the stats are cleared every frame + stateManager.attach(new ResetStatsState()); + } + + /** + * @return The {@link AssetManager asset manager} for this application. + */ + @Override + public AssetManager getAssetManager() { + return assetManager; + } + + /** + * @return the {@link InputManager input manager}. + */ + @Override + public InputManager getInputManager() { + return inputManager; + } + + /** + * @return the {@link AppStateManager app state manager} + */ + @Override + public AppStateManager getStateManager() { + return stateManager; + } + + /** + * @return the {@link RenderManager render manager} + */ + @Override + public RenderManager getRenderManager() { + return renderManager; + } + + /** + * @return The {@link Renderer renderer} for the application + */ + @Override + public Renderer getRenderer() { + return renderer; + } + + /** + * @return The {@link AudioRenderer audio renderer} for the application + */ + @Override + public AudioRenderer getAudioRenderer() { + return audioRenderer; + } + + /** + * @return The {@link Listener listener} object for audio + */ + @Override + public Listener getListener() { + return listener; + } + + /** + * @return The {@link JmeContext display context} for the application + */ + @Override + public JmeContext getContext() { + return context; + } + + /** + * @return The {@link Camera camera} for the application + */ + @Override + public Camera getCamera() { + return cam; + } + + /** + * Starts the application in {@link Type#Display display} mode. + * + * @see #start(com.jme3.system.JmeContext.Type) + */ + @Override + public void start() { + start(JmeContext.Type.Display, false); + } + + /** + * Starts the application in {@link Type#Display display} mode. + * + * @param waitFor true→wait for the context to be initialized, false→don't wait + * @see #start(com.jme3.system.JmeContext.Type) + */ + @Override + public void start(boolean waitFor) { + start(JmeContext.Type.Display, waitFor); + } + + /** + * Starts the application. Creating a rendering context and executing the main loop in a separate + * thread. + * + * @param contextType the type of context to create + */ + public void start(JmeContext.Type contextType) { + start(contextType, false); + } + + /** + * Starts the application. Creating a rendering context and executing the main loop in a separate + * thread. + * + * @param contextType the type of context to create + * @param waitFor true→wait for the context to be initialized, false→don't wait + */ + public void start(JmeContext.Type contextType, boolean waitFor) { + if (context != null && context.isCreated()) { + logger.warning("start() called when application already created!"); + return; + } + + if (settings == null) { + settings = new AppSettings(true); + } + + logger.log(Level.FINE, "Starting application: {0}", getClass().getName()); + context = JmeSystem.newContext(settings, contextType); + context.setSystemListener(this); + context.create(waitFor); + } + + /** + * Sets an AppProfiler hook that will be called back for specific steps within a single update + * frame. Value defaults to null. + * + * @param prof the profiler to use (alias created) or null for none + */ + @Override + public void setAppProfiler(AppProfiler prof) { + this.prof = prof; + if (renderManager != null) { + renderManager.setAppProfiler(prof); + } + } + + /** + * Returns the current AppProfiler hook, or null if none is set. + */ + @Override + public AppProfiler getAppProfiler() { + return prof; + } + + /** + * Initializes the application's canvas for use. + *

+ * After calling this method, cast the {@link #getContext()} context to JmeCanvasContext, then + * acquire the canvas with 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 Type#Canvas + */ + public void createCanvas() { + if (context != null && context.isCreated()) { + logger.warning("createCanvas() called when application already created!"); + return; + } + + if (settings == null) { + settings = new AppSettings(true); + } + + if (logger.isLoggable(Level.FINE)) { + logger.log(Level.FINE, "Starting application: {0}", getClass().getName()); + } + context = JmeSystem.newContext(settings, JmeContext.Type.Canvas); + context.setSystemListener(this); + } + + /** + * Starts the rendering thread after createCanvas() has been called. + *

+ * Same as calling startCanvas(false) + * + * @see #startCanvas(boolean) + */ + public void startCanvas() { + startCanvas(false); + } + + /** + * Starts the rendering thread after createCanvas() has been called. + *

+ * 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 + */ + public void startCanvas(boolean waitFor) { + context.create(waitFor); + } + + /** + * Internal use only. + */ + @Override + public void reshape(int w, int h) { + if (renderManager != null) { + renderManager.notifyReshape(w, h); + } + } + + + @Override + public void rescale(float x, float y) { + if (renderManager != null) { + renderManager.notifyRescale(x, y); + } + } + + /** + * Restarts the context, applying any changed settings. + *

+ * Changes to the {@link AppSettings} of this Application are not applied immediately; calling + * this method forces the context to restart, applying the new settings. + */ + @Override + public void restart() { + context.setSettings(settings); + context.restart(); + } + + /** + * Requests the context to close, shutting down the main loop and making necessary cleanup + * operations. + * + * Same as calling stop(false) + * + * @see #stop(boolean) + */ + @Override + 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. + * + * @param waitFor true→wait for the context to be fully destroyed, true→don't wait + */ + @Override + public void stop(boolean waitFor) { + logger.log(Level.FINE, "Closing application: {0}", getClass().getName()); + context.destroy(waitFor); + } + + /** + * Do not call manually. Callback from ContextListener. + *

+ * Initializes the Application, 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. + */ + @Override + public void initialize() { + if (assetManager == null) { + initAssetManager(); + } + + initDisplay(); + initCamera(); + + if (inputEnabled) { + initInput(); + } + initAudio(); + + // update timer so that the next delta is not too large + // timer.update(); + timer.reset(); + + // user code here + } + + /** + * Internal use only. + */ + @Override + public void handleError(String errMsg, Throwable t) { + // Print error to log. + logger.log(Level.SEVERE, errMsg, t); + // Display error message on screen if not in headless mode + if (context.getType() != JmeContext.Type.Headless) { + if (t != null) { + JmeSystem.handleErrorMessage(errMsg + "\n" + t.getClass().getSimpleName() + + (t.getMessage() != null ? ": " + t.getMessage() : "")); + } else { + JmeSystem.handleErrorMessage(errMsg); + } + } + + stop(); // stop the application + } + + /** + * Internal use only. + */ + @Override + public void gainFocus() { + if (lostFocusBehavior != LostFocusBehavior.Disabled) { + if (lostFocusBehavior == LostFocusBehavior.PauseOnLostFocus) { + paused = false; + } + context.setAutoFlushFrames(true); + if (inputManager != null) { + inputManager.reset(); + } + } + } + + /** + * Internal use only. + */ + @Override + public void loseFocus() { + if (lostFocusBehavior != LostFocusBehavior.Disabled) { + if (lostFocusBehavior == LostFocusBehavior.PauseOnLostFocus) { + paused = true; + } + context.setAutoFlushFrames(false); + } + } + + /** + * Internal use only. + */ + @Override + public void requestClose(boolean esc) { + context.destroy(false); + } + + /** + * Enqueues a task/callable object to execute in the jME3 rendering thread. + *

+ * 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. + * + * @param type of result returned by the Callable + * @param callable The callable to run in the main jME3 thread + * @return a new instance + */ + @Override + public Future enqueue(Callable callable) { + AppTask task = new AppTask<>(callable); + taskQueue.add(task); + return task; + } + + /** + * Enqueues a runnable object to execute in the jME3 rendering thread. + *

+ * Runnables are executed right at the beginning of the main loop. They are executed even if the + * application is currently paused or out of focus. + * + * @param runnable The runnable to run in the main jME3 thread + */ + @Override + @SuppressWarnings("unchecked") + public void enqueue(Runnable runnable) { + enqueue(new RunnableWrapper(runnable)); + } + + /** + * Runs tasks enqueued via {@link #enqueue(Callable)} + */ + protected void runQueuedTasks() { + AppTask task; + while ((task = taskQueue.poll()) != null) { + if (!task.isCancelled()) { + task.invoke(); + } + } + } + + /** + * Do not call manually. Callback from ContextListener. + */ + @Override + public void update() { + // Make sure the audio renderer is available to callables + AudioContext.setAudioRenderer(audioRenderer); + + if (prof != null) + prof.appStep(AppStep.QueuedTasks); + runQueuedTasks(); + + if (speed == 0 || paused) + return; + + timer.update(); + + if (inputEnabled) { + if (prof != null) + prof.appStep(AppStep.ProcessInput); + inputManager.update(timer.getTimePerFrame()); + } + + if (audioRenderer != null) { + if (prof != null) + prof.appStep(AppStep.ProcessAudio); + audioRenderer.update(timer.getTimePerFrame()); + } + + // user code here + } + + protected void destroyInput() { + if (mouseInput != null) + mouseInput.destroy(); + + if (keyInput != null) + keyInput.destroy(); + + if (joyInput != null) + joyInput.destroy(); + + if (touchInput != null) + touchInput.destroy(); + + inputManager = null; + } + + /** + * Do not call manually. Callback from ContextListener. + */ + @Override + public void destroy() { + stateManager.cleanup(); + + destroyInput(); + if (audioRenderer != null) + audioRenderer.cleanup(); + + timer.reset(); + } + + /** + * @return The GUI viewport. Which is used for the on screen statistics and FPS. + */ + @Override + public ViewPort getGuiViewPort() { + return guiViewPort; + } + + @Override + public ViewPort getViewPort() { + return viewPort; + } + + private class RunnableWrapper implements Callable { + private final Runnable runnable; + + public RunnableWrapper(Runnable runnable) { + this.runnable = runnable; + } + + @Override + public Object call() { + runnable.run(); + return null; + } + } + + /** + * This call will return a list of Monitors that glfwGetMonitors() returns and information about + * the monitor, like width, height, and refresh rate. + * + * @return returns a list of monitors and their information. + */ + public Monitors getMonitors() { + return context.getMonitors(); + } - @Override - public Object call() { - runnable.run(); - return null; - } - } - - /** - * This call will return a list of Monitors that glfwGetMonitors() - * returns and information about the monitor, like width, height, - * and refresh rate. - * - * @return returns a list of monitors and their information. - */ - public Monitors getMonitors() - { - return context.getMonitors(); - } - - /** - * Use this to get the positional number of the primary - * monitor from the glfwGetMonitors() function call. - * - * @return the position of the value in the arraylist of - * the primary monitor. - */ - public int getPrimaryMonitor() - { - return context.getPrimaryMonitor(); - } + /** + * Use this to get the positional number of the primary monitor from the glfwGetMonitors() + * function call. + * + * @return the position of the value in the arraylist of the primary monitor. + */ + public int getPrimaryMonitor() { + return context.getPrimaryMonitor(); + } } diff --git a/jme3-core/src/main/java/com/jme3/system/AppSettings.java b/jme3-core/src/main/java/com/jme3/system/AppSettings.java index c5509301ac..cfa98ec41e 100644 --- a/jme3-core/src/main/java/com/jme3/system/AppSettings.java +++ b/jme3-core/src/main/java/com/jme3/system/AppSettings.java @@ -1485,27 +1485,29 @@ public void setWindowYPosition(int pos) { /** * Gets the monitor number used when creating a window. * - *

This setting is used only with LWJGL3, it defines which monitor - * to use when creating a OpenGL window. + *

+ * This setting is used only with LWJGL3, it defines which monitor to use when creating a OpenGL + * window. * * @return the desired monitor used when creating a OpenGL window * @see #setMonitor(long) */ public int getMonitor() { - return getInteger("Monitor"); + return getInteger("Monitor"); } /** - * Sets the monitor number used when creating a window. The position - * number is the number in the list of monitors GlfwGetMonitors returns. + * Sets the monitor number used when creating a window. The position number is the number in the + * list of monitors GlfwGetMonitors returns. * - *

This setting is used only with LWJGL3, it defines which monitor - * to use when creating a OpenGL window. its default value is 0. + *

+ * This setting is used only with LWJGL3, it defines which monitor to use when creating a OpenGL + * window. its default value is 0. * * @param mon the desired monitor used when creating a OpenGL window * */ public void setMonitor(int mon) { - putInteger("Monitor", mon); + putInteger("Monitor", mon); } -} + } diff --git a/jme3-core/src/main/java/com/jme3/system/JmeContext.java b/jme3-core/src/main/java/com/jme3/system/JmeContext.java index 59d7cdbb05..258639634f 100644 --- a/jme3-core/src/main/java/com/jme3/system/JmeContext.java +++ b/jme3-core/src/main/java/com/jme3/system/JmeContext.java @@ -227,20 +227,18 @@ public enum Type { public int getWindowYPosition(); /** - * This call will return a list of Monitors that glfwGetMonitors() - * returns and information about the monitor, like width, height, - * and refresh rate. + * This call will return a list of Monitors that glfwGetMonitors() returns and information about + * the monitor, like width, height, and refresh rate. * * @return returns a list of monitors and their information. */ public Monitors getMonitors(); /** - * Use this to get the positional number of the primary - * monitor from the glfwGetMonitors() function call. + * Use this to get the positional number of the primary monitor from the glfwGetMonitors() + * function call. * - * @return the position of the value in the arraylist of - * the primary monitor. - */ + * @return the position of the value in the arraylist of the primary monitor. + */ public int getPrimaryMonitor(); -} + } diff --git a/jme3-core/src/main/java/com/jme3/system/MonitorInfo.java b/jme3-core/src/main/java/com/jme3/system/MonitorInfo.java index 64864fb70e..a7791d37b2 100644 --- a/jme3-core/src/main/java/com/jme3/system/MonitorInfo.java +++ b/jme3-core/src/main/java/com/jme3/system/MonitorInfo.java @@ -1,73 +1,66 @@ /* - * Copyright (c) 2009-2023 jMonkeyEngine - * All rights reserved. + * Copyright (c) 2009-2023 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: + * 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 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. + * * 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. + * * 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. + * 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.system; /** - * This class holds information about the monitor that was - * returned by glfwGetMonitors() calls in the context - * class + * This class holds information about the monitor that was returned by glfwGetMonitors() calls in + * the context class * * @author Kevin Bales */ public class MonitorInfo { - - /** - * monitorID - monitor id that was return from Lwjgl3. - */ - public long monitorID = 0; - /** - * width - width that was return from Lwjgl3. - */ - public int width = 1080; + /** + * monitorID - monitor id that was return from Lwjgl3. + */ + public long monitorID = 0; - /** - * height - height that was return from Lwjgl3. - */ - public int height = 1920; + /** + * width - width that was return from Lwjgl3. + */ + public int width = 1080; - /** - * rate - refresh rate that was return from Lwjgl3. - */ - public int rate = 60; - - /** - * primary - indicates if the monitor is the primary monitor. - */ - public boolean primary = false; - - /** - * name - monitor name that was return from Lwjgl3. - */ - public String name = "Generic Monitor"; + /** + * height - height that was return from Lwjgl3. + */ + public int height = 1920; + + /** + * rate - refresh rate that was return from Lwjgl3. + */ + public int rate = 60; + + /** + * primary - indicates if the monitor is the primary monitor. + */ + public boolean primary = false; + + /** + * name - monitor name that was return from Lwjgl3. + */ + public String name = "Generic Monitor"; } diff --git a/jme3-core/src/main/java/com/jme3/system/Monitors.java b/jme3-core/src/main/java/com/jme3/system/Monitors.java index 61a874d201..b834e518f8 100644 --- a/jme3-core/src/main/java/com/jme3/system/Monitors.java +++ b/jme3-core/src/main/java/com/jme3/system/Monitors.java @@ -1,119 +1,105 @@ /* - * Copyright (c) 2009-2023 jMonkeyEngine - * All rights reserved. + * Copyright (c) 2009-2023 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: + * 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 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. + * * 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. + * * 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. + * 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.system; import java.util.ArrayList; /** - * This class holds all information about all monitors that where - * return from the glfwGetMonitors() call. It stores them into - * an + * This class holds all information about all monitors that where return from the glfwGetMonitors() + * call. It stores them into an * * @author Kevin Bales */ public class Monitors { - private ArrayList monitors = new ArrayList(); - - public int addNewMonitor(long monitorID) - { - MonitorInfo info = new MonitorInfo(); - info.monitorID = monitorID; - monitors.add(info); - return monitors.size() - 1; - } - - /** - * This function returns the size of the monitor ArrayList - * @return the - */ - public int size() - { - return monitors.size(); - } - - /** - * Call to get monitor information on a certain monitor. - * - * @param pos the position in the arraylist of the monitor - * information that you want to get. - * @return returns the MonitorInfo data for the monitor - * called for. - */ - public MonitorInfo get(int pos) - { - if (pos < monitors.size()) - return monitors.get(pos); - - return null; - } + private ArrayList monitors = new ArrayList(); - /** - * Set information about this monitor stored in monPos position - * in the array list. - * - * @param monPos arraylist position of monitor to update - * @param width the current width the monitor is displaying - * @param height the current height the monitor is displaying - * @param rate the current refresh rate the monitor is set to - */ - public void setInfo(int monPos, String name, int width, int height, int rate) { - if (monPos < monitors.size() ) { - MonitorInfo info = monitors.get(monPos); - if (info != null) { - info.width = width; - info.height = height; - info.rate = rate; - info.name = name; - } - } - } + public int addNewMonitor(long monitorID) { + MonitorInfo info = new MonitorInfo(); + info.monitorID = monitorID; + monitors.add(info); + return monitors.size() - 1; + } + + /** + * This function returns the size of the monitor ArrayList + * + * @return the + */ + public int size() { + return monitors.size(); + } + + /** + * Call to get monitor information on a certain monitor. + * + * @param pos the position in the arraylist of the monitor information that you want to get. + * @return returns the MonitorInfo data for the monitor called for. + */ + public MonitorInfo get(int pos) { + if (pos < monitors.size()) + return monitors.get(pos); + + return null; + } - /** - * This function will mark a certain monitor as the - * primary monitor. - * - * @param monPos the position in the arraylist of which - * monitor is the primary monitor - */ - public void setPrimaryMonitor(int monPos) { - if (monPos < monitors.size() ) { - MonitorInfo info = monitors.get(monPos); - if (info != null) - info.primary = true; + /** + * Set information about this monitor stored in monPos position in the array list. + * + * @param monPos arraylist position of monitor to update + * @param width the current width the monitor is displaying + * @param height the current height the monitor is displaying + * @param rate the current refresh rate the monitor is set to + */ + public void setInfo(int monPos, String name, int width, int height, int rate) { + if (monPos < monitors.size()) { + MonitorInfo info = monitors.get(monPos); + if (info != null) { + info.width = width; + info.height = height; + info.rate = rate; + info.name = name; } - - } - - + } + } + + /** + * This function will mark a certain monitor as the primary monitor. + * + * @param monPos the position in the arraylist of which monitor is the primary monitor + */ + public void setPrimaryMonitor(int monPos) { + if (monPos < monitors.size()) { + MonitorInfo info = monitors.get(monPos); + if (info != null) + info.primary = true; + } + + } + + } diff --git a/jme3-core/src/main/java/com/jme3/system/NullContext.java b/jme3-core/src/main/java/com/jme3/system/NullContext.java index f0eccdc112..e58f143b45 100644 --- a/jme3-core/src/main/java/com/jme3/system/NullContext.java +++ b/jme3-core/src/main/java/com/jme3/system/NullContext.java @@ -307,15 +307,15 @@ public int getWindowYPosition() { throw new UnsupportedOperationException("null context"); } - @Override - public Monitors getMonitors() { + @Override + public Monitors getMonitors() { // TODO Auto-generated method stub return null; - } + } - @Override - public int getPrimaryMonitor() { + @Override + public int getPrimaryMonitor() { // TODO Auto-generated method stub return 0; - } + } } diff --git a/jme3-desktop/src/main/java/com/jme3/system/awt/AwtPanelsContext.java b/jme3-desktop/src/main/java/com/jme3/system/awt/AwtPanelsContext.java index 23a46c8930..afb8003fcd 100644 --- a/jme3-desktop/src/main/java/com/jme3/system/awt/AwtPanelsContext.java +++ b/jme3-desktop/src/main/java/com/jme3/system/awt/AwtPanelsContext.java @@ -329,15 +329,15 @@ public int getWindowYPosition() { return inputSource.getY(); } - @Override - public Monitors getMonitors() { - // TODO Auto-generated method stub - return null; - } - - @Override - public int getPrimaryMonitor() { - // TODO Auto-generated method stub - return 0; - } + @Override + public Monitors getMonitors() { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getPrimaryMonitor() { + // TODO Auto-generated method stub + return 0; + } } diff --git a/jme3-examples/src/main/java/jme3test/app/TestMonitorApp.java b/jme3-examples/src/main/java/jme3test/app/TestMonitorApp.java index f673c22afc..bf3b837fdd 100644 --- a/jme3-examples/src/main/java/jme3test/app/TestMonitorApp.java +++ b/jme3-examples/src/main/java/jme3test/app/TestMonitorApp.java @@ -53,199 +53,188 @@ import com.jme3.system.Monitors; /** - * Tests the capability to change which monitor the window - * will be created on. Also, shows that you can force - * JME to center the window. Also, it shows to to force JME to - * set the window to x,y coords. Center window and window - * position doesn't apply if in fullscreen. + * Tests the capability to change which monitor the window will be created on. + * Also, shows that you can force JME to center the window. Also, it shows to to + * force JME to set the window to x,y coords. Center window and window position + * doesn't apply if in fullscreen. * * @author Kevin Bales */ -public class TestMonitorApp extends SimpleApplication implements ActionListener { - - private BitmapText txt; - private BitmapText selectedMonitorTxt; - private BitmapText fullScreenTxt; - private int monitorSelected = 0; - private Monitors monitors = null; - - public static void main(String[] args){ - TestMonitorApp app = new TestMonitorApp(); - AppSettings settings = new AppSettings(true); - settings.setResizable(false); - app.setShowSettings(true); - settings.setRenderer(AppSettings.LWJGL_OPENGL33); - settings.setMonitor(0); - settings.setResolution(800, 600); - - settings.setFullscreen(true); - - //Force JME to center the window, this only applies if it is - //not fullscreen. - settings.setCenterWindow(true); - - //If center window is not turned on, you can force JME to - //open the window at certain x,y coords. These are ignored - //if the screen is set to "fullscreen". - settings.setWindowXPosition(0); - settings.setWindowYPosition(0); - - try - { - //Let's try and load the AppSetting parameters back into memory - InputStream out = new FileInputStream("TestMonitorApp.prefs"); - settings.load(out); - } - catch (IOException e) - { - System.out.println("failed to load settings, reverting to defaults"); - } - app.setSettings(settings); - - app.start(); - } - - - @Override - public void simpleInitApp() { - flyCam.setDragToRotate(true); - int numMonitors = 1; - - //If monitor is define, Jme supports multiple monitors. Setup to keys - if (monitors == null) { - inputManager.addMapping("down", new KeyTrigger(KeyInput.KEY_DOWN)); - inputManager.addMapping("fullscreen", new KeyTrigger(KeyInput.KEY_F)); - inputManager.addListener(this, "down", "fullscreen"); - } - - //Get the selected monitor - monitorSelected = settings.getMonitor(); - monitors = context.getMonitors(); - if (monitors != null) - numMonitors = monitors.size(); - - - - //Let's define the labels for users to see what is going on with Multiple Monitor - String labelValue = ""; - labelValue = "There are "+numMonitors+" monitor(s) hooked up to this computer."; - txt = new BitmapText(loadGuiFont()); - txt.setText(labelValue); - txt.setLocalTranslation(0, settings.getHeight(), 0); - guiNode.attachChild(txt); - - txt = new BitmapText(loadGuiFont()); - if (!settings.isFullscreen()) - txt.setText("Window is on Monitor N/A (fullscreen only feature)"); - else - txt.setText("Window is on Monitor "+settings.getMonitor()); - - txt.setLocalTranslation(0, settings.getHeight() - 40, 0); - guiNode.attachChild(txt); - - if (monitors != null) { - selectedMonitorTxt = new BitmapText(loadGuiFont()); - //Lets display information about selected monitor - String label = "Selected Monitor "+ - "Name: "+monitors.get(settings.getMonitor()).name+" "+ - monitorSelected+ " Res: " + - monitors.get(settings.getMonitor()).width+","+ - monitors.get(settings.getMonitor()).height + - " refresh: "+monitors.get(settings.getMonitor()).rate; - selectedMonitorTxt.setText(label); - selectedMonitorTxt.setLocalTranslation(0, settings.getHeight() - 80, 0); - guiNode.attachChild(selectedMonitorTxt); - - //Let's loop through all the monitors and display on the screen - for(int i = 0; i < monitors.size(); i++) { - MonitorInfo monitor = monitors.get(i); - labelValue = "Mon : "+i+" "+monitor.name+" " + monitor.width +","+ monitor.height +" refresh: "+ monitor.rate; - txt = new BitmapText(loadGuiFont()); - txt.setText(labelValue); - txt.setLocalTranslation(0, settings.getHeight() - 160 - (40*i), 0); - guiNode.attachChild(txt); - } - } - - //Lets put a label up there for FullScreen/Window toggle - fullScreenTxt = new BitmapText(loadGuiFont()); - if (!settings.isFullscreen()) - fullScreenTxt.setText("(f) Window Screen"); - else - fullScreenTxt.setText("(f) Fullscreen"); - - fullScreenTxt.setLocalTranslation(00, settings.getHeight() - 240, 0); - guiNode.attachChild(fullScreenTxt); - - BitmapText infoTxt = new BitmapText(loadGuiFont()); - infoTxt.setText("Restart is required to activate changes in settings."); - infoTxt.setLocalTranslation(0, settings.getHeight() - 300, 0); - guiNode.attachChild(infoTxt); - - - } - - @Override - public void onAction(String name, boolean isPressed, float tpf) { +public class TestMonitorApp extends SimpleApplication + implements ActionListener { + + private BitmapText txt; + private BitmapText selectedMonitorTxt; + private BitmapText fullScreenTxt; + private int monitorSelected = 0; + private Monitors monitors = null; + + public static void main(String[] args) { + TestMonitorApp app = new TestMonitorApp(); + AppSettings settings = new AppSettings(true); + settings.setResizable(false); + app.setShowSettings(true); + settings.setRenderer(AppSettings.LWJGL_OPENGL33); + settings.setMonitor(0); + settings.setResolution(800, 600); + + settings.setFullscreen(true); + + // Force JME to center the window, this only applies if it is + // not fullscreen. + settings.setCenterWindow(true); + + // If center window is not turned on, you can force JME to + // open the window at certain x,y coords. These are ignored + // if the screen is set to "fullscreen". + settings.setWindowXPosition(0); + settings.setWindowYPosition(0); + + try { + // Let's try and load the AppSetting parameters back into memory + InputStream out = new FileInputStream("TestMonitorApp.prefs"); + settings.load(out); + } catch (IOException e) { + System.out.println("failed to load settings, reverting to defaults"); + } + app.setSettings(settings); + + app.start(); + } + + @Override + public void simpleInitApp() { + flyCam.setDragToRotate(true); + int numMonitors = 1; + + // If monitor is define, Jme supports multiple monitors. Setup to keys + if (monitors == null) { + inputManager.addMapping("down", new KeyTrigger(KeyInput.KEY_DOWN)); + inputManager.addMapping("fullscreen", new KeyTrigger(KeyInput.KEY_F)); + inputManager.addListener(this, "down", "fullscreen"); + } + + // Get the selected monitor + monitorSelected = settings.getMonitor(); + monitors = context.getMonitors(); + if (monitors != null) + numMonitors = monitors.size(); + + // Let's define the labels for users to see what is going on with Multiple + // Monitor + String labelValue = ""; + labelValue = "There are " + numMonitors + + " monitor(s) hooked up to this computer."; + txt = new BitmapText(loadGuiFont()); + txt.setText(labelValue); + txt.setLocalTranslation(0, settings.getHeight(), 0); + guiNode.attachChild(txt); + + txt = new BitmapText(loadGuiFont()); + if (!settings.isFullscreen()) + txt.setText("Window is on Monitor N/A (fullscreen only feature)"); + else + txt.setText("Window is on Monitor " + settings.getMonitor()); + + txt.setLocalTranslation(0, settings.getHeight() - 40, 0); + guiNode.attachChild(txt); + + if (monitors != null) { + selectedMonitorTxt = new BitmapText(loadGuiFont()); + // Lets display information about selected monitor + String label = "Selected Monitor " + "Name: " + + monitors.get(settings.getMonitor()).name + " " + + monitorSelected + " Res: " + + monitors.get(settings.getMonitor()).width + "," + + monitors.get(settings.getMonitor()).height + " refresh: " + + monitors.get(settings.getMonitor()).rate; + selectedMonitorTxt.setText(label); + selectedMonitorTxt.setLocalTranslation(0, settings.getHeight() - 80, + 0); + guiNode.attachChild(selectedMonitorTxt); + + // Let's loop through all the monitors and display on the screen + for (int i = 0; i < monitors.size(); i++) { + MonitorInfo monitor = monitors.get(i); + labelValue = "Mon : " + i + " " + monitor.name + " " + monitor.width + + "," + monitor.height + " refresh: " + monitor.rate; + txt = new BitmapText(loadGuiFont()); + txt.setText(labelValue); + txt.setLocalTranslation(0, settings.getHeight() - 160 - (40 * i), + 0); + guiNode.attachChild(txt); + } + } + + // Lets put a label up there for FullScreen/Window toggle + fullScreenTxt = new BitmapText(loadGuiFont()); + if (!settings.isFullscreen()) + fullScreenTxt.setText("(f) Window Screen"); + else + fullScreenTxt.setText("(f) Fullscreen"); + + fullScreenTxt.setLocalTranslation(00, settings.getHeight() - 240, 0); + guiNode.attachChild(fullScreenTxt); + + BitmapText infoTxt = new BitmapText(loadGuiFont()); + infoTxt.setText("Restart is required to activate changes in settings."); + infoTxt.setLocalTranslation(0, settings.getHeight() - 300, 0); + guiNode.attachChild(infoTxt); + + } + + @Override + public void onAction(String name, boolean isPressed, float tpf) { if (monitors == null) return; - + if (name.equals("down") && isPressed) { monitorSelected++; if (monitorSelected >= monitors.size()) monitorSelected = 0; saveSettings(); - } - else if (name.equals("up") && isPressed) { + } else if (name.equals("up") && isPressed) { monitorSelected--; if (monitorSelected < 0) - monitorSelected = monitors.size()-1; + monitorSelected = monitors.size() - 1; saveSettings(); - } - else if (name.equals("fullscreen") && isPressed) { + } else if (name.equals("fullscreen") && isPressed) { settings.setFullscreen(!settings.isFullscreen()); saveSettings(); - } + } } - - /** - * This function saves out the AppSettings into a file to be loaded back in - * on start of application. - */ - public void saveSettings() - { - - try - { - settings.setMonitor(monitorSelected); - OutputStream out = new FileOutputStream("TestMonitorApp.prefs"); - settings.save(out); - - int monitorSelected = settings.getMonitor(); - String label = "Selected Monitor "+ monitorSelected+ - " "+ monitors.get(monitorSelected).name+ - " Res: " +monitors.get(monitorSelected).width+","+ - monitors.get(monitorSelected).height + - "refresh: "+monitors.get(monitorSelected).rate; - selectedMonitorTxt.setText(label); - if (!settings.isFullscreen()) - fullScreenTxt.setText("(f) Window Screen"); - else - fullScreenTxt.setText("(f) Fullscreen"); - } - catch (FileNotFoundException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - catch (IOException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } + /** + * This function saves out the AppSettings into a file to be loaded back in + * on start of application. + */ + public void saveSettings() { + + try { + settings.setMonitor(monitorSelected); + OutputStream out = new FileOutputStream("TestMonitorApp.prefs"); + settings.save(out); + + int monitorSelected = settings.getMonitor(); + String label = "Selected Monitor " + monitorSelected + " " + + monitors.get(monitorSelected).name + " Res: " + + monitors.get(monitorSelected).width + "," + + monitors.get(monitorSelected).height + "refresh: " + + monitors.get(monitorSelected).rate; + selectedMonitorTxt.setText(label); + if (!settings.isFullscreen()) + fullScreenTxt.setText("(f) Window Screen"); + else + fullScreenTxt.setText("(f) Fullscreen"); + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } } diff --git a/jme3-ios/src/main/java/com/jme3/system/ios/IGLESContext.java b/jme3-ios/src/main/java/com/jme3/system/ios/IGLESContext.java index d19a18c44a..2a18b56569 100644 --- a/jme3-ios/src/main/java/com/jme3/system/ios/IGLESContext.java +++ b/jme3-ios/src/main/java/com/jme3/system/ios/IGLESContext.java @@ -268,17 +268,15 @@ public int getWindowYPosition() { throw new UnsupportedOperationException("not implemented yet"); } - @Override - public Monitors getMonitors() - { - // TODO Auto-generated method stub - return null; - } - - @Override - public int getPrimaryMonitor() - { - // TODO Auto-generated method stub - return 0; - } + @Override + public Monitors getMonitors() { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getPrimaryMonitor() { + // TODO Auto-generated method stub + return 0; + } } \ No newline at end of file diff --git a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java index 17d0b9bd6c..7728c11257 100644 --- a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java +++ b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java @@ -1,33 +1,27 @@ /* - * Copyright (c) 2009-2021 jMonkeyEngine - * All rights reserved. + * Copyright (c) 2009-2021 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: + * 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 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. + * * 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. + * * 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. + * 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.system.lwjgl; @@ -51,470 +45,453 @@ public class LwjglCanvas extends LwjglAbstractDisplay implements JmeCanvasContext { - protected static final int TASK_NOTHING = 0, - TASK_DESTROY_DISPLAY = 1, - TASK_CREATE_DISPLAY = 2, - TASK_COMPLETE = 3; - -// protected static final boolean USE_SHARED_CONTEXT = -// Boolean.parseBoolean(System.getProperty("jme3.canvas.sharedctx", "true")); - - protected static final boolean USE_SHARED_CONTEXT = false; - - private static final Logger logger = Logger.getLogger(LwjglDisplay.class.getName()); - private Canvas canvas; - private int width; - private int height; - - private final Object taskLock = new Object(); - private int desiredTask = TASK_NOTHING; - - private Thread renderThread; - private boolean runningFirstTime = true; - private boolean mouseWasGrabbed = false; - - private boolean mouseWasCreated = false; - private boolean keyboardWasCreated = false; - - private Pbuffer pbuffer; - private PixelFormat pbufferFormat; - private PixelFormat canvasFormat; - - private class GLCanvas extends Canvas { - @Override - public void addNotify(){ - super.addNotify(); - - if (renderThread != null && renderThread.getState() == Thread.State.TERMINATED) { - return; // already destroyed. - } - - if (renderThread == null){ - logger.log(Level.FINE, "EDT: Creating OGL thread."); - - // Also set some settings on the canvas here. - // So we don't do it outside the AWT thread. - canvas.setFocusable(true); - canvas.setIgnoreRepaint(true); - - renderThread = new Thread(LwjglCanvas.this, THREAD_NAME); - renderThread.start(); - }else if (needClose.get()){ - return; - } - - logger.log(Level.FINE, "EDT: Telling OGL to create display .."); - synchronized (taskLock){ - desiredTask = TASK_CREATE_DISPLAY; -// while (desiredTask != TASK_COMPLETE){ -// try { -// taskLock.wait(); -// } catch (InterruptedException ex) { -// return; -// } -// } -// desiredTask = TASK_NOTHING; - } -// logger.log(Level.FINE, "EDT: OGL has created the display"); - } + protected static final int TASK_NOTHING = 0, TASK_DESTROY_DISPLAY = 1, TASK_CREATE_DISPLAY = 2, + TASK_COMPLETE = 3; - @Override - public void removeNotify(){ - if (needClose.get()){ - logger.log(Level.FINE, "EDT: Application is stopped. Not restoring canvas."); - super.removeNotify(); - return; - } - - // We must tell GL context to shut down and wait for it to - // shut down. Otherwise, issues will occur. - logger.log(Level.FINE, "EDT: Telling OGL to destroy display .."); - synchronized (taskLock){ - desiredTask = TASK_DESTROY_DISPLAY; - while (desiredTask != TASK_COMPLETE){ - try { - taskLock.wait(); - } catch (InterruptedException ex){ - super.removeNotify(); - return; - } - } - desiredTask = TASK_NOTHING; - } - - logger.log(Level.FINE, "EDT: Acknowledged receipt of canvas death"); - // GL context is dead at this point + // protected static final boolean USE_SHARED_CONTEXT = + // Boolean.parseBoolean(System.getProperty("jme3.canvas.sharedctx", "true")); - super.removeNotify(); - } - } + protected static final boolean USE_SHARED_CONTEXT = false; - public LwjglCanvas(){ - super(); - canvas = new GLCanvas(); - } + private static final Logger logger = Logger.getLogger(LwjglDisplay.class.getName()); + private Canvas canvas; + private int width; + private int height; - @Override - public Type getType() { - return Type.Canvas; - } + private final Object taskLock = new Object(); + private int desiredTask = TASK_NOTHING; - @Override - public void create(boolean waitFor){ - if (renderThread == null){ - logger.log(Level.FINE, "MAIN: Creating OGL thread."); + private Thread renderThread; + private boolean runningFirstTime = true; + private boolean mouseWasGrabbed = false; - renderThread = new Thread(LwjglCanvas.this, THREAD_NAME); - renderThread.start(); - } - // do not do anything. - // superclass's create() will be called at initInThread() - if (waitFor) { - waitFor(true); - } - } + private boolean mouseWasCreated = false; + private boolean keyboardWasCreated = false; + + private Pbuffer pbuffer; + private PixelFormat pbufferFormat; + private PixelFormat canvasFormat; + private class GLCanvas extends Canvas { @Override - public void setTitle(String title) { + public void addNotify() { + super.addNotify(); + + if (renderThread != null && renderThread.getState() == Thread.State.TERMINATED) { + return; // already destroyed. + } + + if (renderThread == null) { + logger.log(Level.FINE, "EDT: Creating OGL thread."); + + // Also set some settings on the canvas here. + // So we don't do it outside the AWT thread. + canvas.setFocusable(true); + canvas.setIgnoreRepaint(true); + + renderThread = new Thread(LwjglCanvas.this, THREAD_NAME); + renderThread.start(); + } else if (needClose.get()) { + return; + } + + logger.log(Level.FINE, "EDT: Telling OGL to create display .."); + synchronized (taskLock) { + desiredTask = TASK_CREATE_DISPLAY; + // while (desiredTask != TASK_COMPLETE){ + // try { + // taskLock.wait(); + // } catch (InterruptedException ex) { + // return; + // } + // } + // desiredTask = TASK_NOTHING; + } + // logger.log(Level.FINE, "EDT: OGL has created the display"); } @Override - public void restart() { - frameRate = settings.getFrameRate(); - // TODO: Handle other cases, like change of pixel format, etc. + public void removeNotify() { + if (needClose.get()) { + logger.log(Level.FINE, "EDT: Application is stopped. Not restoring canvas."); + super.removeNotify(); + return; + } + + // We must tell GL context to shut down and wait for it to + // shut down. Otherwise, issues will occur. + logger.log(Level.FINE, "EDT: Telling OGL to destroy display .."); + synchronized (taskLock) { + desiredTask = TASK_DESTROY_DISPLAY; + while (desiredTask != TASK_COMPLETE) { + try { + taskLock.wait(); + } catch (InterruptedException ex) { + super.removeNotify(); + return; + } + } + desiredTask = TASK_NOTHING; + } + + logger.log(Level.FINE, "EDT: Acknowledged receipt of canvas death"); + // GL context is dead at this point + + super.removeNotify(); } + } - @Override - public Canvas getCanvas(){ - return canvas; + public LwjglCanvas() { + super(); + canvas = new GLCanvas(); + } + + @Override + public Type getType() { + return Type.Canvas; + } + + @Override + public void create(boolean waitFor) { + if (renderThread == null) { + logger.log(Level.FINE, "MAIN: Creating OGL thread."); + + renderThread = new Thread(LwjglCanvas.this, THREAD_NAME); + renderThread.start(); } - - @Override - protected void runLoop(){ - if (desiredTask != TASK_NOTHING){ - synchronized (taskLock){ - switch (desiredTask){ - case TASK_CREATE_DISPLAY: - logger.log(Level.FINE, "OGL: Creating display .."); - restoreCanvas(); - listener.gainFocus(); - desiredTask = TASK_NOTHING; - break; - case TASK_DESTROY_DISPLAY: - logger.log(Level.FINE, "OGL: Destroying display .."); - listener.loseFocus(); - pauseCanvas(); - break; - } - desiredTask = TASK_COMPLETE; - taskLock.notifyAll(); - } - } - - if (renderable.get()){ - int newWidth = Math.max(canvas.getWidth(), 1); - int newHeight = Math.max(canvas.getHeight(), 1); - if (width != newWidth || height != newHeight){ - width = newWidth; - height = newHeight; - if (listener != null){ - listener.reshape(width, height); - } - } - }else{ - if (frameRate <= 0){ - // NOTE: MUST be done otherwise - // Windows OS will freeze - Display.sync(30); - } + // do not do anything. + // superclass's create() will be called at initInThread() + if (waitFor) { + waitFor(true); + } + } + + @Override + public void setTitle(String title) {} + + @Override + public void restart() { + frameRate = settings.getFrameRate(); + // TODO: Handle other cases, like change of pixel format, etc. + } + + @Override + public Canvas getCanvas() { + return canvas; + } + + @Override + protected void runLoop() { + if (desiredTask != TASK_NOTHING) { + synchronized (taskLock) { + switch (desiredTask) { + case TASK_CREATE_DISPLAY: + logger.log(Level.FINE, "OGL: Creating display .."); + restoreCanvas(); + listener.gainFocus(); + desiredTask = TASK_NOTHING; + break; + case TASK_DESTROY_DISPLAY: + logger.log(Level.FINE, "OGL: Destroying display .."); + listener.loseFocus(); + pauseCanvas(); + break; } - - super.runLoop(); + desiredTask = TASK_COMPLETE; + taskLock.notifyAll(); + } } - private void pauseCanvas(){ - if (Mouse.isCreated()){ - if (Mouse.isGrabbed()){ - Mouse.setGrabbed(false); - mouseWasGrabbed = true; - } - mouseWasCreated = true; - Mouse.destroy(); - } - if (Keyboard.isCreated()){ - keyboardWasCreated = true; - Keyboard.destroy(); + if (renderable.get()) { + int newWidth = Math.max(canvas.getWidth(), 1); + int newHeight = Math.max(canvas.getHeight(), 1); + if (width != newWidth || height != newHeight) { + width = newWidth; + height = newHeight; + if (listener != null) { + listener.reshape(width, height); } + } + } else { + if (frameRate <= 0) { + // NOTE: MUST be done otherwise + // Windows OS will freeze + Display.sync(30); + } + } + + super.runLoop(); + } + + private void pauseCanvas() { + if (Mouse.isCreated()) { + if (Mouse.isGrabbed()) { + Mouse.setGrabbed(false); + mouseWasGrabbed = true; + } + mouseWasCreated = true; + Mouse.destroy(); + } + if (Keyboard.isCreated()) { + keyboardWasCreated = true; + Keyboard.destroy(); + } - renderable.set(false); - destroyContext(); + renderable.set(false); + destroyContext(); + } + + /** + * Called to restore the canvas. + */ + private void restoreCanvas() { + logger.log(Level.FINE, "OGL: Waiting for canvas to become displayable.."); + while (!canvas.isDisplayable()) { + try { + Thread.sleep(10); + } catch (InterruptedException ex) { + logger.log(Level.SEVERE, "OGL: Interrupted! ", ex); + } } - /** - * Called to restore the canvas. - */ - private void restoreCanvas(){ - logger.log(Level.FINE, "OGL: Waiting for canvas to become displayable.."); - while (!canvas.isDisplayable()){ - try { - Thread.sleep(10); - } catch (InterruptedException ex) { - logger.log(Level.SEVERE, "OGL: Interrupted! ", ex); - } - } - - logger.log(Level.FINE, "OGL: Creating display context .."); + logger.log(Level.FINE, "OGL: Creating display context .."); - // Set renderable to true, since canvas is now displayable. - renderable.set(true); - createContext(settings); + // Set renderable to true, since canvas is now displayable. + renderable.set(true); + createContext(settings); - logger.log(Level.FINE, "OGL: Display is active!"); + logger.log(Level.FINE, "OGL: Display is active!"); - try { - if (mouseWasCreated){ - Mouse.create(); - if (mouseWasGrabbed){ - Mouse.setGrabbed(true); - mouseWasGrabbed = false; - } - } - if (keyboardWasCreated){ - Keyboard.create(); - keyboardWasCreated = false; - } - } catch (LWJGLException ex){ - logger.log(Level.SEVERE, "Encountered exception when restoring input", ex); + try { + if (mouseWasCreated) { + Mouse.create(); + if (mouseWasGrabbed) { + Mouse.setGrabbed(true); + mouseWasGrabbed = false; } + } + if (keyboardWasCreated) { + Keyboard.create(); + keyboardWasCreated = false; + } + } catch (LWJGLException ex) { + logger.log(Level.SEVERE, "Encountered exception when restoring input", ex); + } - SwingUtilities.invokeLater(new Runnable(){ - @Override - public void run(){ - canvas.requestFocus(); - } - }); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + canvas.requestFocus(); + } + }); + } + + /** + * It seems it is best to use one pixel format for all shared contexts. + * + * @see http://developer.apple.com/library/mac/#qa/qa1248/_index.html + * + * @param forPbuffer true→zero samples, false→correct number of samples + * @return a new instance + */ + protected PixelFormat acquirePixelFormat(boolean forPbuffer) { + if (forPbuffer) { + // Use 0 samples for pbuffer format, prevents + // crashes on bad drivers + if (pbufferFormat == null) { + pbufferFormat = new PixelFormat(settings.getBitsPerPixel(), settings.getAlphaBits(), + settings.getDepthBits(), settings.getStencilBits(), 0, // samples + 0, 0, 0, settings.useStereo3D()); + } + return pbufferFormat; + } else { + if (canvasFormat == null) { + int samples = getNumSamplesToUse(); + canvasFormat = new PixelFormat(settings.getBitsPerPixel(), settings.getAlphaBits(), + settings.getDepthBits(), settings.getStencilBits(), samples, 0, 0, 0, + settings.useStereo3D()); + } + return canvasFormat; } - - /** - * It seems it is best to use one pixel format for all shared contexts. - * @see http://developer.apple.com/library/mac/#qa/qa1248/_index.html - * - * @param forPbuffer true→zero samples, false→correct number of samples - * @return a new instance - */ - protected PixelFormat acquirePixelFormat(boolean forPbuffer){ - if (forPbuffer){ - // Use 0 samples for pbuffer format, prevents - // crashes on bad drivers - if (pbufferFormat == null){ - pbufferFormat = new PixelFormat(settings.getBitsPerPixel(), - settings.getAlphaBits(), - settings.getDepthBits(), - settings.getStencilBits(), - 0, // samples - 0, - 0, - 0, - settings.useStereo3D()); - } - return pbufferFormat; - }else{ - if (canvasFormat == null){ - int samples = getNumSamplesToUse(); - canvasFormat = new PixelFormat(settings.getBitsPerPixel(), - settings.getAlphaBits(), - settings.getDepthBits(), - settings.getStencilBits(), - samples, - 0, - 0, - 0, - settings.useStereo3D()); - } - return canvasFormat; - } + } + + /** + * Makes sure the pbuffer is available and ready for use + * + * @throws LWJGLException if the buffer can't be made current + */ + protected void makePbufferAvailable() throws LWJGLException { + if (pbuffer != null && pbuffer.isBufferLost()) { + logger.log(Level.WARNING, "PBuffer was lost!"); + pbuffer.destroy(); + pbuffer = null; } - /** - * Makes sure the pbuffer is available and ready for use - * - * @throws LWJGLException if the buffer can't be made current - */ - protected void makePbufferAvailable() throws LWJGLException{ - if (pbuffer != null && pbuffer.isBufferLost()){ - logger.log(Level.WARNING, "PBuffer was lost!"); - pbuffer.destroy(); - pbuffer = null; - } - - if (pbuffer == null) { - pbuffer = new Pbuffer(1, 1, acquirePixelFormat(true), null); - pbuffer.makeCurrent(); - logger.log(Level.FINE, "OGL: Pbuffer has been created"); - - // Any created objects are no longer valid - if (!runningFirstTime){ - renderer.resetGLObjects(); - } + if (pbuffer == null) { + pbuffer = new Pbuffer(1, 1, acquirePixelFormat(true), null); + pbuffer.makeCurrent(); + logger.log(Level.FINE, "OGL: Pbuffer has been created"); + + // Any created objects are no longer valid + if (!runningFirstTime) { + renderer.resetGLObjects(); + } + } + + pbuffer.makeCurrent(); + if (!pbuffer.isCurrent()) { + throw new LWJGLException("Pbuffer cannot be made current"); + } + } + + protected void destroyPbuffer() { + if (pbuffer != null) { + if (!pbuffer.isBufferLost()) { + pbuffer.destroy(); + } + pbuffer = null; + } + } + + /** + * This is called: 1) When the context thread ends 2) Any time the canvas becomes non-displayable + */ + @Override + protected void destroyContext() { + try { + // invalidate the state so renderer can resume operation + if (!USE_SHARED_CONTEXT) { + renderer.cleanup(); + } + + if (Display.isCreated()) { + /* + * FIXES: org.lwjgl.LWJGLException: X Error BadWindow (invalid Window parameter) + * request_code: 2 minor_code: 0 + * + * Destroying keyboard early prevents the error above, triggered by destroying keyboard in + * by Display.destroy() or Display.setParent(null). Therefore, Keyboard.destroy() should + * precede any of these calls. + */ + if (Keyboard.isCreated()) { + // Should only happen if called in + // LwjglAbstractDisplay.deinitInThread(). + Keyboard.destroy(); } - - pbuffer.makeCurrent(); - if (!pbuffer.isCurrent()){ - throw new LWJGLException("Pbuffer cannot be made current"); + + // try { + // NOTE: On Windows XP, not calling setParent(null) + // freezes the application. + // On Mac it freezes the application. + // On Linux it fixes a crash with X Window System. + if (JmeSystem.getPlatform() == Platform.Windows32 + || JmeSystem.getPlatform() == Platform.Windows64) { + // Display.setParent(null); } + // } catch (LWJGLException ex) { + // logger.log(Level.SEVERE, "Encountered exception when setting parent to null", ex); + // } + + Display.destroy(); + } + + // The canvas is no longer visible, + // but the context thread is still running. + if (!needClose.get()) { + // MUST make sure there's still a context current here. + // Display is dead, make PBuffer available to the system. + makePbufferAvailable(); + + renderer.invalidateState(); + } else { + // The context thread is no longer running. + // Destroy pbuffer. + destroyPbuffer(); + } + } catch (LWJGLException ex) { + listener.handleError("Failed make pbuffer available", ex); } - - protected void destroyPbuffer(){ - if (pbuffer != null){ - if (!pbuffer.isBufferLost()){ - pbuffer.destroy(); - } - pbuffer = null; + } + + /** + * This is called: 1) When the context thread starts 2) Any time the canvas becomes displayable + * again. In the first call of this method, OpenGL context is not ready yet. Therefore, OpenCL + * context cannot be created. The second call of this method is done after "simpleInitApp" is + * called. Therefore, OpenCL won't be available in "simpleInitApp" if Canvas/Swing is used. To use + * OpenCL with Canvas/Swing, you need to use OpenCL in the rendering loop "simpleUpdate" and check + * for "context.getOpenCLContext()!=null". + */ + @Override + protected void createContext(AppSettings settings) { + // In case canvas is not visible, we still take framerate + // from settings to prevent "100% CPU usage" + frameRate = settings.getFrameRate(); + allowSwapBuffers = settings.isSwapBuffers(); + + try { + if (renderable.get()) { + if (!runningFirstTime) { + // because the display is a different opengl context + // must reset the context state. + if (!USE_SHARED_CONTEXT) { + renderer.cleanup(); + } } - } - - /** - * This is called: - * 1) When the context thread ends - * 2) Any time the canvas becomes non-displayable - */ - @Override - protected void destroyContext(){ - try { - // invalidate the state so renderer can resume operation - if (!USE_SHARED_CONTEXT){ - renderer.cleanup(); - } - - if (Display.isCreated()){ - /* FIXES: - * org.lwjgl.LWJGLException: X Error - * BadWindow (invalid Window parameter) request_code: 2 minor_code: 0 - * - * Destroying keyboard early prevents the error above, triggered - * by destroying keyboard in by Display.destroy() or Display.setParent(null). - * Therefore, Keyboard.destroy() should precede any of these calls. - */ - if (Keyboard.isCreated()){ - // Should only happen if called in - // LwjglAbstractDisplay.deinitInThread(). - Keyboard.destroy(); - } - - //try { - // NOTE: On Windows XP, not calling setParent(null) - // freezes the application. - // On Mac it freezes the application. - // On Linux it fixes a crash with X Window System. - if (JmeSystem.getPlatform() == Platform.Windows32 - || JmeSystem.getPlatform() == Platform.Windows64){ - //Display.setParent(null); - } - //} catch (LWJGLException ex) { - // logger.log(Level.SEVERE, "Encountered exception when setting parent to null", ex); - //} - - Display.destroy(); - } - - // The canvas is no longer visible, - // but the context thread is still running. - if (!needClose.get()){ - // MUST make sure there's still a context current here. - // Display is dead, make PBuffer available to the system. - makePbufferAvailable(); - - renderer.invalidateState(); - }else{ - // The context thread is no longer running. - // Destroy pbuffer. - destroyPbuffer(); - } - } catch (LWJGLException ex) { - listener.handleError("Failed make pbuffer available", ex); + + // if the pbuffer is currently active, + // make sure to deactivate it + destroyPbuffer(); + + if (Keyboard.isCreated()) { + Keyboard.destroy(); } - } - /** - * This is called: - * 1) When the context thread starts - * 2) Any time the canvas becomes displayable again. - * In the first call of this method, OpenGL context is not ready yet. Therefore, OpenCL context cannot be created. - * The second call of this method is done after "simpleInitApp" is called. Therefore, OpenCL won't be available in "simpleInitApp" if Canvas/Swing is used. - * To use OpenCL with Canvas/Swing, you need to use OpenCL in the rendering loop "simpleUpdate" and check for "context.getOpenCLContext()!=null". - */ - @Override - protected void createContext(AppSettings settings) { - // In case canvas is not visible, we still take framerate - // from settings to prevent "100% CPU usage" - frameRate = settings.getFrameRate(); - allowSwapBuffers = settings.isSwapBuffers(); - try { - if (renderable.get()){ - if (!runningFirstTime){ - // because the display is a different opengl context - // must reset the context state. - if (!USE_SHARED_CONTEXT){ - renderer.cleanup(); - } - } - - // if the pbuffer is currently active, - // make sure to deactivate it - destroyPbuffer(); - - if (Keyboard.isCreated()){ - Keyboard.destroy(); - } - - try { - Thread.sleep(1000); - } catch (InterruptedException ex) { - } - - Display.setVSyncEnabled(settings.isVSync()); - Display.setParent(canvas); - - if (USE_SHARED_CONTEXT){ - Display.create(acquirePixelFormat(false), pbuffer); - }else{ - Display.create(acquirePixelFormat(false)); - } - if (settings.isOpenCLSupport()) { - initOpenCL(); - } - - renderer.invalidateState(); - }else{ - // First create the pbuffer, if it is needed. - makePbufferAvailable(); - } - - // At this point, the OpenGL context is active. - if (runningFirstTime){ - // THIS is the part that creates the renderer. - // It must always be called, now that we have the pbuffer workaround. - initContextFirstTime(); - runningFirstTime = false; - } - } catch (LWJGLException ex) { - listener.handleError("Failed to initialize OpenGL context", ex); - // TODO: Fix deadlock that happens after the error (throw runtime exception?) + Thread.sleep(1000); + } catch (InterruptedException ex) { + } + + Display.setVSyncEnabled(settings.isVSync()); + Display.setParent(canvas); + + if (USE_SHARED_CONTEXT) { + Display.create(acquirePixelFormat(false), pbuffer); + } else { + Display.create(acquirePixelFormat(false)); + } + if (settings.isOpenCLSupport()) { + initOpenCL(); } - } - @Override - public Monitors getMonitors() - { - // TODO Auto-generated method stub - return null; - } - - @Override - public int getPrimaryMonitor() - { - // TODO Auto-generated method stub - return 0; - } + renderer.invalidateState(); + } else { + // First create the pbuffer, if it is needed. + makePbufferAvailable(); + } + + // At this point, the OpenGL context is active. + if (runningFirstTime) { + // THIS is the part that creates the renderer. + // It must always be called, now that we have the pbuffer workaround. + initContextFirstTime(); + runningFirstTime = false; + } + } catch (LWJGLException ex) { + listener.handleError("Failed to initialize OpenGL context", ex); + // TODO: Fix deadlock that happens after the error (throw runtime exception?) + } + } + + @Override + public Monitors getMonitors() { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getPrimaryMonitor() { + // TODO Auto-generated method stub + return 0; + } } diff --git a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglDisplay.java b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglDisplay.java index bf7eef3aa0..020746256b 100644 --- a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglDisplay.java +++ b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglDisplay.java @@ -284,18 +284,16 @@ private ByteBuffer imageToByteBuffer(BufferedImage image) { return ByteBuffer.wrap(imageBuffer); } - @Override - public Monitors getMonitors() - { - // TODO Auto-generated method stub - return null; - } + @Override + public Monitors getMonitors() { + // TODO Auto-generated method stub + return null; + } - @Override - public int getPrimaryMonitor() - { - // TODO Auto-generated method stub - return 0; - } + @Override + public int getPrimaryMonitor() { + // TODO Auto-generated method stub + return 0; + } } diff --git a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglOffscreenBuffer.java b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglOffscreenBuffer.java index 1965d19ec0..86add690a4 100644 --- a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglOffscreenBuffer.java +++ b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglOffscreenBuffer.java @@ -220,18 +220,16 @@ public TouchInput getTouchInput() { public void setTitle(String title) { } - @Override - public Monitors getMonitors() - { - // TODO Auto-generated method stub - return null; - } - - @Override - public int getPrimaryMonitor() - { - // TODO Auto-generated method stub - return 0; - } + @Override + public Monitors getMonitors() { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getPrimaryMonitor() { + // TODO Auto-generated method stub + return 0; + } } diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java index e0002d6424..d9f23baeeb 100644 --- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java @@ -291,9 +291,9 @@ public void invoke(int error, long description) { // long monitor = NULL; - /** - * Let's grab the monitor selected, if not found it will return primaryMonitor. - * if not full screen just use primary monitor data. + /** + * Let's grab the monitor selected, if not found it will return + * primaryMonitor. if not full screen just use primary monitor data. */ if (settings.isFullscreen()) { monitor = getMonitor(settings.getMonitor()); @@ -305,18 +305,19 @@ public void invoke(int error, long description) { int requestWidth = settings.getWindowWidth(); int requestHeight = settings.getWindowHeight(); if (requestWidth <= 0 || requestHeight <= 0) { - requestWidth = videoMode.width(); - requestHeight = videoMode.height(); + requestWidth = videoMode.width(); + requestHeight = videoMode.height(); } - //Lets use the monitor selected from AppSettings if FullScreen is - //set. + // Lets use the monitor selected from AppSettings if FullScreen is + // set. if (settings.isFullscreen()) - window = glfwCreateWindow(requestWidth, requestHeight, settings.getTitle(), monitor, NULL); - else - window = glfwCreateWindow(requestWidth, requestHeight, settings.getTitle(), NULL, NULL); + window = glfwCreateWindow(requestWidth, requestHeight, + settings.getTitle(), monitor, NULL); + else + window = glfwCreateWindow(requestWidth, requestHeight, + settings.getTitle(), NULL, NULL); - if (window == NULL) { throw new RuntimeException("Failed to create the GLFW window"); } diff --git a/jme3-vr/src/main/java/com/jme3/system/lwjgl/LwjglDisplayVR.java b/jme3-vr/src/main/java/com/jme3/system/lwjgl/LwjglDisplayVR.java index 888c8b879d..f7f08126ba 100644 --- a/jme3-vr/src/main/java/com/jme3/system/lwjgl/LwjglDisplayVR.java +++ b/jme3-vr/src/main/java/com/jme3/system/lwjgl/LwjglDisplayVR.java @@ -53,17 +53,15 @@ public Context getOpenCLContext() { return null; } - @Override - public Monitors getMonitors() - { - // TODO Auto-generated method stub - return null; - } + @Override + public Monitors getMonitors() { + // TODO Auto-generated method stub + return null; + } - @Override - public int getPrimaryMonitor() - { - // TODO Auto-generated method stub - return 0; - } + @Override + public int getPrimaryMonitor() { + // TODO Auto-generated method stub + return 0; + } }