Integrating Nifty ScreenController with AbstractAppState

Hey all, thanks for looking.



So I can set up Nifty, get my screens displaying and connected with a ScreenController class by setting the controller parameter in my screen’s XML definition but I’m a little stumped when it comes to swapping Nifty screens and the actual sections of your game.



This tutorial is what’s causing me problems.



It says:

Pro Tip: Since you are writing a jME3 application, you can additionally make the ScreenController class extend the AbstractAppState class! This gives the ScreenController access to the application object and to the update loop!


But it doesn't say anything more about how that is actually implemented. Following the tutorial, I'm left in a situation where the ScreenControllers are created but of course, never attached to the state manager so I don't have a reference to the application object.

So how do I actually implement Nifty into a proper game? All the tuts and examples are self-contained and don't really show any real-world use of Nifty, as far as I can tell.

Thanks.

The pattern I use is:

gotoScreen() in nifty is what changes the screen and game state.



no onStartScreen effects inside Nifty.



When the callback happens in the screen controller to say the screen is started:

  1. Fire an onCustom to trigger any effects that would normally be onStartScreen
  2. Activate (either attach or enable depending on how you are using the states) the app state.



    When the callback happens to say the screen is ended:
  3. Disable/Detach the state





    When the state is activated/deactivated then that code should attach and detach objects from the scene graph as required.





    (Edit second callback should have been saying ended not started).

Thanks Zarch, that does help me get my head around part of it.



So, how do you attach/detach states in the ScreenController? By passing in the SimpleApplication in it’s constructor? What about subsequent ScreenControllers that are instantiated by nifty itself?



Perhaps I’m using ScreenControllers incorrectly. It’s easy to get the ScreenController for the start screen working as you can instantiate it yourself when loading you XML.

nifty = niftyDisplay.getNifty();
nifty.fromXml("Interface/UI.xml", "start", new MainMenuController(app));


But then, of course, nifty does the screen changing and instantiates it's own ScreenControllers leaving me with no way to pass anything to them and no way to attach states in their onStartScreen() or onEndScreen() methods.

What am I missing?

nifty.registerScreenControllers()

Thanks Zarch, that didn’t help but I appreciate it. Whatever I did this way just instantiated the default screen controllers. :frowning:



I worked it out in the end using some code from the docs entitled “Nifty GUI 1.3 - Use case scenarios” and subheading “Load several XML files”… something I’m not doing, nor have any desire to do.



Essentially, you HAVE to extend AbstractAppState and you HAVE to let nifty instantiate your ScreenControllers. You can then use nifty.getScreen().getScreenController() to grab a reference to them and attach them to the state manager. This, of course, all has to be done at start-up, just to add to the confusion.



Thanks again.

I can promise that you don’t have to. It’s snipped a bit but this is straight from our simpleInitApp:



[java]

PlayerState playerState = new PlayerState();

stateManager.attach(playerState);

HeroState heroState = new HeroState(playerState);

stateManager.attach(heroState);

MatchState matchState = new MatchState();

stateManager.attach(matchState);

PostMatchState postMatchState = new PostMatchState(nifty);



nifty.registerScreenController(playerState, heroState, matchState, postMatchState);

[/java]

Important to add to zarch’s post: Do this before loading your XML. Just in case that wasn’t obvious.

That was pretty much exactly what I did, but it didn’t work. I’m sure I had it assbackward somewhere, but I have it working now, thanks.



Now if I could just make Nifty shut the hell up. Is there an actual fix for the Logger? The nifty blog says it’s been fixed but it doesn’t work in my JME. The myriad of posts about it here have no real conclusions, only temporary fixes. I have nighty svn turned on and have updated.

[java]

try {

Logger.getLogger(“de.lessvoid.nifty”).setLevel(Level.WARNING);

Logger.getLogger(“NiftyInputEventHandlingLog”).setLevel(Level.WARNING);

Logger.getLogger(“com.jme3.scene.Node”).setLevel(Level.WARNING);

Logger.getLogger(“com.jme3.scene.Node”).setLevel(Level.WARNING);

} catch (AccessControlException ex) {

// Can’t change logging levels in an applet(!)

}

[/java]



Works for me :slight_smile:

I use this in my main:



[java]

Handler[] handlers = Logger.getLogger("").getHandlers();

for (Handler handler : handlers) {

handler.setLevel(Level.ALL);

}

Logger.getLogger("").setLevel(Level.WARNING);

[/java]



Edit: Doh, must remember to refresh page before answering :slight_smile:

Okay, Zarch’s code does make Nifty shut up, for the most part. It still throws out a few INFO messages but it’s no where near as bad so that will suffice for now.



Thanks Jmassing but that would stop the Logger from printing my own Logs and Zarch’s code seems better.

@ctwildgoose said:
Okay, Zarch's code does make Nifty shut up, for the most part. It still throws out a few INFO messages but it's no where near as bad so that will suffice for now.

Thanks Jmassing but that would stop the Logger from printing my own Logs and Zarch's code seems better.

It's the same code, but I set the root logger to warning and then I enable finer logging for my own packages.

Logger.getLogger("my.package").setLevel(Level.FINEST);

More a matter of taste, shut off everything and enable for specific packages or just shut up specific packages, either way works.
@jmaasing said:
It's the same code, but I set the root logger to warning and then I enable finer logging for my own packages.

Logger.getLogger("my.package").setLevel(Level.FINEST);

More a matter of taste, shut off everything and enable for specific packages or just shut up specific packages, either way works.


The reason I prefer this way around is because if anything unusual does start happening somewhere then I know about it. Otherwise you need to know that the debugging level contains something interesting in order to turn it on - but you may not even know that debugging level exists!