gotoScreen and onStartScreen

Has anyone else noticed that when you goto a screen using nifty.gotoScreen() then onStartScreen effects don’t seem to be called?



Do you really need to do a fromXml every time you change screen in order to get onStartScreen effects and the callback to the controller to happen?



Thanks,

Zarch

Hm, didn’t notice this. Can you do a test case for this? I’m sure @void256 would be interested in this.

Edit: this,this,this… a rhetorical masterpiece ^^

Something else must be wrong i use this intensively and never had this issue.

I’m quite willing to believe that something else is wrong but I’m struggling to find it :slight_smile:



Symptoms are:

First screen works - calls



nifty.gotoScreen(“playerHud”);



The effects play (stuff zooms into screen) and onStartScreen() is called in the PlayerState controller.



We then popup a menu and select an option from it. From that menu we do



nifty.gotoScreen(“heroHud”);



Again all the effects work, onEndScreen and onStartScreen are called as expected, menus zoom on and off the screen.



In that new screen something is clicked and



nifty.gotoScreen(“playerHud”);

is called again.



Again the onEndScreen effects and call backs occur as expected, however then the playerHud just appears with no effects being played and the onStartScreen method is never called.





Could this be something to do with the popup menu and opening/closing that at the same time as changing the screen underlying it?

If you call the same screen twice without closing nifty, if I remember correctly, you have to reset the effect.

1 Like

How do you do that?

Something along that line should work. Untested though.



[java]

nifty.getCurrentScreen().findElementByName(“screen_id”).resetEffects();

[/java]



Although, you might want to call that before switching to a different screen… Unsure if that’ll even work for a Screen.

2 Likes

Alternatively, you could trigger the effect programmatically yourself.



[java]

nifty.getCurrentScreen().findElementByName("screen_id").startEffect(EffectEventId.onStartScreen);

[/java]

2 Likes

Ok, I switched the nifty.gotoScreen(“playerHud”);with a nifty.fromXml(“Interface/PlayerHud.xml”, “playerHud”) and it now works exactly as expected.



Is it recommended to use fromXml all the time rather than gotoScreen? It seems a bit inefficient to be constantly reparsing the xml…

@zarch said:
Ok, I switched the nifty.gotoScreen("playerHud");with a nifty.fromXml("Interface/PlayerHud.xml", "playerHud") and it now works exactly as expected.

Is it recommended to use fromXml all the time rather than gotoScreen? It seems a bit inefficient to be constantly reparsing the xml...


That works because you're reloading the screen entirely, not just "paging" from one screen definition to another.
2 Likes

Aha! Thanks a lot madjack!



public void onEndScreen() {

screen.getRootElement().resetAllEffects();



Added that in the PlayerState controller and it seems to have fixed things.



It still seems a bit odd that I need to reset it manually like that though.

From a design point of view you might not want an “intro” each time you switch to a screen, but I’ll agree on this too. But let’s leave it at that. At least Nifty is being improved upon, that’s a good start.

1 Like

There must be something else wrong.



I’ve just checked this with a standard Nifty “hello world” example and onStartScreen effects work for me even when you nifty.gotoScreen() to the current screen. It should work for other screens too.



XML-Example: Only a single screen called “start” with onStartScreen “move” effect applied to a panel:



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

<nifty xmlns=“http://nifty-gui.sourceforge.net/nifty-1.3.xsd” xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance” xsi:schemaLocation=“http://nifty-gui.sourceforge.net/nifty-1.3.xsd http://nifty-gui.sourceforge.net/nifty-1.3.xsd”>

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

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

<screen id=“start” controller=“de.lessvoid.nifty.examples.helloworld.HelloWorldStartScreen”>

<layer id=“layer” backgroundColor="#003f" childLayout=“center”>

<panel id=“panel” height=“25%” width=“35%” align=“center” valign=“center” backgroundColor="#f60f" childLayout=“center” visibleToMouse=“true”>

<interact onClick=“quit()”/>

<effect>

<onStartScreen name=“move” mode=“in” direction=“top” length=“300” startDelay=“0” inherit=“true”/>

<onEndScreen name=“move” mode=“out” direction=“bottom” length=“300” startDelay=“0” inherit=“true”/>

<onHover name=“pulsate” scaleFactor=“0.008” startColor="#f600" endColor="#ffff" post=“true”/>

</effect>

<text id=“text” font=“aurulent-sans-16.fnt” color="#000f" text=“Hello World!” align=“center” valign=“center” />

</panel>

</layer>

</screen>

</nifty>[/xml]



And the ScreenController with the “quit()” method that is being called when the panel is being clicked. It simply goes to the active screen called “start” again which first calls onEndScreen effects and then calls onStartScreen effects again.



[java]public class HelloWorldStartScreen implements ScreenController {

private Nifty nifty;



public void bind(final Nifty newNifty, final Screen newScreen) {

this.nifty = newNifty;

}



@Override

public void onStartScreen() {

}



@Override

public void onEndScreen() {

}



public void quit() {

nifty.gotoScreen(“start”); <


}
...
[/java]

Here is a video proof: http://vimeo.com/39800746 ;)

PS: While waiting for the video to be available I've checked this again with two screens and it works there as well.
PPS: Please provide a SSCCE for this as Normen suggested.

@void256

Maybe try it with one XML containing 2 screens. Load the XML calling the first screen then switch to the second screen. It’s when you come back to the first screen that onStartScreen isn’t called.



At least that’s what I think happens.

1 Like

That’s what I did while waiting for the video to be available, one XML file, two screens and nifty.gotoScreen() between both screens. Works for me.

In my case its:



register the three controllers



loadXml(logonScreen.xml, logonScreen)

addXml(playerScreen)

addXml(heroScreen)

addXml(popup)



from logonScreen - gotoScreen(playerScreen)

on playerScreen popup(popup)

from playerScreen gotoScreen(heroScreen)

from heroScreen gotoScreen(playerScreen) * this is the transition where playerScreen gets no effects/callback



I’ll try and put a simple example together when I get a chance. Calling the reset effects function has fixed it for now though.

Sorry it’s taken so long, I’ve had a really busy week!



It definitely seems to be connected to the popup. I’ve just tried putting together a test case and while I’ve not (yet) reproduced the exact behaviour I can definitely break nifty in a similar way.



Attached is a SimpleGame project. Build and Run it and you should see a spinning cube and a menu.



www.herodex.net/downloads/NiftyTransitionTest.zip



Click on gotoTwo and gotoOne to switch between the two screens as much as you like.

Click on popup and then gotoTwo on the popup and it calls exactly the same method as not in the popup but the results are very different. The screen transitions out but then reappears and now refuses to respond to any user input. Screen ending/etc handlers are never called as the cube would disappear if they were but instead it keeps spinning behind the gui.





Thanks,

Zarch

P.S. Is it possible to get a callback into the handler when the transition to that screen starts as well as when it ends? The only way I can think to do that atm is to remove the onStartScreen and use onCustom to do the entry effects.

@void256 said:
That's what I did while waiting for the video to be available, one XML file, two screens and nifty.gotoScreen() between both screens. Works for me.


Any thoughts on this please Void?

Change the code at the end of the StateOne.java file like so:



[java]…

public void gotoTwo() {

closePopup();

}



private void closePopup() {

if (popup != null) {

final Element toClose = popup;

popup.stopEffect(EffectEventId.onCustom);

popup.startEffect(EffectEventId.onCustom, new EndNotify() {

@Override

public void perform() {

nifty.closePopup(toClose.getId(), new EndNotify() {

@Override

public void perform() {

nifty.gotoScreen(“screenTwo”);

}

});

}

}, “hide”);

}

}

[/java]



Explanation:



nifty.closePopup() will not close the popup immediatly. The close request will be queued and will be executed at a later time.



But this is clearly a bug since you’ve called it in a reasonable way and Nifty should really handle this case internally correctly without showing this odd behaviour. I’ve added a bug report for this in the sf.net bug tracker.



Thanks for taking the time to create an excellent sscce for this issue. I was able to reproduce this in seconds and it’s clearly a bug! :slight_smile:

3 Likes

Thanks @Void256, glad it worked :slight_smile:



Incidentally if I remove the closePopup call from screen one then the transition between the two screens works correctly and when you return to screen one then the popup is still open. Is that the intended behaviour?