I spent the past few days trying to wrap my head around Nifty. I’ve got a system set up where de.lessvoid.nifty.controls.Controller objects listen to various layers in a single nifty screen and receive feedback from those layers. At the moment I don’t use a ScreenController, I could but there’s no apparent need for it yet.
I don’t understand one fairly big thing… How do I connect the game to the gui?
Am I right in assuming Nifty.setGlobalProperties is the proper way to pass handles to the datamodels used by the game? Or should I use the screencontroller object for that? The de.lessvoid.nifty.controls.Controller’s I use do not allow parameters in their constructors, (I would have preferred that direct approach) but apparently the instance of the controller I pass is only used to produce a new instance via parameterless constructor. (Surprising)
Also, next up: a game data-model will change, this means either listeners will fire or time passes. How do I ensure the GUI represents the latest data from the games datamodels? For example if I have a model in game that produces random numbers how do I get the gui to show those numbers in a label, updating the label when needed (preferably via listeners)? Can I just add listeners to those models and change the field from whichever thread calls those? Or will there be threading trouble? (Most GUI’s I know are handled by a separate thread and act up or won’t act at all if you just start poking values into them.)
Nifty is done on the rendering thread - so you need to make sure you make changes to the GUI from that thread in the same way you do for changes to the scene graph. Enqueue the changes (app.enqueue()) if they are coming in from the wrong thread.
Nifty → Your Game Object
To notify your game objects when something in Nifty happens I suggest using Nifty Events with the event bus. This is probably the best way since you don’t need to worry how you get your game objects into the Controller or ScreenController instances.
Your Game Object → Nifty
This should be easier. You need a reference to the current Nifty screen and you call screen.findNiftyControl(…) or screen.findElementByName(…) to get a reference to the NiftyControl or the element in question. If you’re using a NiftyControl you access the control with it’s control API interface. If you use plain elements you’ll need to fumble around with the TextRenderer/ImageRenderer/PanelRender stuff the Element provides.
Besides this zarch is right of course that you’ll need to make sure that everything you do with Nifty is being done from the main thread.
Thanks for the threading tip zarch, I will keep it in mind… I didn’t know app.enqueue yet but it’ll surely come in handy at some point.
And void256, that event bus is what I use when I use: " @NiftyEventSubscriber(pattern = “”)"? I’m using that, only I don’t want the data models to actually listen to the fields and buttons directly. So this is how I connected the Controllers to the gui. My problem is rather how to connect the controllers to the gamemodel.
I think a game object like an AI agent or spaceship should have no knowledge of the gui. That’s what the gui controllers are for. It’s okay for the controllers to be tightly bound to both nifty and their relevant data models since that’s essentially their job.
I discovered that the screencontroller doesn’t have the parameterless constructor requirement like the controllers have. The binding phase of the controllers has access to the screencontroller through the screen. So now I pass references of the datamodels to the controllers via that route. Essentially the bind method now binds the controller to the hud by getting references to the relevant controls. But it also binds to the models by getting the references to the relevant values in the models, and setting up listeners.
I hope this does not stray too far from nifty gui’s original philosophy. What do you think?
I use Controls (the jme3 ones) which have a connection to the required GUI elements that I attach to spatials in MonkeyZone to display hitpoints etc. for example.
That definately has the advantage of being up to date because you update every call to update… But will it also respond to gui events?
Well depends on what state of the gui you check and apply in the Control. I never used the event system.