Error: State was changed … GuiNode (multiAppStates)

Hi,



i want to build a pauseGameScreen, so when the game is running and F12 is pressed, i wan to change the current app state to the pauseScreenState but i only receive this message:



[java]

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

State was changed after rootNode.updateGeometricState() call.

Make sure you do not modify the scene from another thread!

Problem spatial name: Gui Node

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

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

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

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

at com.jme3.app.SimpleApplication.update(SimpleApplication.java:251)

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

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

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

at java.lang.Thread.run(Thread.java:679)

[/java]



to do this i’ll make somethuing like this:

[java]

(update-loop)

if(pause) {



stateManager.detach(this);

stateManager.attach(gamePausedState);



pause = false;

}





(actionlistener - also implemented)

if (binding.equals(“PauseGame”)) { //Trigger is also defined and added to inputmanager

pause = true;

}

(keylistener)

[/java]



so any ideas whats wrong here?



thanks,

tom

Never do anything to the scene graph on stateAttached() and stateDetached() since they may or may not be run from the proper thread. They are always run from the thread that called attach() or detach().



I’m not sure that’s your problem here, though… but it’s worth fixing to see.



Add stuff in initialize() and remove it in cleanup(). The “right” answer is actually to do some enable/disable management of your own but since you are disabling by removing then using initialize() and cleanup() should see if this is some weird threading problem or something else.

There is nothing wrong in the code you posted that I can see so it must be in the code you didn’t post.



What does the pauseScreenState and “this” state do? Are they doing things on the sceneGraph in either stateAttached or stateDetached?



Are you running the latest table updates or the crusty old plain beta?

@pspeed said:
Are you running the latest table updates or the crusty old plain beta?

nightly build...

Document: GameRunning.java
[java]
package net.wronguniverse.src.AppStates;

imports...

import static net.wronguniverse.src.WrongUniverseCoreClass.*;
/**
* @author Tom Schneider
*/
public class GameRunning extends AbstractAppState implements ActionListener{

//Nifty Variablen laden
private Nifty nifty;
private NiftyJmeDisplay niftyDisplay;



private int fps = 0;
BitmapText hudText;
float scounter = 0f;


private SimpleApplication app;
private Node rootNode;
private AssetManager assetManager;
private AppStateManager stateManager;
private InputManager inputManager;
private ViewPort viewPort;
private ViewPort guiViewPort;
private AudioRenderer audioRenderer;
private Node guiNode;
private Camera cam;

private Node stateNode = new Node("State root-Node to be added to root-node");

private BulletAppState bulletAppState;
private RigidBodyControl landscape;
private CharacterControl player;
private Vector3f walkDirection = new Vector3f();
private boolean left = false, right = false, up = false, down = false, jump=true;
Geometry g;
ViewStats stats;
private boolean pause = false;

public GameRunning(SimpleApplication app) {
this.app = app; // can cast Application to something more specific
this.rootNode = this.app.getRootNode();
this.assetManager = this.app.getAssetManager();
this.stateManager = this.app.getStateManager();
this.inputManager = this.app.getInputManager();
this.viewPort = this.app.getViewPort();
this.guiViewPort = this.app.getGuiViewPort();
this.audioRenderer = this.app.getAudioRenderer();
this.guiNode = this.app.getGuiNode();
this.cam = this.app.getCamera();

}

@Override
public void initialize(AppStateManager stateManager, Application app) {
super.initialize(stateManager, app);

niftyDisplay = new NiftyJmeDisplay(assetManager,
inputManager,
audioRenderer,
guiViewPort);

nifty = niftyDisplay.getNifty();
//nifty.registerScreenController(this);
nifty.addXml("Interface/GUI_02.xml");
nifty.gotoScreen("gamehud");

guiNode.detachAllChildren();
viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f));




guiViewPort.addProcessor(niftyDisplay);

inputManager.setCursorVisible(false);

//STATS AND GUI

//guiNode.attachChild(hudText);
stats = new ViewStats(app, guiNode);



// PHYSICS // PHYSICS // PHYSICS // PHYSICS // PHYSICS //
bulletAppState = new BulletAppState();
stateManager.attach(bulletAppState);
//bulletAppState.getPhysicsSpace().enableDebug(assetManager);





// TERRAIN // TERRAIN // TERRAIN // TERRAIN // TERRAIN //
Node mainScene = new Node("mainScene's Node");
Spatial scn = assetManager.loadModel("Scenes/freeWorld.j3o");
mainScene.attachChild(scn);

stateNode.attachChild(mainScene);
stateNode.attachChild(guiNode);



DirectionalLight sun = new DirectionalLight();
sun.setColor(ColorRGBA.White);
sun.setDirection(new Vector3f(-.5f,-.5f,-.5f));
stateNode.addLight(sun);

CollisionShape sceneShape = CollisionShapeFactory.createMeshShape(mainScene);
landscape = new RigidBodyControl(sceneShape, 0);
scn.addControl(landscape);

CapsuleCollisionShape cs = new CapsuleCollisionShape(1.5f, 6f, 1);
player = new CharacterControl(cs, 0.05f);
player.setJumpSpeed(20);
player.setFallSpeed(30);
player.setGravity(30);
player.setPhysicsLocation(new Vector3f(0, 10, 0));


bulletAppState.getPhysicsSpace().add(landscape);
bulletAppState.getPhysicsSpace().add(player);
Box b = new Box(0.2f,0.2f,0.2f);
g = new Geometry("Box", b);
Material m = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
m.setColor("Color", ColorRGBA.Blue);
g.setMaterial(m);
g.setLocalTranslation(player.getPhysicsLocation());
mainScene.attachChild(g);

setUpKeys();

//cam.setFrustumPerspective(180f,settings.getHeight()/settings.getWidth(),1f,1e24f);
cam.lookAt(new Vector3f(0,-2,0), Vector3f.UNIT_Y);

}

private void setUpKeys() {

inputManager.addMapping("Left", new KeyTrigger(KeyInput.KEY_A));
inputManager.addMapping("Right", new KeyTrigger(KeyInput.KEY_D));
inputManager.addMapping("Up", new KeyTrigger(KeyInput.KEY_W));
inputManager.addMapping("Down", new KeyTrigger(KeyInput.KEY_S));
inputManager.addMapping("Jump", new KeyTrigger(KeyInput.KEY_SPACE));
inputManager.addMapping("PauseGame", new KeyTrigger(KeyInput.KEY_F12));
inputManager.addListener(this, "Left");
inputManager.addListener(this, "Right");
inputManager.addListener(this, "Up");
inputManager.addListener(this, "Down");
inputManager.addListener(this, "Jump");
inputManager.addListener(this, "PauseGame");

//inputManager.addListener(this, new String[]{"Jump"});
}

@Override
public void update(float tpf) {


stats.updateStats();

Vector3f camDir = cam.getDirection().clone().multLocal(0.4f);
Vector3f camLeft = cam.getLeft().clone().multLocal(0.3f);
walkDirection.set(0,0,0);
if(left) walkDirection.addLocal(camLeft);
if(right) walkDirection.addLocal(camLeft.negate());
if(up) walkDirection.addLocal(camDir);
if(down) walkDirection.addLocal(camDir.negate());
player.setWalkDirection(walkDirection);

//reset position if y less than -100
if(player.getPhysicsLocation().getY() <= -100) {
player.setPhysicsLocation(new Vector3f(0, 10f, 0));
}

cam.setLocation(player.getPhysicsLocation());
g.setLocalTranslation(player.getPhysicsLocation().add(new Vector3f(0,2,0)));


if(pause) {

stateManager.detach(this);
//stateManager.attach(gamePausedState);

pause = false;
}

}

@Override
public void stateAttached(AppStateManager stateManager) {
rootNode.attachChild(stateNode);
//guiViewPort.addProcessor(niftyDisplay);

}

@Override
public void stateDetached(AppStateManager stateManager) {
stats.removeStats();
stateManager.detach(bulletAppState);
rootNode.detachChild(stateNode);

guiViewPort.removeProcessor(niftyDisplay);

}

public void onAction(String binding, boolean value, float tpf) {
if (binding.equals("Left")) {
left = value;
} if (binding.equals("Right")) {
right = value;
} if (binding.equals("Up")) {
up = value;
} if (binding.equals("Down")) {
down = value;
}


else if (binding.equals("PauseGame")) {
pause = true;

}

}

}

[/java]

Document: WrongUniverseCoreClass
[java]package net.wronguniverse.src;

imports


public class WrongUniverseCoreClass extends SimpleApplication {

public static AppSettings settings;

public static Intro introState;
public static MainMenu mainMenuState;
public static GameRunning gameRunningState;
public static GamePaused gamePausedState;

public static int fps = 0;
BitmapText hudText;
float scounter = 0f;

private static boolean gameDevMode = false;

public static void main(String[] args) {



WrongUniverseCoreClass coregame = new WrongUniverseCoreClass();

settings = new AppSettings(true);
settings.setSettingsDialogImage("Images/Logos/01.png");

settings.setResolution(1024, 768);
settings.setTitle("Wrong Universe Prototype 0.2");


coregame.setSettings(settings);
coregame.setShowSettings(!gameDevMode);

coregame.start();

}

@Override
public void simpleInitApp() {
inputManager.setCursorVisible(true);
//setDisplayStatView(false); //Disable stats
//setDisplayFps(false); //disable fps
//inputManager.deleteMapping(FlyByCamera.class.);
//flyCam.setEnabled(false);





introState = new Intro(this);
mainMenuState = new MainMenu(this);
gameRunningState = new GameRunning(this);
gamePausedState = new GamePaused(this);

if(gameDevMode) stateManager.attach(gameRunningState);
else stateManager.attach(introState);


flyCam.setMoveSpeed(100);


}


public void simpleUpdate(float tpf) {
scounter += timer.getTimePerFrame();
int bufferfps = (int)timer.getFrameRate();
if(scounter >= 1f){ scounter = 0f;fps=bufferfps;}
}

}
[/java]