Quellcode durchsuchen

Allow application to be a resizable window.
Also allow buffer swapping to be disabled, e.g. for Oculus Rift.

shadowislord vor 10 Jahren
Ursprung
Commit
809092c236

+ 55 - 0
jme3-core/src/main/java/com/jme3/system/AppSettings.java

@@ -129,6 +129,8 @@ public final class AppSettings extends HashMap<String, Object> {
         defaults.put("MinHeight", 0);
         defaults.put("MinWidth", 0);
         defaults.put("GammaCorrection", false);
+        defaults.put("Resizable", false);
+        defaults.put("SwapBuffers", true);
       //  defaults.put("Icons", null);
     }
 
@@ -935,4 +937,57 @@ public final class AppSettings extends HashMap<String, Object> {
     public boolean getGammaCorrection() {
         return getBoolean("GammaCorrection");
     }
+    
+    /**
+     * Allows the display window to be resized by dragging its edges.
+     * 
+     * Only supported for {@link JmeContext.Type#Display} contexts which 
+     * are in windowed mode, ignored for other types. 
+     * The default value is <code>false</code>.
+     * 
+     * @param resizable True to make a resizable window, false to make a fixed
+     * size window.
+     */
+    public void setResizable(boolean resizable) {
+        putBoolean("Resizable", true);
+    }
+    
+    /**
+     * Determine if the display window can be resized by dragging its edges.
+     * 
+     * @return True if the window is resizable, false if it is fixed size.
+     * 
+     * @see #setResizable(boolean) 
+     */
+    public boolean isResizable() {
+        return getBoolean("Resizable");
+    }
+    
+    /**
+     * When enabled the display context will swap buffers every frame.
+     * 
+     * This may need to be disabled when integrating with an external
+     * library that handles buffer swapping on its own, e.g. Oculus Rift.
+     * When disabled, the engine will process window messages
+     * after each frame but it will not swap buffers - note that this
+     * will cause 100% CPU usage normally as there's no VSync or any framerate
+     * caps (unless set via {@link #setFrameRate(int) }.
+     * The default is <code>true</code>.
+     * 
+     * @param swapBuffers True to enable buffer swapping, false to disable it.
+     */
+    public void setSwapBuffers(boolean swapBuffers) {
+        putBoolean("SwapBuffers", swapBuffers);
+    }
+   
+    /**
+     * Determine if the the display context will swap buffers every frame.
+     * 
+     * @return True if buffer swapping is enabled, false otherwise.
+     * 
+     * @see #setSwapBuffers(boolean) 
+     */
+    public boolean isSwapBuffers() {
+        return getBoolean("SwapBuffers");
+    }
 }

+ 87 - 0
jme3-examples/src/main/java/jme3test/app/TestResizableApp.java

@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2009-2015 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *   may be used to endorse or promote products derived from this software
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package jme3test.app;
+
+import com.jme3.app.SimpleApplication;
+import com.jme3.font.BitmapText;
+import com.jme3.font.Rectangle;
+import com.jme3.material.Material;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.shape.Box;
+import com.jme3.system.AppSettings;
+import jme3test.model.shape.TestBox;
+
+/**
+ * Tests the capability to resize the application window.
+ * 
+ * @author Kirill Vainer
+ */
+public class TestResizableApp extends SimpleApplication {
+    
+    private BitmapText txt;
+    
+    public static void main(String[] args){
+        TestResizableApp app = new TestResizableApp();
+        AppSettings settings = new AppSettings(true);
+        settings.setResizable(true);
+        app.setSettings(settings);
+        app.setShowSettings(false);
+        app.start();
+    }
+
+    public void reshape(int width, int height) {
+        super.reshape(width, height);
+
+        // Need to move text relative to app height
+        txt.setLocalTranslation(0, settings.getHeight(), 0);
+        txt.setText("Drag the corners of the application to resize it.\n" +
+                    "Current Size: " + settings.getWidth() + "x" + settings.getHeight());
+    }
+    
+    public void simpleInitApp() {
+        flyCam.setDragToRotate(true);
+        
+        Box b = new Box(1, 1, 1);
+        Geometry geom = new Geometry("Box", b);
+        Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+        mat.setTexture("ColorMap", assetManager.loadTexture("Interface/Logo/Monkey.jpg"));
+        geom.setMaterial(mat);
+        rootNode.attachChild(geom);
+        
+        txt = new BitmapText(loadGuiFont(), false);
+        txt.setText("Drag the corners of the application to resize it.\n" +
+                    "Current Size: " + settings.getWidth() + "x" + settings.getHeight());
+        txt.setLocalTranslation(0, settings.getHeight(), 0);
+        guiNode.attachChild(txt);
+    }
+
+}

+ 19 - 18
jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglAbstractDisplay.java

@@ -59,6 +59,7 @@ public abstract class LwjglAbstractDisplay extends LwjglContext implements Runna
     protected boolean wasActive = false;
     protected int frameRate = 0;
     protected boolean autoFlush = true;
+    protected boolean allowSwapBuffers = false;
 
     /**
      * @return Type.Display or Type.Canvas
@@ -149,7 +150,7 @@ public abstract class LwjglAbstractDisplay extends LwjglContext implements Runna
             throw new IllegalStateException();
 
         listener.update();
-
+        
         // All this does is call swap buffers
         // If the canvas is not active, there's no need to waste time
         // doing that ..
@@ -158,30 +159,30 @@ public abstract class LwjglAbstractDisplay extends LwjglContext implements Runna
 
             // calls swap buffers, etc.
             try {
-                if (autoFlush){
+                if (allowSwapBuffers && autoFlush) {
                     Display.update(false);
-                }else{
-                    Display.processMessages();
-                    Thread.sleep(50);
-                    // add a small wait
-                    // to reduce CPU usage
-                }
+                } 
             } catch (Throwable ex){
                 listener.handleError("Error while swapping buffers", ex);
             }
         }
 
-        if (frameRate > 0)
-            Display.sync(frameRate);
-
-        if (renderable.get()){
-            if (autoFlush){
-                // check input after we synchronize with framerate.
-                // this reduces input lag.
-                Display.processMessages();
-            }
+        int frameRateCap;
+        if (autoFlush) {
+            frameRateCap = frameRate;
+        } else {
+            frameRateCap = 20;
         }
-
+        
+        if (frameRateCap > 0) {
+            // Cap framerate
+            Display.sync(frameRateCap);
+        }
+        
+        // check input after we synchronize with framerate.
+        // this reduces input lag.
+        Display.processMessages();
+        
         // Subclasses just call GLObjectManager clean up objects here
         // it is safe .. for now.
         renderer.postFrame();

+ 1 - 0
jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java

@@ -435,6 +435,7 @@ public class LwjglCanvas extends LwjglAbstractDisplay implements JmeCanvasContex
         // 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()){

+ 10 - 3
jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglDisplay.java

@@ -94,6 +94,7 @@ public class LwjglDisplay extends LwjglAbstractDisplay {
                                          settings.useStereo3D());
         
         frameRate = settings.getFrameRate();
+        allowSwapBuffers = settings.isSwapBuffers();
         logger.log(Level.FINE, "Selected display mode: {0}", displayMode);
 
         boolean pixelFormatChanged = false;
@@ -108,6 +109,7 @@ public class LwjglDisplay extends LwjglAbstractDisplay {
         pixelFormat = pf;
         
         Display.setTitle(settings.getTitle());
+        Display.setResizable(settings.isResizable());
         
         if (displayMode != null) {
             if (settings.isFullscreen()) {
@@ -172,14 +174,19 @@ public class LwjglDisplay extends LwjglAbstractDisplay {
     @Override
     public void runLoop(){
         // This method is overriden to do restart
-        if (needRestart.getAndSet(false)){
-            try{
+        if (needRestart.getAndSet(false)) {
+            try {
                 createContext(settings);
-            }catch (LWJGLException ex){
+            } catch (LWJGLException ex) {
                 logger.log(Level.SEVERE, "Failed to set display settings!", ex);
             }
             listener.reshape(settings.getWidth(), settings.getHeight());
             logger.fine("Display restarted.");
+        } else if (Display.wasResized()) {
+            int newWidth = Display.getWidth();
+            int newHeight = Display.getHeight();
+            settings.setResolution(newWidth, newHeight);
+            listener.reshape(newWidth, newHeight);
         }
 
         super.runLoop();