From d4ade2473f47578bd2df4b5b1bc9bcf4d28ef945 Mon Sep 17 00:00:00 2001 From: void Date: Sun, 15 Feb 2015 23:17:18 +0100 Subject: [PATCH] feature: Update Nifty GUI to version 1.4.1 This commit updates Nifty to version 1.4.1 and makes all the necessary changes to the JME-Nifty integration to be compatible with this version of Nifty (manily support of multiple texture atlases in the batch renderer and some minor changes like the removal of some *Null classes). Most User code should still be able to compile with this change. However, the NiftyJmeDisplay constructor that requires the width and height of the texture atlas has been deprecated in favour of the newly added static factory methods: NiftyJmeDisplay.newNiftyJmeDisplay(). The new methods add support for the Nifty BatchRenderConfiguration class that allow further configuration of some rendering details. The testcase jme3test.niftygui.TestNiftyGui has been modified to use the new methods and seems to render fine for me. Most of Nifty 1.4.1 should be compatible with old versions of Nifty. However some compile-time incompatibilities might exists to old 1.3.x code. Additionally some internal mechanism have been modified with 1.4 so there might be additional runtime incompatibilities as well. --- .../java/jme3test/niftygui/TestNiftyGui.java | 13 +- jme3-niftygui/build.gradle | 6 +- .../com/jme3/cinematic/events/GuiEvent.java | 4 +- .../com/jme3/cinematic/events/GuiTrack.java | 4 +- .../com/jme3/niftygui/InputSystemJme.java | 3 +- .../jme3/niftygui/JmeBatchRenderBackend.java | 137 ++++++++++++++---- .../com/jme3/niftygui/NiftyJmeDisplay.java | 107 +++++++++++++- .../com/jme3/niftygui/RenderDeviceJme.java | 11 +- 8 files changed, 238 insertions(+), 47 deletions(-) diff --git a/jme3-examples/src/main/java/jme3test/niftygui/TestNiftyGui.java b/jme3-examples/src/main/java/jme3test/niftygui/TestNiftyGui.java index 8d3532844..fe9171c92 100644 --- a/jme3-examples/src/main/java/jme3test/niftygui/TestNiftyGui.java +++ b/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"); } diff --git a/jme3-niftygui/build.gradle b/jme3-niftygui/build.gradle index 8572b3127..abe25f6e4 100644 --- a/jme3-niftygui/build.gradle +++ b/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' } diff --git a/jme3-niftygui/src/main/java/com/jme3/cinematic/events/GuiEvent.java b/jme3-niftygui/src/main/java/com/jme3/cinematic/events/GuiEvent.java index de685d445..2f5d788b4 100644 --- a/jme3-niftygui/src/main/java/com/jme3/cinematic/events/GuiEvent.java +++ b/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); } } diff --git a/jme3-niftygui/src/main/java/com/jme3/cinematic/events/GuiTrack.java b/jme3-niftygui/src/main/java/com/jme3/cinematic/events/GuiTrack.java index 04230e287..a7bd123bc 100644 --- a/jme3-niftygui/src/main/java/com/jme3/cinematic/events/GuiTrack.java +++ b/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); } } diff --git a/jme3-niftygui/src/main/java/com/jme3/niftygui/InputSystemJme.java b/jme3-niftygui/src/main/java/com/jme3/niftygui/InputSystemJme.java index 6c0e52566..d76fc0b20 100644 --- a/jme3-niftygui/src/main/java/com/jme3/niftygui/InputSystemJme.java +++ b/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) { diff --git a/jme3-niftygui/src/main/java/com/jme3/niftygui/JmeBatchRenderBackend.java b/jme3-niftygui/src/main/java/com/jme3/niftygui/JmeBatchRenderBackend.java index 60b515a46..97f46120a 100644 --- a/jme3-niftygui/src/main/java/com/jme3/niftygui/JmeBatchRenderBackend.java +++ b/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 textures = new HashMap(); + 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(2, new Factory() { + this.batchPool = new ObjectPool(new Factory() { @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