浏览代码

Merge pull request #213 from void256/master

feature: Update Nifty GUI to version 1.4.1
normen 10 年之前
父节点
当前提交
0e6bc92d19

+ 9 - 4
jme3-examples/src/main/java/jme3test/niftygui/TestNiftyGui.java

@@ -52,6 +52,7 @@ public class TestNiftyGui extends SimpleApplication implements ScreenController
         app.start();
     }
 
+    @Override
     public void simpleInitApp() {
         Box b = new Box(Vector3f.ZERO, 1, 1, 1);
         Geometry geom = new Geometry("Box", b);
@@ -60,10 +61,11 @@ public class TestNiftyGui extends SimpleApplication implements ScreenController
         geom.setMaterial(mat);
         rootNode.attachChild(geom);
 
-        NiftyJmeDisplay niftyDisplay = new NiftyJmeDisplay(assetManager,
-                                                          inputManager,
-                                                          audioRenderer,
-                                                          guiViewPort);
+        NiftyJmeDisplay niftyDisplay = NiftyJmeDisplay.newNiftyJmeDisplay(
+                assetManager,
+                inputManager,
+                audioRenderer,
+                guiViewPort);
         nifty = niftyDisplay.getNifty();
         nifty.fromXml("Interface/Nifty/HelloJme.xml", "start", this);
 
@@ -76,14 +78,17 @@ public class TestNiftyGui extends SimpleApplication implements ScreenController
         inputManager.setCursorVisible(true);
     }
 
+    @Override
     public void bind(Nifty nifty, Screen screen) {
         System.out.println("bind( " + screen.getScreenId() + ")");
     }
 
+    @Override
     public void onStartScreen() {
         System.out.println("onStartScreen");
     }
 
+    @Override
     public void onEndScreen() {
         System.out.println("onEndScreen");
     }

+ 3 - 3
jme3-niftygui/build.gradle

@@ -10,7 +10,7 @@ repositories {
 
 dependencies {
     compile project(':jme3-core')
-    compile 'lessvoid:nifty:1.3.3'
-    compile 'lessvoid:nifty-default-controls:1.3.3'
-    compile 'lessvoid:nifty-style-black:1.3.3'
+    compile 'lessvoid:nifty:1.4.1'
+    compile 'lessvoid:nifty-default-controls:1.4.1'
+    compile 'lessvoid:nifty-style-black:1.4.1'
 }

+ 2 - 2
jme3-niftygui/src/main/java/com/jme3/cinematic/events/GuiEvent.java

@@ -37,7 +37,6 @@ import com.jme3.export.JmeExporter;
 import com.jme3.export.JmeImporter;
 import com.jme3.export.OutputCapsule;
 import de.lessvoid.nifty.Nifty;
-import de.lessvoid.nifty.screen.NullScreen;
 import java.io.IOException;
 
 /**
@@ -82,7 +81,8 @@ public class GuiEvent extends AbstractCinematicEvent {
     }
 
     @Override
-    public void onStop() {        if (!(nifty.getCurrentScreen() instanceof NullScreen)) {
+    public void onStop() {
+        if (nifty.getCurrentScreen() != null) {
             nifty.getCurrentScreen().endScreen(null);
         }
     }

+ 2 - 2
jme3-niftygui/src/main/java/com/jme3/cinematic/events/GuiTrack.java

@@ -37,7 +37,6 @@ import com.jme3.export.JmeExporter;
 import com.jme3.export.JmeImporter;
 import com.jme3.export.OutputCapsule;
 import de.lessvoid.nifty.Nifty;
-import de.lessvoid.nifty.screen.NullScreen;
 import java.io.IOException;
 
 /**
@@ -84,7 +83,8 @@ public class GuiTrack extends AbstractCinematicEvent {
     }
 
     @Override
-    public void onStop() {        if (!(nifty.getCurrentScreen() instanceof NullScreen)) {
+    public void onStop() {
+        if (nifty.getCurrentScreen() != null) {
             nifty.getCurrentScreen().endScreen(null);
         }
     }

+ 1 - 2
jme3-niftygui/src/main/java/com/jme3/niftygui/InputSystemJme.java

@@ -41,7 +41,6 @@ import com.jme3.system.JmeSystem;
 import de.lessvoid.nifty.Nifty;
 import de.lessvoid.nifty.NiftyInputConsumer;
 import de.lessvoid.nifty.controls.TextField;
-import de.lessvoid.nifty.controls.nullobjects.TextFieldNull;
 import de.lessvoid.nifty.elements.Element;
 import de.lessvoid.nifty.input.keyboard.KeyboardInputEvent;
 import de.lessvoid.nifty.spi.input.InputSystem;
@@ -310,7 +309,7 @@ public class InputSystemJme implements InputSystem, RawInputListener {
             Element element = nifty.getCurrentScreen().getFocusHandler().getKeyboardFocusElement();
             if (element != null) {
                 final TextField textField = element.getNiftyControl(TextField.class);
-                if (textField != null && !(textField instanceof TextFieldNull)) {
+                if (textField != null) {
                     Logger.getLogger(InputSystemJme.class.getName()).log(Level.FINE, "Current TextField: {0}", textField.getId());
                     String initialValue = textField.getText();
                     if (initialValue == null) {

+ 108 - 29
jme3-niftygui/src/main/java/com/jme3/niftygui/JmeBatchRenderBackend.java

@@ -57,13 +57,15 @@ import com.jme3.texture.Texture.MinFilter;
 import com.jme3.texture.Texture2D;
 import com.jme3.util.BufferUtils;
 
-import de.lessvoid.nifty.batch.spi.BatchRenderBackend;
+import de.lessvoid.nifty.render.batch.spi.BatchRenderBackend;
 import de.lessvoid.nifty.render.BlendMode;
 import de.lessvoid.nifty.spi.render.MouseCursor;
 import de.lessvoid.nifty.tools.Color;
+import de.lessvoid.nifty.tools.Factory;
 import de.lessvoid.nifty.tools.ObjectPool;
-import de.lessvoid.nifty.tools.ObjectPool.Factory;
 import de.lessvoid.nifty.tools.resourceloader.NiftyResourceLoader;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * Nifty GUI BatchRenderBackend Implementation for jMonkeyEngine.
@@ -82,18 +84,21 @@ public class JmeBatchRenderBackend implements BatchRenderBackend {
 
   private RenderManager renderManager;
   private NiftyJmeDisplay display;
-  private Texture2D textureAtlas;
+  private Map<Integer, Texture2D> textures = new HashMap<Integer, Texture2D>();
+  private int textureAtlasId = 1;
   private Batch currentBatch;
   private Matrix4f tempMat = new Matrix4f();
   private ByteBuffer initialData;
 
   // this is only used for debugging purpose and will make the removed textures filled with a color
-  private boolean fillRemovedTexture =
-      Boolean.getBoolean(System.getProperty(JmeBatchRenderBackend.class.getName() + ".fillRemovedTexture", "false"));
+  // please note: the old way to init this via a system property has been
+  // removed since it's now possible to configure it using the
+  // BatchRenderConfiguration class when you create the NiftyJmeDisplay instance
+  private boolean fillRemovedTexture = false;
 
   public JmeBatchRenderBackend(final NiftyJmeDisplay display) {
     this.display = display;
-    this.batchPool = new ObjectPool<Batch>(2, new Factory<Batch>() {
+    this.batchPool = new ObjectPool<Batch>(new Factory<Batch>() {
       @Override
       public Batch createNew() {
         return new Batch();
@@ -152,9 +157,18 @@ public class JmeBatchRenderBackend implements BatchRenderBackend {
   @Override
   public MouseCursor createMouseCursor(final String filename, final int hotspotX, final int hotspotY) throws IOException {
     return new MouseCursor() {
-      public void dispose() {
-      }
-  };
+        @Override
+        public void dispose() {
+        }
+
+        @Override
+        public void enable() {
+        }
+
+        @Override
+        public void disable() {
+        }
+    };
   }
 
   @Override
@@ -166,9 +180,9 @@ public class JmeBatchRenderBackend implements BatchRenderBackend {
   }
 
   @Override
-  public void createAtlasTexture(final int width, final int height) {
+  public int createTextureAtlas(final int width, final int height) {
     try {
-      createAtlasTextureInternal(width, height);
+      int atlasId = addTexture(createAtlasTextureInternal(width, height));
 
       // we just initialize a second buffer here that will replace the texture atlas image
       initialData = BufferUtils.createByteBuffer(width*height*4);
@@ -178,15 +192,18 @@ public class JmeBatchRenderBackend implements BatchRenderBackend {
         initialData.put((byte) 0x00);
         initialData.put((byte) 0xff);
       }
+      return atlasId;
     } catch (Exception e) {
       log.log(Level.WARNING, e.getMessage(), e);
+      return 0; // TODO Nifty always expects this call to be successfull
+                // there currently is no way to return failure or something :/
     }
   }
 
   @Override
-  public void clearAtlasTexture(final int width, final int height) {
-    initialData.rewind();
-    textureAtlas.getImage().setData(initialData);
+  public void clearTextureAtlas(final int atlasId) {
+      initialData.rewind();
+      getTextureAtlas(atlasId).getImage().setData(initialData);
   }
 
   @Override
@@ -200,16 +217,41 @@ public class JmeBatchRenderBackend implements BatchRenderBackend {
   }
 
   @Override
-  public void addImageToTexture(final Image image, final int x, final int y) {
+  public Image loadImage(final ByteBuffer imageData, final int imageWidth, final int imageHeight) {
+    return new ImageImpl(new com.jme3.texture.Image(Format.RGBA8, imageWidth, imageHeight, imageData));
+  }
+  
+  @Override
+  public void addImageToAtlas(final Image image, final int x, final int y, final int atlasTextureId) {
+    ImageImpl imageImpl = (ImageImpl) image;
+    imageImpl.modifyTexture(this, getTextureAtlas(atlasTextureId), x, y);
+  }
+
+  @Override
+  public int createNonAtlasTexture(final Image image) {
     ImageImpl imageImpl = (ImageImpl) image;
-    imageImpl.modifyTexture(this, textureAtlas, x, y);
+
+    Texture2D texture = new Texture2D(imageImpl.image);
+    texture.setMinFilter(MinFilter.NearestNoMipMaps);
+    texture.setMagFilter(MagFilter.Nearest);
+    return addTexture(texture);
+  }
+
+  @Override
+  public void deleteNonAtlasTexture(final int textureId) {
+    textures.remove(textureId);
   }
 
   @Override
-  public void beginBatch(final BlendMode blendMode) {
+  public boolean existsNonAtlasTexture(final int textureId) {
+    return textures.containsKey(textureId);
+  }
+
+  @Override
+  public void beginBatch(final BlendMode blendMode, final int textureId) {
     batches.add(batchPool.allocate());
     currentBatch = batches.get(batches.size() - 1);
-    currentBatch.begin(blendMode);
+    currentBatch.begin(blendMode, getTextureAtlas(textureId));
   }
 
   @Override
@@ -225,9 +267,10 @@ public class JmeBatchRenderBackend implements BatchRenderBackend {
       final float textureX,
       final float textureY,
       final float textureWidth,
-      final float textureHeight) {
+      final float textureHeight,
+      final int textureId) {
     if (!currentBatch.canAddQuad()) {
-      beginBatch(currentBatch.getBlendMode());
+      beginBatch(currentBatch.getBlendMode(), textureId);
     }
     currentBatch.addQuadInternal(x, y, width, height, color1, color2, color3, color4, textureX, textureY, textureWidth, textureHeight);
   }
@@ -242,7 +285,7 @@ public class JmeBatchRenderBackend implements BatchRenderBackend {
   }
 
   @Override
-  public void removeFromTexture(final Image image, final int x, final int y, final int w, final int h) {
+  public void removeImageFromAtlas(final Image image, final int x, final int y, final int w, final int h, final int atlasTextureId) {
     // Since we clear the whole texture when we switch screens it's not really necessary to remove data from the
     // texture atlas when individual textures are removed. If necessary this can be enabled with a system property.
     if (!fillRemovedTexture) {
@@ -258,24 +301,47 @@ public class JmeBatchRenderBackend implements BatchRenderBackend {
     }
     initialData.rewind();
     modifyTexture(
-        textureAtlas,
+        getTextureAtlas(atlasTextureId),
         new com.jme3.texture.Image(Format.RGBA8, image.getWidth(), image.getHeight(), initialData),
         x,
         y);
   }
 
+  /**
+   * Whether or not to render textures with high quality settings. Usually, setting to true will result in slower
+   * performance, but nicer looking textures, and vice versa. How high quality textures are rendered versus low quality
+   * textures will vary depending on the {@link de.lessvoid.nifty.render.batch.spi.BatchRenderBackend} implementation.
+   */
+  @Override
+  public void useHighQualityTextures(final boolean shouldUseHighQualityTextures) {
+      // TODO when true this should use something like linear filtering
+      // not sure right now how to tell jme about that ... might not be
+      // necessary to be set?
+  }
+
+  /**
+   * Whether or not to overwrite previously used atlas space with blank data. Setting to true will result in slower
+   * performance, but may be useful in debugging when visually inspecting the atlas, since there will not be portions
+   * of old images visible in currently unused atlas space.
+   */
+  @Override
+  public void fillRemovedImagesInAtlas(final boolean shouldFill) {
+    fillRemovedTexture = shouldFill;
+  }
+
   // internal implementations
 
-  private void createAtlasTextureInternal(final int width, final int height) throws Exception {
+  private Texture2D createAtlasTextureInternal(final int width, final int height) throws Exception {
     ByteBuffer initialData = BufferUtils.createByteBuffer(width*height*4);
     for (int i=0; i<width*height*4; i++) {
-      initialData.put((byte) 0x80);
+      initialData.put((byte) 0x00);
     }
     initialData.rewind();
 
-    textureAtlas = new Texture2D(new com.jme3.texture.Image(Format.RGBA8, width, height, initialData));
-    textureAtlas.setMinFilter(MinFilter.NearestNoMipMaps);
-    textureAtlas.setMagFilter(MagFilter.Nearest);
+    Texture2D texture = new Texture2D(new com.jme3.texture.Image(Format.RGBA8, width, height, initialData));
+    texture.setMinFilter(MinFilter.NearestNoMipMaps);
+    texture.setMagFilter(MagFilter.Nearest);
+    return texture;
   }
 
   private void modifyTexture(
@@ -294,6 +360,16 @@ public class JmeBatchRenderBackend implements BatchRenderBackend {
     renderer.modifyTexture(textureAtlas, image, x, y);
   }
 
+  private Texture2D getTextureAtlas(final int atlasId) {
+    return textures.get(atlasId);
+  }
+
+  private int addTexture(final Texture2D texture) {
+    final int atlasId = textureAtlasId++;
+    textures.put(atlasId, texture);
+    return atlasId;
+  }
+
   /**
    * Simple BatchRenderBackend.Image implementation that will transport the dimensions of an image as well as the
    * actual bytes from the loadImage() to the addImageToTexture() method.
@@ -389,6 +465,7 @@ public class JmeBatchRenderBackend implements BatchRenderBackend {
 
     // current blend mode
     private BlendMode blendMode = BlendMode.BLEND;
+    private Texture2D texture;
     private Material material;
 
     public Batch() {
@@ -416,8 +493,10 @@ public class JmeBatchRenderBackend implements BatchRenderBackend {
       renderState.setDepthWrite(false);
     }
 
-    public void begin(final BlendMode blendMode) {
+    public void begin(final BlendMode blendMode, final Texture2D texture) {
       this.blendMode = blendMode;
+      this.texture = texture;
+
       quadCount = 0;
       globalVertexIndex = 0;
       vertexPosBuffer.clear();
@@ -449,7 +528,7 @@ public class JmeBatchRenderBackend implements BatchRenderBackend {
       renderManager.setWorldMatrix(tempMat);
       renderManager.setForcedRenderState(renderState);
 
-      material.setTexture("ColorMap", textureAtlas);
+      material.setTexture("ColorMap", texture);
       mesh.updateCounts();
       material.render(meshGeometry, renderManager);
       renderManager.setForcedRenderState(null);

+ 104 - 3
jme3-niftygui/src/main/java/com/jme3/niftygui/NiftyJmeDisplay.java

@@ -49,7 +49,8 @@ import com.jme3.renderer.queue.RenderQueue;
 import com.jme3.texture.FrameBuffer;
 
 import de.lessvoid.nifty.Nifty;
-import de.lessvoid.nifty.batch.BatchRenderDevice;
+import de.lessvoid.nifty.render.batch.BatchRenderConfiguration;
+import de.lessvoid.nifty.render.batch.BatchRenderDevice;
 import de.lessvoid.nifty.tools.TimeProvider;
 import de.lessvoid.nifty.tools.resourceloader.ResourceLocation;
 
@@ -92,6 +93,68 @@ public class NiftyJmeDisplay implements SceneProcessor {
     public NiftyJmeDisplay() {
     }
 
+    /**
+     * Create a new NiftyJmeDisplay for use with the Batched Nifty Renderer.
+     *
+     * Nifty will use texture atlases for rendering. Every graphical asset
+     * you're rendering through Nifty will be placed into a texture atlas. The
+     * goal is to render all Nifty components in a single (or at least very few)
+     * draw calls. This should speed up rendering quite a bit.
+     *
+     * This call will use a default BatchRenderConfiguration for Nifty.
+     * See the other method {@link #newNiftyJmeDisplay(com.jme3.asset.AssetManager, com.jme3.input.InputManager, com.jme3.audio.AudioRenderer, com.jme3.renderer.ViewPort, de.lessvoid.nifty.render.batch.BatchRenderConfiguration) }
+     * when you want to change the default BatchRenderConfiguration and provide
+     * your own.
+     *
+     * @param assetManager jME AssetManager
+     * @param inputManager jME InputManager
+     * @param audioRenderer jME AudioRenderer
+     * @param viewport Viewport to use
+     */
+    public static NiftyJmeDisplay newNiftyJmeDisplay(
+        final AssetManager assetManager,
+        final InputManager inputManager,
+        final AudioRenderer audioRenderer,
+        final ViewPort viewport) {
+        return newNiftyJmeDisplay(
+                assetManager,
+                inputManager,
+                audioRenderer,
+                viewport,
+                new BatchRenderConfiguration());
+    }
+
+    /**
+     * Create a new NiftyJmeDisplay for use with the Batched Nifty Renderer.
+     *
+     * Nifty will use texture atlas for rendering. Every graphical asset you're
+     * rendering through Nifty will be placed into a texture atlas. The goal is
+     * to render all Nifty components in a single (or at least very few) draw
+     * calls. This should speed up rendering quite a bit.
+     *
+     * @param assetManager jME AssetManager
+     * @param inputManager jME InputManager
+     * @param audioRenderer jME AudioRenderer
+     * @param viewport Viewport to use
+     * @param batchRenderConfiguration the Nifty BatchRenderConfiguration that
+     *        you can use to further configure batch rendering. If unsure you
+     *        can simply use new BatchRenderConfiguration() in here for the
+     *        default configuration which should give you good default values.
+     */
+    public static NiftyJmeDisplay newNiftyJmeDisplay(
+        final AssetManager assetManager,
+        final InputManager inputManager,
+        final AudioRenderer audioRenderer,
+        final ViewPort viewport,
+        final BatchRenderConfiguration batchRenderConfiguration) {
+        return new NiftyJmeDisplay(
+                assetManager,
+                inputManager,
+                audioRenderer,
+                viewport,
+                batchRenderConfiguration);
+    }
+
     /**
      * Create a new NiftyJmeDisplay for use with the Batched Nifty Renderer (improved Nifty rendering performance).
      *
@@ -113,6 +176,10 @@ public class NiftyJmeDisplay implements SceneProcessor {
      * @param viewport Viewport to use
      * @param atlasWidth the width of the texture atlas Nifty uses to speed up rendering (2048 is a good value)
      * @param atlasHeight the height of the texture atlas Nifty uses to speed up rendering (2048 is a good value)
+     *
+     * @deprecated use the static factory methods {@link #newNiftyJmeDisplay(com.jme3.asset.AssetManager, com.jme3.input.InputManager, com.jme3.audio.AudioRenderer, com.jme3.renderer.ViewPort) }
+     * or {@link #newNiftyJmeDisplay(com.jme3.asset.AssetManager, com.jme3.input.InputManager, com.jme3.audio.AudioRenderer, com.jme3.renderer.ViewPort, de.lessvoid.nifty.render.batch.BatchRenderConfiguration) }
+     * instead of this constructor.
      */
     public NiftyJmeDisplay(
         final AssetManager assetManager,
@@ -120,14 +187,48 @@ public class NiftyJmeDisplay implements SceneProcessor {
         final AudioRenderer audioRenderer,
         final ViewPort viewport,
         final int atlasWidth,
-        final int atlasHeight){
+        final int atlasHeight) {
+      // The code duplication in here really sucks - it's a copy of the
+      // private constructor below that takes a BatchRenderConfiguration as an
+      // additional parameter. This method should really be removed soon and
+      // users should simply call the new factory methods.
+      //
+      // For now I keep this constructor as-is but have marked it as deprecated
+      // to allow migration to the new way to instantiate this class.
+      initialize(assetManager, inputManager, audioRenderer, viewport);
+
+      this.renderDev = null;
+      this.batchRendererBackend = new JmeBatchRenderBackend(this);
+
+      BatchRenderConfiguration batchRenderConfiguration = new BatchRenderConfiguration();
+      batchRenderConfiguration.atlasWidth = atlasWidth;
+      batchRenderConfiguration.atlasHeight = atlasHeight;
+
+      nifty = new Nifty(
+          new BatchRenderDevice(batchRendererBackend, batchRenderConfiguration),
+          soundDev,
+          inputSys,
+          new TimeProvider());
+      inputSys.setNifty(nifty);
+
+      resourceLocation = new ResourceLocationJme();
+      nifty.getResourceLoader().removeAllResourceLocations();
+      nifty.getResourceLoader().addResourceLocation(resourceLocation);
+    }
+
+    private NiftyJmeDisplay(
+        final AssetManager assetManager,
+        final InputManager inputManager,
+        final AudioRenderer audioRenderer,
+        final ViewPort viewport,
+        final BatchRenderConfiguration batchRenderConfiguration) {
       initialize(assetManager, inputManager, audioRenderer, viewport);
 
       this.renderDev = null;
       this.batchRendererBackend = new JmeBatchRenderBackend(this);
 
       nifty = new Nifty(
-          new BatchRenderDevice(batchRendererBackend, atlasWidth, atlasHeight),
+          new BatchRenderDevice(batchRendererBackend, batchRenderConfiguration),
           soundDev,
           inputSys,
           new TimeProvider());

+ 9 - 2
jme3-niftygui/src/main/java/com/jme3/niftygui/RenderDeviceJme.java

@@ -47,7 +47,6 @@ import com.jme3.scene.VertexBuffer.Usage;
 import com.jme3.scene.shape.Quad;
 import com.jme3.texture.Texture2D;
 import com.jme3.util.BufferUtils;
-import de.lessvoid.nifty.elements.render.TextRenderer.RenderFontNull;
 import de.lessvoid.nifty.render.BlendMode;
 import de.lessvoid.nifty.spi.render.MouseCursor;
 import de.lessvoid.nifty.spi.render.RenderDevice;
@@ -152,6 +151,14 @@ public class RenderDeviceJme implements RenderDevice {
         return new MouseCursor() {
             public void dispose() {
             }
+
+            @Override
+            public void enable() {
+            }
+
+            @Override
+            public void disable() {
+            }
         };
     }
     
@@ -223,7 +230,7 @@ public class RenderDeviceJme implements RenderDevice {
 
     @Override
     public void renderFont(RenderFont font, String str, int x, int y, Color color, float sizeX, float sizeY) {        
-        if (str.length() == 0 || font instanceof RenderFontNull) {
+        if (str.length() == 0) {
             return;
         }