So how to initialize an appstate together with an ScreenController?
i have some app states like
[java]
public class Intro_Controller extends AbstractAppState implements ScreenController
{
private Nifty nifty;
private AppStateManager stateManager;
private SimpleApplication app;
public void bind(Nifty newNifty, Screen screen){
this.nifty = newNifty;
}
public void onStartScreen() {
}
public void onEndScreen() {
}
public void next(){
Intro_Controller2 intro2 = new Intro_Controller2();
intro2.initialize(stateManager, app);
stateManager.detach(Intro_Controller.this); // null pointer
stateManager.attach(intro2); //null pointer
nifty.gotoScreen("intro2");
}
@Override
public void update(float tpf) {
}
@Override
public void initialize(AppStateManager pstateManager, Application papp) {
super.initialize(pstateManager, papp);
System.out.println("INIT");
this.app = (SimpleApplication) papp; // can cast Application to something more specific
stateManager = pstateManager;
System.out.println("statemanager:"+stateManager + " app:"+papp);
}
}[/java]
i initialize Intro_Controller from simple init app
[java]
@Override
public void simpleInitApp() {
[…]
// start the screen
Intro_Controller intro = new Intro_Controller();
intro.initialize(stateManager, this);
stateManager.attach(intro);
nifty.gotoScreen("intro");
}
[/java]
statemanager and app are not null when system.out.println(); is used in initialize, but
they are always Null if i want to use them in the Intro controller, for example start the next appstate in next();.
i cant seem to find a method like [java]
nifty.gotoScreen(<STRING>,<SCREENCONTROLLER>);[/java]
how can i avoid this problem?
mfg
You do not pass the instance of your Intro_Controller to the nifty instance when you create it, so it creates a new instance that is not managed by the state manager.
so it works now, i managed to get it to work like this:
[java]
public class Main extends SimpleApplication {
private Intro_Controller Intro;
private Intro_Controller2 Intro2; … and so on
[/java]
[…somewhre later…]
[and then…somewhere else.]
[java]
@Override
public void simpleInitApp() {
[…]
// start the screen
nifty.addScreen("intro", new ScreenBuilder("intro") {{
Intro = new Intro_Controller();
controller(Intro);
[…]
Intro.initialize(stateManager, this);
stateManager.attach(Intro);
nifty.gotoScreen("intro");
}
}
[/java]
the problem is that this is messing up the code like hell
You might want to use the code blocks next time to make your stuff more readable.
In my case, I create my controllers+states and attach them then I pass them to nifty when I load the XML. It’s pretty clean.
sorry i have been in a hurry before… i added the blocks now
can you give me an example?
i am now pretty confused now as i am facing a problem with the design now…
The problem is i need Intro Controller 2 in Intro Controller to start Intro Controller 2 then.
but i am adding all screens at the beginning in the main class that starts Intro Controller
im confused like hell
Mmm… I don’t think I do it that way.
I have a handful of screen controllers that are also app states that I initialize with my main menu. When a user clicks some sub-part of that menu then I load new screens with new screen controllers that are also app states. My GUIs are 100% created with XML.
I may not be the best person to help as I don’t mess with nifty much anymore and will be removing it from Mythruna soon.
You could use fromXml(String fileName, String startScreen, ScreenController…controllers) to pass a ScreenController you instantiated yourself to Nifty. Or you could just let Nifty instantiate your controllers and get them afterwards by screen.getScreenController().
[java]
Screen intro = nifty.getScreen("intro");
Intro_Controller Intro = (Intro_Controller) intro.getScreenController();[/java]
did the job
Thats a bit backwards as you’d want to create the instance yourself and then pass it to nifty, not let nifty create it and then get it from there normally… But if it works for you then you can ofc use nifty as the “Factory” just as well…
Thats how I had to do it - let Nifty instantiate my screen controllers for me, and use the app if I needed to pass any other appstates around the controllers. I’ll post an example when I get home.
@pspeed
What are you thinking of replacing it with? I’m concerned about how suitable nifty is for me.
Your options for nifty are:
1 If you want to instantiate your own screen controllers, you need all of your screens in a single XML file.
2. If you want your screens in separate XML files, and to create the screen controllers yourself, you have to call fromXML every time you change screens. That parses the XML every single time.
3. If you want your screens in separate XML files, but dont mind not creating your own screen controllers yourself (ie letting nifty instantiate them for you), then you can do what you did. Notice that each and every single screen will still have its own instance of the screen controller, even if they are the same class.
Actually, that’s not true.
The way I do it (pseudo code as not got the real code handy) is:
[java]
state1 = new FooState();
state2 = new BarState()
stateManager.registerState(state1);
stateManager.registerState(state2);
nifty.registerScreenControllers(state1, state2);
nifty.fromXml(“state1.xml”);
nifty.addXml(“state2.xml”);
nifty.gotoScreen(“state1Screen”);
[/java]
I then go one step further and actually in the State objects:
[java]
onStartScreen() {
setEnabled(true);
}
onEndScreen() {
screen.getRootElement().resetAllEffects(); // This bit is important as otherwise onStart only gets called once
setEnabled(false);
}
[/java]
Now anywhere in your code you can do nifty.gotoScreen(“state1”) and it will do the nifty transitions and then at the point of the switchover disabled the old state and activate the new one…all nice and automatically.
(forgot to say, you need to do a [java]super.setEnabled(false)[/java] in your controller initializers too otherwise they start enabled).
@normen said:
Thats a bit backwards as you'd want to create the instance yourself and then pass it to nifty, not let nifty create it and then get it from there normally.. But if it works for you then you can ofc use nifty as the "Factory" just as well..
i dont understand, why do i have several instances?
i cant figure out why everyone uses xml, it has no syntax correction or auto complete funktion or anything, so why? :?
so this is the complete way i do now
[java]
@Override
public void simpleInitApp() {
NiftyJmeDisplay niftyDisplay = new NiftyJmeDisplay(
assetManager, inputManager, audioRenderer, guiViewPort);
Nifty nifty = niftyDisplay.getNifty();
guiViewPort.addProcessor(niftyDisplay);
flyCam.setDragToRotate(true);
nifty.loadStyleFile("nifty-default-styles.xml");
nifty.loadControlFile("nifty-default-controls.xml");
nifty.addScreen("intro", new ScreenBuilder("intro") {{
Intro_Controller Intro = new Intro_Controller();
controller(Intro);
layer(new LayerBuilder("background") {{
onStartScreenEffect(new EffectBuilder("fade"){{
length(1000);
startDelay(0);
inherit(true);
post(false);
this.effectParameter("start", "#0");
this.effectParameter("end", "#f");
}});
onEndScreenEffect(new EffectBuilder("fade"){{
length(500);
startDelay(0);
inherit(true);
post(false);
this.effectParameter("start", "#f");
this.effectParameter("end", "#0");
}});
childLayoutCenter();
width("100%");
height("100%");
backgroundColor("#000000");
panel(new PanelBuilder() {{
childLayoutCenter(); // panel properties, add more...
height("100%");
panel(new PanelBuilder() {{
childLayoutCenter(); // panel properties, add more...
width("100%");
image(new ImageBuilder() {{
filename("assets/Res/intro.png");
alignCenter();
interactOnClick("next()");
}});
}});
}});
interactOnClick("next()");
}});
}}.build(nifty));
// and any other screen i ever use
Screen intro = nifty.getScreen("intro");
Intro_Controller Intro = (Intro_Controller) intro.getScreenController(); // so i can get the intro_Controller created in nifty ...
System.out.println("Intro:"+Intro); // <- not null
Intro.initialize(stateManager, this);
stateManager.attach(Intro);
nifty.gotoScreen("intro");
}[/java]
[java]
public class Intro_Controller extends AbstractAppState implements ScreenController, KeyInputHandler
{
private Nifty nifty;
private AppStateManager stateManager;
private SimpleApplication app;
private Intro_Controller2 Intro2;
public void bind(Nifty newNifty, Screen screen)
{ nifty = newNifty;
}
public void onStartScreen() {
Screen intro = nifty.getScreen("intro2");
Intro2 = (Intro_Controller2) intro.getScreenController();
Thread lLadeThread = new ladeThread();
lLadeThread.start();
}
public void onEndScreen() {
}
public void next(){
Intro2.initialize(stateManager, app);
stateManager.detach(this);
stateManager.attach(Intro2);
nifty.gotoScreen("intro2");
}
public boolean keyEvent(NiftyInputEvent inputEvent)
{
Intro2.initialize(stateManager, app);
stateManager.detach(Intro_Controller.this);
stateManager.attach(Intro2);
nifty.gotoScreen("intro2");
return true;
}
private class ladeThread extends Thread {
public void run() {
try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Intro2.initialize(stateManager, app);
stateManager.detach(Intro_Controller.this);
stateManager.attach(Intro2);
nifty.gotoScreen("intro2");
}
}
@Override
public void update(float tpf) {
}
@Override
public void initialize(AppStateManager pstateManager, Application papp) {
super.initialize(pstateManager, papp);
this.app = (SimpleApplication) papp; // can cast Application to something more specific
stateManager = pstateManager;
}
}[/java]
i dont understand, why do i have several instances?
He wanted to say that when you load xml screens (fromXml), nifty does create a instance of your control for you *new Intro_Controller();
*.
i cant figure out why everyone uses xml, it has no syntax correction or auto complete funktion or anything, so why?
Because using xml improves the maintenance *A LOT*.
@kullorki said:
i cant figure out why everyone uses xml, it has no syntax correction or auto complete funktion or anything, so why? :?
If you include a "schemaLocation" correctly in your XML, like here http://www.hub.jmonkeyengine.org/wiki/doku.php/jme3:advanced:nifty_gui_xml_layout - the paragraph "Make Screens", the editor will suggest allowed elements when you type a "<". Any generic XML-editor will do this for you and also validate that your XML-file has the correct syntax. It isn't the usual java editor and not the same hotkeys but it has both auto-complete and syntax checks.
On the other hand, if you like constructing the GUI in java that is fine, use the tool that works best for you.