Hi, i have a question about where/when to update Gui data?
Im not using nifty xml/etc. i use my extended class using BitmapText class and Picture class.
and when i try to update BitmapText position (to have it under object when its moving) In simpleUpdate i have this:
2011-09-26 11:39:45 com.jme3.app.Application handleError
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: Gui Node
at com.jme3.scene.Spatial.checkCulling(Spatial.java:229)
at com.jme3.renderer.RenderManager.renderScene(RenderManager.java:508)
at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:712)
at com.jme3.renderer.RenderManager.render(RenderManager.java:745)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:249)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:158)
at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:203)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:221)
at java.lang.Thread.run(Thread.java:619)
it appear in random time.
doing everything other like opening panels / loading windows / etc Work Fine. Just This sticky object text which is update every frame get this exception.
or just tell me how to easy do sticky object text (like nickname over player) and animated text like (moving up Damage number over player)
During the update() loop the “rootNode” is updated (obviously). If you modify its content after it’s been updated but before the next loop you’ll get the error above.
So to remove that error, you have to have all your modifications done before it’s updated. There is also another way to fix this and it’s sometimes not possible to do it otherwise (depending on how your game is set up) and it’s to call theNode.updateGeometricState(); That call will update the node and its geometry but this is a double-edge sword. It can be helpful in certain situation but you can’t use this as a crutch. That means you have to try as much as possible to set everything in the node before it’s update. You could also flag it to be updated on the following frame instead of the one currently running.
simpleUpdate() runs right before the “rootNode” updates, so technically you shouldn’t get that error. But my guess is, there’s something going on elsewhere modifying the scene graph after the update. Are you positive it’s coming from there? Is there any other place where you add/remove/rotate/etc geometries/spatials in the rootNode?
From the quick look of that ObjectStickText class, if I were you, I’d make that an AbstractAppState. Much easier to work with. You should read on this in the wiki.
re: “and fragment from my extended gui class:” Who calls that updateData()?
Something is modifying the scenegraph outside of simpleUpdate(). You just need to figure out what. You have no other threads running? You aren’t using Swing or something to update your scene graph?
updateData() was ok! dont touch it! ;p Problem was in Attach
@pspeed: yes, it’s true i had problem from another thread but With Adding gui node (not updating).
I had Asynchronous Connection that was calling method to add GuiNode(not in simpleUpdate). Thats why i had problem.
I waited more time ~30 sec and i get same error with comment “objectStickText.updateAll();”. When it was uncomment error appears “earlier” don’t know why.
Nevermind of all i just created now Clear solution for it( for updateData too to be sure )
Cool! I actually had one helpful thread in the last week!
Grammar nazi in me has his hackles raised. It’s detach, not dettach. And you should ALWAYS use proper naming convention! Don’t use uppercase on method names!
Note: it looks to me like your callback stuff is essentially reinventing the Callable queue that is already built into JME. Your version just isn’t thread safe.
When I started using jME I was a complete idiot (only slightly better now ;)) and to fix that I had to put a println(“modified node in xmethod()”); and I can tell you that for about a week I deeply hated the scene graph. I had node.updateGeometricState() all over the place… Today I laugh at it, but you were good (or lucky).
@pspeed: so maybe will you help me make it thread safe?
it work nice but it appear, you have right, becouse when i try remove gui node in this callback i have this:
SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at mygame.GameApplicationExtend$ObjectStickText.updateAll(GameApplicationExtend.java:1080)
at mygame.Client.simpleUpdate(Client.java:735)
and i cant use it: https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:advanced:multithreading?s[]=concurrent
The concurrent mod exception may be unrelated to threading… it’s hard to see because I can only see a mix of old and new code. I tried to see who was adding or removing to/from stickTextList but I wasn’t sure I was seeing the right stuff. But you can get a concurrent mod exception without any threads at all if you try to modify the list while you are iterating over it.
The data structures you use are not thread safe, though and you are treating them as such with your home grown version of JME’s callable queue.
pspeed said:
The concurrent mod exception may be unrelated to threading... it's hard to see because I can only see a mix of old and new code. I tried to see who was adding or removing to/from stickTextList but I wasn't sure I was seeing the right stuff. But you can get a concurrent mod exception without any threads at all if you try to modify the list while you are iterating over it.
The data structures you use are not thread safe, though and you are treating them as such with your home grown version of JME's callable queue.
for remember, my problem is when i remove gui element (BitmapText or Picture) and i done it in simpleUpdate
i dont know how to do it properly, i try done it like this:
[java] public void simpleUpdate(float tpf) {
Callable<MyCallback> processGUI = new Callable<MyCallback>(){
public MyCallback call() throws Exception {
gameGUI.renderUpdate();
return null;
}
};
application.enqueue(processGUI);
[/java]
or i should done it like this?:
[java] public void simpleUpdate(float tpf) {
Callable<MyCallback> processGUI = new Callable<MyCallback>(){
public MyCallback call() throws Exception {
for (MyCallback renderCallback : gameGUI.rendererUpdateList) {
gameGUI.renderCallback.end();
}
gameGUI.rendererUpdateList.clear();
return null;
}
};
application.enqueue(processGUI);
[/java]
or somethin like this?(becouse i remove BitmapText):
[java] public void simpleUpdate(float tpf) {
Callable<BitmapText> processGUI = new Callable<BitmapText>(){
public BitmapText call() throws Exception {
for (MyCallback renderCallback : gameGUI.rendererUpdateList) {
gameGUI.renderCallback.end();
}
gameGUI.rendererUpdateList.clear();
return null;
}
};
application.enqueue(processGUI);
[/java]
which way is good for me to understand it?
sorry i just dont understand how it work
but it seem dont work for removing GUI stick element
SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at mygame.GameApplicationExtend$ObjectStickText.updateAll(GameApplicationExtend.java:1090)
at mygame.Client.simpleUpdate(Client.java:748)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:241)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:158)
at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:203)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:221)
at java.lang.Thread.run(Thread.java:619)
so problem is elsewhere or i just not proper write Callable?
it can edit only returned object yes?
if yes, then i dont think if Callable can help in my problem
If you are already in simpleUpdate() then you don’t need to do anything special. The Callable stuff is meant to do from other threads which is what I thought the issue was and why you needed some home-grown Callable thing.
public MyInput newInput(String newName, float newFontsize, int newX, int newY, int newWidth, int newHeight, String newImg, String newImgOver, String newStr) {
Just on quick glance you will get a concurrent modification exception just in that loop. You cannot modify an ArrayList that you are iterating over in this way. At best you could convert to use an actual iterator and then call iterator.remove()…
but really… why not just clear the list after the loop instead of removing each element?
And I’m still not sure what all of the callbacks are for.