Scene graph is not properly updated for rendering

Hi,

sometimes i getting this exception:
[java]
SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
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.renderSubScene(RenderManager.java:647)
at com.jme3.renderer.RenderManager.renderScene(RenderManager.java:640)
at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:974)
at com.jme3.renderer.RenderManager.render(RenderManager.java:1035)
at cz.ascaria.zoneofuprising.ZoneOfUprising.update(ZoneOfUprising.java:64)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:151)
at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:185)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:228)
at java.lang.Thread.run(Thread.java:744)
[/java]

it happens randomly with small probability when i navigating through gui (creating and destroying windows)

[java]
// switching layouts
// Destroy all layouts and show specified one
for(Map.Entry<Class<?extends Layout>, Layout> entry : layouts.entrySet()) {
if(layout.equals(entry.getKey())) {
entry.getValue().open();
} else {
entry.getValue().close();
}
}

// Layout creation and destroy snippets
protected void check() {
if(null == guiManager) {
throw new IllegalStateException(“You must use setGuiManager() first”);
}
if(null == screen) {
throw new IllegalStateException(“You must use setScreen() first”);
}
}

public boolean isOpened() {
    return null != win;
}

public void open() {
    check();
    if(isOpened()) {
        close();
    }

    // Create window
    win = new Window(screen, new Vector2f(15f, 15f), new Vector2f(600f, 150f));
    ...
    win.centerToParent();
    screen.addElement(win);
    ...
    // Exit button
    ButtonAdapter exit = new ButtonAdapter(screen, new Vector2f(290f, 80f)) {
        @Override
        public void onButtonMouseLeftUp(MouseButtonEvent evt, boolean toggled) {
            app.stop();
        }
    };
    exit.setText("Exit");
    win.addChild(exit);
}

public void close() {
    if(null != win) {
        win.hide();
        screen.removeElement(win);
        win = null;
    }
}

[/java]

ps: when i call screen.removeElement on modal window, modal layer is not deleted, so i must first call hide and then remove

im doing everything in main thread
maybe should i avoid modyfing scenegraph from button events like this?
[java]
// Storno button
ButtonAdapter storno = new ButtonAdapter(screen, new Vector2f(170f, 150f)) {
@Override
public void onButtonMouseLeftUp(MouseButtonEvent evt, boolean toggled) {
close();
}
};
storno.setText(“Storno”);
win.addChild(storno);

    // Back button
    ButtonAdapter back = new ButtonAdapter(screen, new Vector2f(290f, 400f)) {
        @Override
        public void onButtonMouseLeftUp(MouseButtonEvent evt, boolean toggled) {
            guiManager.show(MainMenuLayout.class);
        }
    };
    back.setText("Back");
    win.addChild(back);

[/java]

First… a couple things I noticed while reading through this:

You’re calling centerToParent() before you add the window to the screen… meaning there is no parent to center to.

Modal windows must call hide or hideWithEffect to properly close the modal background. If you use an effect, you can setDestroyOnHide(true); if you really want to completely remove the window after the fact.

We really need to determine what you are doing differently to stop hide/show from properly working, as I haven’t seen this issue before. The library is run completely on the update loop in the proper order and calling screen.removeElement(this) from within an event handler works fine in the tests I ran here. The problem has to reside in the guiManager class as I can’t repro any of these issues here.

Let me have a look through it now that I’m finally up and not feeling so sick.

yea im calling center to parent early, but it doing what i want, center element relative to whole screen :slight_smile: i know im supposed to center after adding :slight_smile:

here are my sources

i dont know how to reproduce this scene graph exception… sometimes it crashes after two button clicks, sometimes i switching between mainmenu and settings dozen times and everything is ok

@Ascaria said: yea im calling center to parent early, but it doing what i want, center element relative to whole screen :) i know im supposed to center after adding :)

here are my sources

i dont know how to reproduce this scene graph exception… sometimes it crashes after two button clicks, sometimes i switching between mainmenu and settings dozen times and everything is ok

Usually if it intermittently happening, that means you are calling something from another thread and getting lucky on the timing.

yea but i didnt implement multithreading yet, so everything in those sources are in single thread. i also know that im not supposed to edit scenegraph on another thread, but first return result to main thread.

i must be very lucky, i tried to spam clicks to cycle between main menu and settings for dozen seconds and nothing… then on another run, it crashed sometimes even while first time loading main menu

i have no idea what is going on… maybe @normen can you help us? :slight_smile: sources are attached, you can look into it, but everything must be right :frowning:

@Ascaria said: yea but i didnt implement multithreading yet, so everything in those sources are in single thread. i also know that im not supposed to edit scenegraph on another thread, but first return result to main thread.

i must be very lucky, i tried to spam clicks to cycle between main menu and settings for dozen seconds and nothing… then on another run, it crashed sometimes even while first time loading main menu

i have no idea what is going on… maybe @normen can you help us? :slight_smile: sources are attached, you can look into it, but everything must be right :frowning:

sorry i forgot you dont like to repeat yourself :slight_smile: but isnt it interesting? :slight_smile: single-threaded app crashing due to threads? :slight_smile:

@Ascaria said: single-threaded app crashing due to threads? :)

Is that Swing? Then your assumption is wrong, swing runs its own thread. It is all explained in the Swing tutorial Lesson: Concurrency in Swing (The Java™ Tutorials > Creating a GUI With Swing)

hmm i dont have much experience with swing. i currently using it only in Main method in Main.java to give a choose to run server or client and then i use it for server’s console window, not in client…

so only client-side swing is in Main.java and server does not crashing… so i think im not wrong…

but i can give it a try and use swing on server side only when choice to run server/client was already made, so there will be absolutely no swing in client

edit: after all, i do not editing scenegraph from swing on clientside, only kicking players on serverside

@Ascaria said: hmm i dont have much experience with swing. i currently using it only in Main method in Main.java to give a choose to run server or client and then i use it for server's console window, not in client...

so only client-side swing is in Main.java and server does not crashing… so i think im not wrong…

but i can give it a try and use swing on server side only when choice to run server/client was already made, so there will be absolutely no swing in client

edit: after all, i do not editing scenegraph from swing on clientside, only kicking players on serverside

Oh, I probably read to quickly and confused things. So never mind what I said, sorry to confuse the issue.

so problem prevails, damn :slight_smile:

Save reference to Renderthread in simpleinit
add checks everywhere that currenthread is jme thread.

@Empire Phoenix said: Save reference to Renderthread in simpleinit add checks everywhere that currenthread is jme thread.

umm never done this before, can you explain what to do slightly more? :slight_smile:

@Override
public void simpleInitApp() {
this.renderThread = Thread.currentThread();

@Override
public void whatever() {
assert Thread.currentThread() == this.getRendererApp().renderThread : “Wrong thread!” + Thread.currentThread();

1 Like

Well, another assumption we are all making is that you haven’t messed something up in your (unnecessary) forking of SimpleApplication. I assume your update() method is still doing exactly what SimpleApplication’s update() method is doing.

@pspeed said: Well, another assumption we are all making is that you haven't messed something up in your (unnecessary) forking of SimpleApplication. I assume your update() method is still doing _exactly_ what SimpleApplication's update() method is doing.

I haven’t been able to repro a single issue reported by @Ascaria and haven’t had any other users report any of these issues as well. I’m starting to veer towards not making this assumption now.

@Ascaria
Try this:

  • Start a new project using SimpleApllication
  • Add the screen control
  • Use appstates for two different “ui screens”
  • Try using hide/show now
  • Try removing an element from the screen via a button event now

I think you’ll find that all of this works and it may help you narrow down where you are hitting issues. You will also never encounter the error in the topic of this thread. I also think you’ll find the use of AppStates much easier than the layout wrapper you are currently using.

@Empire Phoenix said: @Override public void simpleInitApp() { this.renderThread = Thread.currentThread();

@Override
public void whatever() {
assert Thread.currentThread() == this.getRendererApp().renderThread : “Wrong thread!” + Thread.currentThread();

hmm i did this, also added println to it and this is results:

in app init
Current thread: Thread[main,5,main]

in opening and closing windows
BaseLayout.open() thread: Thread[LWJGL Renderer Thread,5,main]
BaseLayout.open() thread: Thread[LWJGL Renderer Thread,5,main]
BaseLayout.close() thread: Thread[LWJGL Renderer Thread,5,main]
BaseLayout.close() thread: Thread[LWJGL Renderer Thread,5,main]
BaseLayout.open() thread: Thread[LWJGL Renderer Thread,5,main]
BaseLayout.open() thread: Thread[LWJGL Renderer Thread,5,main]
BaseLayout.close() thread: Thread[LWJGL Renderer Thread,5,main]
BaseLayout.close() thread: Thread[LWJGL Renderer Thread,5,main]

i dont know what it is mean because i created gui as is in tonegod tutorials

edit ive also added this in GuiManager constructor and there is
GuiManager.GuiManager() thread: Thread[main,5,main]

Its definitely your self-made SimpleApplication, just use the existing one and extend that.

@normen right now i extended simpleapplication and output is the same