Nifty gotoScreen not unloading screen

When I use the gotoScreen method of Nifty, it is loading the screen I point it to, but it is not unloading the current screen and so they are both being displayed and I can still interact with the first screen. Is there something else that I need to do to get only the second screen to display interact with?



This is the code the I have bound to the click event of an image using interact onClick.



[java]

public void openSecondScreen() {

nifty.addXml("Interface/second/interface.xml");

nifty.gotoScreen("second");

}

[/java]



Any help is greatly appreciated.

If you have an XML with multiple screen tags in it, you don’t need to “reload” the XML. Simply using the gotoScreen(“name”) will disable the first and enable the second.



Not sure if that applies here.

1 Like

You should only call “addXml” once, the first time you switch to the screen. (I add all the XML at once in main in fact using fromXml and a series of addXml). After that use gotoScreen to switch between them.



I’ve not seen the exact problem you are describing although I did run into a problem that might be related with effects not working correctly when switching screens, there is a thread about that recently in this forum.

Thanks to both of you. From your suggestions I re-factored my code, much cleaner now, and it works.

Hi there… i’m having the same issue but your solution didn’t make it :confused:



After I click the button a second time the old screen disappears and everything’s fine…



Im quite new to JME and nifty … anyy ideas ??



Appstate:

[java]package main.appstates;



import com.jme3.app.Application;

import com.jme3.app.SimpleApplication;

import com.jme3.app.state.AbstractAppState;

import com.jme3.app.state.AppStateManager;

import com.jme3.asset.AssetManager;

import com.jme3.bullet.BulletAppState;

import com.jme3.input.InputManager;

import com.jme3.niftygui.NiftyJmeDisplay;

import com.jme3.renderer.ViewPort;

import com.jme3.scene.Node;



import de.lessvoid.nifty.Nifty;

import de.lessvoid.nifty.screen.ScreenController;



public class MainTestAppstate extends AbstractAppState {



private SimpleApplication app;

private Node rootNode;

private AssetManager assetManager;

private AppStateManager stateManager;

private InputManager inputManager;

private ViewPort viewPort;

private BulletAppState bullet;

private Nifty nifty;



public MainTestAppstate(AppStateManager stateManager, Application app){

initialize(stateManager, app);

}



public void initialize(AppStateManager stateManager, Application app) {

super.initialize(stateManager, app);

this.app = (SimpleApplication) app; // can cast Application to something more specific

this.rootNode = this.app.getRootNode();

this.assetManager = this.app.getAssetManager();

this.stateManager = this.app.getStateManager();

this.inputManager = this.app.getInputManager();

this.viewPort = this.app.getViewPort();

this.bullet = this.stateManager.getState(BulletAppState.class);



//execute init()

init();



}



public void init(){





NiftyJmeDisplay niftyDisplay = new NiftyJmeDisplay(assetManager,

inputManager,

app.getAudioRenderer(),

app.getGuiViewPort());

nifty = niftyDisplay.getNifty();

nifty.fromXml(“Interface/menues/start.xml”, “start”, new gui.StartScreen());



// attach the nifty display to the gui view port as a processor

app.getGuiViewPort().addProcessor(niftyDisplay);



// disable the fly cam

app.getFlyByCamera().setEnabled(false);

app.getFlyByCamera().setDragToRotate(true);

inputManager.setCursorVisible(true);



}

}

[/java]



my screencontroller (wanted to use one for all menues):

[java]package gui;



import com.jme3.app.SimpleApplication;

import com.jme3.app.state.AbstractAppState;

import com.jme3.niftygui.NiftyJmeDisplay;

import de.lessvoid.nifty.Nifty;

import de.lessvoid.nifty.screen.Screen;

import de.lessvoid.nifty.screen.ScreenController;



public class StartScreen extends AbstractAppState implements ScreenController {



private Nifty nifty;

private Screen screen;



public StartScreen() {

// TODO Auto-generated constructor stub

}



public void moveToMenueScreen(String screenName) {





nifty.fromXml(“Interface/menues/”+ screenName +".xml", screenName);



// switch to screen

nifty.gotoScreen(screenName);



}



/** Nifty GUI ScreenControl methods /



public void bind(Nifty nifty, Screen screen) {

this.nifty = nifty;

this.screen = screen;

}



public void onStartScreen() {

}



public void onEndScreen() {

}



@Override

public void update(float tpf) {

/
* jME update loop! */

}



}[/java]



start.xml:



[xml]<?xml version=“1.0” encoding=“UTF-8”?>

<nifty xmlns=“http://nifty-gui.sourceforge.net/nifty.xsd

xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance

xsi:schemaLocation=“http://nifty-gui.sourceforge.net/nifty.xsd http://nifty-gui.sourceforge.net/nifty.xsd”>



<useControls filename=“nifty-default-controls.xml” />

<useStyles filename=“nifty-default-styles.xml” />



<screen id=“start” controller=“gui.StartScreen”>

<layer id=“foo” backgroundColor="#00006330" childLayout=“vertical”>

<panel id=“centered_shit” height=“30%” width=“50%” align=“center”

valign=“center” childLayout=“vertical”>



<text

text=“Willkommen im Startfeld des unglaublichen Degbugiingtools, KLick Start du Idiot”

font=“Interface/Fonts/Default.fnt” width=“100%” height=“100%” />

<control name=“button” label=“Start” id=“StartButton” align=“center”

valign=“center” visibleToMouse=“true”>

<interact onClick=“moveToMenueScreen(main_menue)” />

</control>

</panel>

</layer>

</screen>

</nifty>[/xml]



main_menue.xml:



[xml]<?xml version=“1.0” encoding=“UTF-8”?>

<nifty xmlns=“http://nifty-gui.sourceforge.net/nifty.xsd

xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance

xsi:schemaLocation=“http://nifty-gui.sourceforge.net/nifty.xsd http://nifty-gui.sourceforge.net/nifty.xsd”>



<useControls filename=“nifty-default-controls.xml” />

<useStyles filename=“nifty-default-styles.xml” />

<screen id=“main_menue” controller=“gui.StartScreen”>



<layer id=“main_menu” backgroundColor="#00000020" childLayout=“vertical”>



<panel id=“main_menue_spacer_top” height=“5%” width=“80%”

align=“center” childLayout=“vertical”>

</panel>

<panel id=“main_menue_controls_panel_top” height=“25%” width=“80%”

align=“center” childLayout=“vertical” backgroundColor="#99000060">



<panel align=“left” valign=“top” childLayout=“horizontal”

backgroundColor="#ffff0060" height=“20%” width=“30%”>



<control name=“button” label=“Start” id=“StartButton”

align=“center” valign=“center” visibleToMouse=“true”>

<interact onClick=“test()”/>

</control>

<text text=“Testblabla” font=“Interface/Fonts/Default.fnt”

width=“100%” height=“100%” />



</panel>

</panel>

<panel id=“main_menue_spacer” height=“5%” width=“80%” align=“center”

childLayout=“center”>

</panel>

<panel id=“main_menue_content_panel_bottom” height=“60%” width=“80%”

align=“center” childLayout=“vertical” backgroundColor="#ffffff30">

</panel>



<panel id=“main_menue_spacer_bottom” height=“5%” width=“80%”

align=“center” childLayout=“vertical”>

</panel>

</layer>

</screen>



</nifty>[/xml]



Tanks a lot in advance

I think that you want is better using different screen tags and switch it. But you can do too:

[java]nifty.removeScreen(“first”);[/java]

or dettach NiftyJmeDisplay from guiViewPort



Anyway check the output. If something is wrong in XML file Nifty starts to run wrong. I’ve been having a lot of troubles because I had a sintax error on XML.

1 Like

Hi Harton,



thanks for your quick response … +1 !

probably you’re right with the XML Issues … is it possibly to check them with the validateXML() method?



greets

just found a warning in my Output …




An event service by the name NiftyEventBusalready exists. Perhaps multiple threads tried to create a service about the same time?


Could this have sth to do with my problem ?

greets

ConsoleOutput after clicking the button twice:


Information: -> subscribe [StartButton] screen [de.lessvoid.nifty.screen.Screen@7fcb943b] -> [de.lessvoid.nifty.Nifty$ClassSaveEventTopicSubscriber@e70ef09{StartButton}{de.lessvoid.nifty.controls.button.ButtonControl$1@185d3f47}{class de.lessvoid.nifty.elements.events.NiftyMousePrimaryClickedEvent}(de.lessvoid.nifty.controls.button.ButtonControl$1@185d3f47),(class de.lessvoid.nifty.elements.events.NiftyMousePrimaryClickedEvent)]
Jul 08, 2012 7:36:01 PM com.jme3.scene.Node attachChild
Information: Child (BitmapFont) attached to this node (null)
Jul 08, 2012 7:36:01 PM com.jme3.scene.Node attachChild
Information: Child (BitmapFont) attached to this node (null)
Jul 08, 2012 7:36:01 PM com.jme3.scene.Node attachChild
Information: Child (BitmapFont) attached to this node (null)
Jul 08, 2012 7:36:01 PM com.jme3.scene.Node attachChild
Information: Child (BitmapFont) attached to this node (null)
Jul 08, 2012 7:36:01 PM com.jme3.renderer.lwjgl.LwjglRenderer updateUniformLocation
Information: Uniform m_VertexColor is not declared in shader [ShaderSource[name=Common/MatDefs/Misc/Unshaded.vert, defines, type=Vertex], ShaderSource[name=Common/MatDefs/Misc/Unshaded.frag, defines, type=Fragment]].
Jul 08, 2012 7:36:02 PM de.lessvoid.nifty.screen.Screen$EndScreenEndNotify perform
Information: onEndScreen has ended
Jul 08, 2012 7:36:02 PM de.lessvoid.nifty.Nifty$SubscriberRegistry unsubscribeScreen
Information: <- unsubscribe screen for [de.lessvoid.nifty.screen.Screen@7785b73c] [StartButton] -> [de.lessvoid.nifty.Nifty$ClassSaveEventTopicSubscriber@6bc10171{StartButton}{null}{class de.lessvoid.nifty.elements.events.NiftyMousePrimaryClickedEvent}]
Jul 08, 2012 7:36:05 PM de.lessvoid.nifty.screen.Screen$EndScreenEndNotify perform
Information: onEndScreen has ended
Jul 08, 2012 7:36:05 PM de.lessvoid.nifty.Nifty$SubscriberRegistry unsubscribeScreen
Information: <- unsubscribe screen for [de.lessvoid.nifty.screen.Screen@7fcb943b] [StartButton] -> [de.lessvoid.nifty.Nifty$ClassSaveEventTopicSubscriber@e70ef09{StartButton}{null}{class de.lessvoid.nifty.elements.events.NiftyMousePrimaryClickedEvent}]

You have started two instances of nifty…

1 Like

Hi zarch,



thanks for the quick response …



Problem is, that i cant find a second init of nifty … is it possible, that “simpleapp” also launches an instance of nifty for displaying debuging information like FPS and stuff ?



greetings

FPS etc is written directly to the GUI node, no Nifty involved.



I don’t know for sure but the error you are seeing there happens when you start up a second Nifty instance. It may be caused by other things as well.



Your code looks ok, but try breakpointing/logging init() and see how many times it is called.

1 Like

I’m pretty sure you enable your AppState twice. That would create a second nifty.



Instead of simply calling setEnable(true), check if it is enabled first.



[java]

if (!states.getState(MainTestAppState.class).isEnabled()) {

// not enabled, do it here

}

[/java]

1 Like

Found your problem.



This is wrong:

[java]

public MainTestAppstate(AppStateManager stateManager, Application app){

initialize(stateManager, app);

}

[/java]



Remove that constructor. “initialize(…)” is called automatically by jME.

1 Like

Ouh wow. … Your my personal hero now :slight_smile:



Actually I called nifty 3times at all :confused:



[java]

public MainTestAppstate(AppStateManager stateManager, Application app){

// initialize(stateManager, app); 1st time

}



public void initialize(AppStateManager stateManager, Application app) {

super.initialize(stateManager, app); 2nd time

this.app = (SimpleApplication) app; // can cast Application to something more specific

this.rootNode = this.app.getRootNode();

this.assetManager = this.app.getAssetManager();

this.stateManager = this.app.getStateManager();

this.inputManager = this.app.getInputManager();

this.viewPort = this.app.getViewPort();

this.bullet = this.stateManager.getState(BulletAppState.class);



//execute init()

init("start");



}

[/java]



and the third time by JME





Oh damn … your post fixed all my problems… THANK YOU !





EDIT: call the super.initialize

@zarch



thx 4 the info about FPS

super.initialize(…) is fine and you DO want to do this. This will set the “initialized = true” in the super class. If you prefer you can also do it yourself and not call the super. “initialized = true” in your own initialize(…) method.



Edit: The reason you want (and need) to either call super.initialize(…) or set it yourself is that if you don’t, when you setEnable(true), that state will be initialized by the AppStateManager every time.



The AppStateManager does something like this:



(pseudo-code)



[java]

if (yourState.isEnabled()) {

if (!yourState.initialized) {

yourState.initialize(…);

}

// … etc.

}[/java]



And that’s something you definitively don’t want to happen.

1 Like

thx 4 this 2