Abrupt State change doesn’t provide enough time for GUI transition effects

If I use [java]statemanager.detach(currentState)[/java] & then the gui(which is attached to the current state) doesn’t get the chance to fade of.



So, how should I change the state so the gui/other elements get the chance/time to work on the transition effect?

xD Dude, when the AppState is detached it obviously is not called anymore and can hence not fade out… Just don’t detach it but set some trigger, then count down the fps and fade out then detach the AppState.

a little guideline would help…what kind of trigger. :frowning:

a simple method… something like:

[java]appState.startFadeOut(1);[/java]

in the class:

[java]

boolean fade = false;

float counter = 0;

float fadeTime = 0;



public void startFadeOut(float time){

fade = true;

fadeTime = time;

counter = 0;

}



public void update(float tpf){

if(fade){

counter+=tpf;

doFadeOut((fadeTime-counter)/fadeTime);

if(counter >= fadeTime){

fade = false;

app.getStateManager().detach(this); //might have to do this in a callable, idk if the list is threadsafe atm

}

}

}

[/java]

1 Like

The list is definitely thread safe.

1 Like

@normen I’ve found an easy solution. When I click the “start game” button I execute the following line,

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

on the state update loop, I have added this line, always checking if the menu is still there or not.

[java]if (nifty.getScreen(“start”) == null) game.getStateManager().detach(this);[/java]

and on the stateDetached method, I just attach the new state. So, when the menu is removed, its time to switch state.

[java]game.getStateManager().attach(new InGameState(RFPGame.getStaticInstance()));[/java]



Now 3 questions,


  1. Is this method ok?


  2. If I just relocate the null pointer check line like the following, I get an error



    [java]SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]

    java.lang.IllegalStateException: Scene graph is not properly updated for rendering.

    Make sure scene graph state was not changed after

    rootNode.updateGeometricState() call.

    Problem spatial name: InGameState Root Node

    at com.jme3.scene.Spatial.checkCulling(Spatial.java:241)

    at com.jme3.renderer.RenderManager.renderScene(RenderManager.java:775)

    at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:1116)

    at com.jme3.renderer.RenderManager.render(RenderManager.java:1167)

    at RFP.states.MainMenuState.update(MainMenuState.java:74)

    at com.jme3.app.state.AppStateManager.update(AppStateManager.java:153)

    at RFP.core.RFPGame.update(RFPGame.java:77)

    at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:149)

    at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:185)

    at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:223)

    at java.lang.Thread.run(Thread.java:662)[/java]



    When the update method of the state is like this,

    [java]@Override

    public void update(float tpf) {

    super.update(tpf);

    // super :: public void update(float tpf){}



    if (nifty.getScreen("start") == null) game.getStateManager().detach(this); // POSITION 1





    rootNode.updateLogicalState(tpf);

    guiNode.updateLogicalState(tpf);

    rootNode.updateGeometricState();

    guiNode.updateGeometricState();



    game.getStateManager().render(game.getRenderManager());

    game.getRenderManager().render(tpf, game.getContext().isRenderable());

    simpleRender(game.getRenderManager());

    game.getStateManager().postRender();

    //

    // if (nifty.getScreen("start") == null) game.getStateManager().detach(this); // POSITION 2

    //

    }[/java]



    The commented line is the position where it works fine. But, where it causes error is where it should be, cause simpleUpdate(tpf) was on that point on SimpleApplication class.


  3. Where should the usual update should take place? At Position 1 or position 2?

oO why do you update the state manager and rootNode etc in the appState? :o

Because I’ve moved all the code from SimpleApp to individual classes. In the MAIN CLASS update method, just the tpf is calculated and stateManager is being updated. And the rootNode, guiNode, and their attachment and detachment to the application viewport is done in their respective states. So, they need to have update methods in the stateUpdate(), dont they? Hence, there is no rootNode or guiNode in the MAIN class to call update to.



Is it something catastrophic?



A little older version of what my states look like. (First Post) . later on i also brought in the stateManager code.

http://hub.jmonkeyengine.org/groups/general-2/forum/topic/how-to-switch-states/

:brainsout:

No one complained in the older thread, so I thought it was ok. :smiley:



(btw, how can i post this smiley? :roll: )

like this :brainsout:

@normen okey I see your point. Now I have re-written them.



MAIN[java]

public class Main extends SimpleApplication{



MainMenuState mainMenuState;



public static void main(String[] args){

Main app = new Main();

app.start();

}



public void simpleInitApp() {

fixSimpleApp();



mainMenuState = new MainMenuState(this);



stateManager.attach(mainMenuState);

}



public void fixSimpleApp(){

inputManager.deleteMapping(INPUT_MAPPING_EXIT);

}

}

[/java]



state class :

[java]public class MainMenuState extends AbstractAppState implements ScreenController{



SimpleApplication game = null;

private NiftyJmeDisplay niftyDisplay = null;

private Nifty nifty = null;



public MainMenuState(SimpleApplication game) {

this.game = game;

}



@Override

public void initialize(AppStateManager stateManager, Application app) {

super.initialize(stateManager, app);



niftyDisplay = new NiftyJmeDisplay(game.getAssetManager(),

game.getInputManager(),

game.getAudioRenderer(),

game.getGuiViewPort());

nifty = niftyDisplay.getNifty();



nifty.fromXml(“Interface/intro.xml”, “start”, this);



game.getGuiViewPort().addProcessor(niftyDisplay);

game.getInputManager().setCursorVisible(true);

}



@Override

public void stateAttached(AppStateManager stateManager) {

}



@Override

public void stateDetached(AppStateManager stateManager) {

game.getGuiViewPort().removeProcessor(niftyDisplay);

game.getStateManager().attach(new InGameState(game));

}



@Override

public void update(float tpf) {

super.update(tpf);

if (nifty.getScreen(“start”) == null) game.getStateManager().detach(this);

}



public void bind(Nifty nifty, Screen screen) {

}



public void onStartScreen() {

}



public void onEndScreen() {

}



public void startGame(){

nifty.removeScreen(“start”);

}



public void exitGame(){

game.stop();

}

}

[/java]



They looks pretty clean to me right now.



No one complained on that old thread of mine, so I kept on using it.