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.
experimental
void 10 years ago
parent d9cc9003ba
commit d4ade2473f
  1. 13
      jme3-examples/src/main/java/jme3test/niftygui/TestNiftyGui.java
  2. 6
      jme3-niftygui/build.gradle
  3. 4
      jme3-niftygui/src/main/java/com/jme3/cinematic/events/GuiEvent.java
  4. 4
      jme3-niftygui/src/main/java/com/jme3/cinematic/events/GuiTrack.java
  5. 3
      jme3-niftygui/src/main/java/com/jme3/niftygui/InputSystemJme.java
  6. 137
      jme3-niftygui/src/main/java/com/jme3/niftygui/JmeBatchRenderBackend.java
  7. 107
      jme3-niftygui/src/main/java/com/jme3/niftygui/NiftyJmeDisplay.java
  8. 11
      jme3-niftygui/src/main/java/com/jme3/niftygui/RenderDeviceJme.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");
}

@ -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'
}

@ -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);
}
}

@ -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);
}
}

@ -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) {

@ -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 boolean existsNonAtlasTexture(final int textureId) {
return textures.containsKey(textureId);
}
@Override
public void beginBatch(final BlendMode blendMode) {
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);

@ -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());

@ -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;
}

Loading…
Cancel
Save