Nifty Gui + 2D Rendering

I’m currently trying to create a 2d game using jme, and all is going well, except my nifty gui is rendered behind my spatials. I’m using the guiNode for attaching spatials in 2d, and the guiViewPort for the gui, but the gui is rendered behind my spatials.

Code:

package com.paloverde.scieval;

import com.jme3.app.SimpleApplication;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.niftygui.NiftyJmeDisplay;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Box;
import com.jme3.system.AppSettings;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture2D;
import com.jme3.ui.Picture;
import de.lessvoid.nifty.Nifty;
import de.lessvoid.nifty.screen.Screen;
import de.lessvoid.nifty.screen.ScreenController;

/**
 * test
 * @author normenhansen
 */
public class Main extends SimpleApplication implements ScreenController {

    private static final int MENU = 0, GAME = 1, PAUSE = 2;
    private static int STATE = MENU;
    Spatial backdrop, hud;
    Nifty nifty;
    
    public static void main(String[] args) {
        Main app = new Main();
        app.showSettings = false;
        
        AppSettings settings = new AppSettings(true);
        settings.setBitsPerPixel(24);
        settings.setSamples(0);
        settings.setHeight(720);
        settings.setWidth(1280);
        settings.setFullscreen(true);
        app.settings = settings;
        app.showSettings = false;
        app.start();
    }

    @Override
    public void simpleInitApp() {
        
        cam.setParallelProjection(true);
        cam.setLocation(new Vector3f(0,0,0.5f));
        getFlyByCamera().setEnabled(false);

        backdrop = getSpatial("Backdrops/bg");
        backdrop.move(0, 720 - (444), 0);
        guiNode.attachChild(backdrop);
        
        hud = getSpatial("Hud");
        
        guiNode.attachChild(hud);
        /*setDisplayStatView(false);
        setDisplayFps(false);
        */
        
         NiftyJmeDisplay niftyDisplay = new NiftyJmeDisplay(assetManager,
                                                          inputManager,
                                                          audioRenderer,
                                                          guiViewPort);
              
       
        nifty = niftyDisplay.getNifty();
        nifty.fromXml("Interface/MenuBeta.xml", "start", this);
        
        guiViewPort.addProcessor(niftyDisplay);
    }

    @Override
    public void simpleUpdate(float tpf) {
        
    }

    private void changeState(int state){
     STATE = state;
     
     guiNode.detachAllChildren();
     
     if(STATE == MENU){
         guiNode.attachChild(backdrop);
          guiNode.attachChild(hud);
     }
    }
    
    @Override
    public void simpleRender(RenderManager rm) {
        //TODO: add render code
    }
    
        private Spatial getSpatial(String name) {
        Node node = new Node(name);
        Picture pic = new Picture(name);
        Texture2D tex = (Texture2D) assetManager.loadTexture("Textures/"+name+".png");
        tex.setMagFilter(Texture.MagFilter.Nearest);
        tex.setMinFilter(Texture.MinFilter.NearestNoMipMaps);
        pic.setTexture(assetManager,tex,true);
 
        float width = tex.getImage().getWidth();
        float height = tex.getImage().getHeight();
        pic.setWidth(width * 4);
        pic.setHeight(height * 4);
        pic.move(0,0,0);
 
        Material picMat = new Material(assetManager, "Common/MatDefs/Gui/Gui.j3md");
        picMat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
        node.setMaterial(picMat);
 
        node.setUserData("radius", width/2);
 
        node.attachChild(pic);
        return node;
    }
        
    public void bind(Nifty nifty, Screen screen) {
        System.out.println("bind( " + screen.getScreenId() + ")");
    }

    public void onStartScreen() {
        System.out.println("onStartScreen");
    }

    public void onEndScreen() {
        System.out.println("onEndScreen");
    }

    public void quit(){
        nifty.gotoScreen("end");
    }

}

And here is my xml:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<nifty xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://nifty-gui.lessvoid.com/nifty-gui" xsi:schemaLocation="https://raw.githubusercontent.com/void256/nifty-gui/1.4/nifty-core/src/main/resources/nifty.xsd https://raw.githubusercontent.com/void256/nifty-gui/1.4/nifty-core/src/main/resources/nifty.xsd">
    <useControls filename="nifty-default-controls.xml"/>
    <useStyles filename="nifty-default-styles.xml"/>
    <screen id="GScreen0">
        <layer id="start" childLayout="absolute">
            <control name="horizontalSlider" id="GHSlider2" min="0" initial="75" max="100" width="256px" x="1001" y="671"/>
            <control name="horizontalSlider" id="GHSlider3" min="0" max="100" initial="100" width="256px" x="1001" y="648"/>
            <control name="checkbox" id="GCheckbox0" x="1001" y="624"/>
            <control name="label" id="GLabel0" width="116px" x="1008" y="626" text="Fullscreen" align="left" height="30px" font="aurulent-sans-16.fnt"/>
            <control name="label" id="GLabel1" width="58px" x="944" y="651" text="Sound" height="28px" font="aurulent-sans-16.fnt"/>
            <control name="label" id="GLabel2" width="49px" x="951" y="673" text="Music" height="28px" font="aurulent-sans-16.fnt"/>
            <control name="label" id="GLabel3" width="100px" x="926" y="575" text="Options" height="50px" font="aurulent-sans-16.fnt"/>
        </layer>
    </screen>
</nifty>

Any way to render in 2D using the root node or fix this issue? (If I add my spatials to the root node they disappear.)

Did you put them in the gui bucket? Else they are rendered in world space and so are huge. (In the GUI, one unit = one pixel so in 3D space that 16 pixel icon is 16 meters across…)

You also might be able to manage this with a different viewport… I haven’t looked at where the normal GUI viewport is in relation to whatever nifty is doing.

Also, depending on what you are doing and how involved your UI would be, there are alternatives to Nifty.