Exporting a node to xml

Hey guys,

I am trying to create objects in the scene and place them in random places (random locations, shapes, colors, etc) - this part is done

and then export them to a file (say xml) so other users can import them later into the scene and preserve these properties.

I am not sure where to start and thought i’d throw it out there to get the best design (or the ‘right’ way to do it) before starting my work.

Thanks in advance :slight_smile:

In would define interchange object (tree) that is filled on export with all the necessary data (if useing an ES this object already exists btw) then use xstream to output it to xml.

Alternativly it could work with the j3o format integrated into the engine, if you can ensure that the stuff lies in the same locations, but as far as i know there can be some problems with this.

Important to know would be the time preservance for this. eg is it thought as a send file exchange format or as a long term archive. (as j3o can internally change in time old stuff might become unreadable)

So I decided to go with the example: https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:advanced:save_and_load

I can export to j3o just fine, but when I attempt to import, I get the following:

EVERE: Could not access constructor of class 'com.sim.animation.animator3d.gui.BitmapTextDrawable'!
Some types need to have the BinaryImporter set up in a special way. Please doublecheck the setup.
Jul 1, 2013 2:46:34 PM class com.jme3.export.binary.BinaryImporter readObject(int id)
SEVERE: Exception
java.lang.InstantiationException: com.sim.animation.animator3d.gui.BitmapTextDrawable
at java.lang.Class.newInstance0(Class.java:340)
at java.lang.Class.newInstance(Class.java:308)
at com.jme3.export.SavableClassUtil.fromName(SavableClassUtil.java:172)
at com.jme3.export.SavableClassUtil.fromName(SavableClassUtil.java:204)
at com.jme3.export.binary.BinaryImporter.readObject(BinaryImporter.java:330)
at com.jme3.export.binary.BinaryInputCapsule.resolveIDs(BinaryInputCapsule.java:484)
at com.jme3.export.binary.BinaryInputCapsule.readSavableArray(BinaryInputCapsule.java:472)
at com.jme3.export.binary.BinaryInputCapsule.readSavableArrayList(BinaryInputCapsule.java:588)
at com.jme3.scene.Node.read(Node.java:599)
at com.jme3.export.binary.BinaryImporter.readObject(BinaryImporter.java:341)
at com.jme3.export.binary.BinaryInputCapsule.resolveIDs(BinaryInputCapsule.java:484)
at com.jme3.export.binary.BinaryInputCapsule.readSavableArray(BinaryInputCapsule.java:472)
at com.jme3.export.binary.BinaryInputCapsule.readSavableArrayList(BinaryInputCapsule.java:588)
at com.jme3.scene.Node.read(Node.java:599)
at com.jme3.export.binary.BinaryImporter.readObject(BinaryImporter.java:341)
at com.jme3.export.binary.BinaryImporter.load(BinaryImporter.java:243)
at com.jme3.export.binary.BinaryImporter.load(BinaryImporter.java:126)
at com.jme3.export.binary.BinaryImporter.load(BinaryImporter.java:110)
at com.jme3.asset.DesktopAssetManager.loadAsset(DesktopAssetManager.java:282)
at com.jme3.asset.DesktopAssetManager.loadModel(DesktopAssetManager.java:410)
at com.jme3.asset.DesktopAssetManager.loadModel(DesktopAssetManager.java:420)
at com.sim.animation.animator3d.Adapters.DrawMode.loadCustomNode(DrawMode.java:236)
at com.sim.animation.animator3d.Adapters.DrawMode.importCustomNode(DrawMode.java:224)
at com.sim.animation.animator3d.Adapters.DrawMode.access$4(DrawMode.java:195)
at com.sim.animation.animator3d.Adapters.DrawMode$4.execute(DrawMode.java:155)
at com.sim.animation.animator3d.Controller.CommandManager.onKeyEvent(CommandManager.java:192)
at com.jme3.input.InputManager.processQueue(InputManager.java:773)
at com.jme3.input.InputManager.update(InputManager.java:851)
at com.jme3.app.Application.update(Application.java:598)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:233)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:149)
at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:182)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:223)
at java.lang.Thread.run(Thread.java:662)
Jul 1, 2013 2:46:34 PM com.jme3.app.Application handleError
SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
java.lang.NullPointerException
at com.jme3.scene.Node.read(Node.java:605)
at com.jme3.export.binary.BinaryImporter.readObject(BinaryImporter.java:341)
at com.jme3.export.binary.BinaryInputCapsule.resolveIDs(BinaryInputCapsule.java:484)
at com.jme3.export.binary.BinaryInputCapsule.readSavableArray(BinaryInputCapsule.java:472)
at com.jme3.export.binary.BinaryInputCapsule.readSavableArrayList(BinaryInputCapsule.java:588)
at com.jme3.scene.Node.read(Node.java:599)
at com.jme3.export.binary.BinaryImporter.readObject(BinaryImporter.java:341)
at com.jme3.export.binary.BinaryImporter.load(BinaryImporter.java:243)
at com.jme3.export.binary.BinaryImporter.load(BinaryImporter.java:126)
at com.jme3.export.binary.BinaryImporter.load(BinaryImporter.java:110)
at com.jme3.asset.DesktopAssetManager.loadAsset(DesktopAssetManager.java:282)
at com.jme3.asset.DesktopAssetManager.loadModel(DesktopAssetManager.java:410)
at com.jme3.asset.DesktopAssetManager.loadModel(DesktopAssetManager.java:420)
at com.sim.animation.animator3d.Adapters.DrawMode.loadCustomNode(DrawMode.java:236)
at com.sim.animation.animator3d.Adapters.DrawMode.importCustomNode(DrawMode.java:224)
at com.sim.animation.animator3d.Adapters.DrawMode.access$4(DrawMode.java:195)
at com.sim.animation.animator3d.Adapters.DrawMode$4.execute(DrawMode.java:155)
at com.sim.animation.animator3d.Controller.CommandManager.onKeyEvent(CommandManager.java:192)
at com.jme3.input.InputManager.processQueue(InputManager.java:773)
at com.jme3.input.InputManager.update(InputManager.java:851)
at com.jme3.app.Application.update(Application.java:598)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:233)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:149)
at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:182)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:223)
at java.lang.Thread.run(Thread.java:662)

and the code for importing is:

 private void loadCustomNode(File customNodeFile) {
    
        ppa.getAssetManager().registerLocator( customNodeFile.getParent(), FileLocator.class);
        Node loadedNode = (Node) ppa.getAssetManager().loadModel(customNodeFile.getName());
        loadedNode.setName("loaded node");
       
        // attach imported node to mode node
        rootNode.attachChild(loadedNode);
 
    }

where the customNodeFile.getName() is customnode.j3o
and the customNodeFile.getParent() is the folder path it’s in

Something is wrong:
java.lang.InstantiationException: com.kiva.sim.animation.animator3d.gui.BitmapTextDrawable

What’s wrong would be dependent on code we cannot see. Hint above.

Does that class have an empty constructor as is required by serialization?

sorry guys I realized the post got posted before finishing, see edited code above

@Momoko_Fan , the node that I am trying to load is a node that contains one or more bitmapTextDrawable that does take inputs in the constructor… but with the code to import a .j3o I am only loading a PRE-saved node no? why would I need to instantiate that constructor again? I am not re-creating these nodes that I am importing…

@homsi said: @Momoko_Fan , the node that I am trying to load is a node that contains one or more bitmapTextDrawable that does take inputs in the constructor... but with the code to import a .j3o I am only loading a PRE-saved node no? why would I need to instantiate that constructor again? I am not re-creating these nodes that I am importing....

JME is not magic. I cannot create objects without constructing them.

ok you’re right, that wasn’t smart from my part, so to make it work, for a constructor of:

  public BitmapTextDrawable(BitmapFont font) {
super(font); // BitmapTextDrawable extends BitmapText
}

what should I do in my loadCustomNode() method to instantiate that constructor correctly?? I am considering the code of:

Node loadedNode = (Node) ppa.getAssetManager().loadModel(customNodeFile.getName());

as a black box that takes a j3o file and loads it. But how can I load it correctly in this case?

You still didn’t understand. The constructor is empty, it must also have no parameters. The read() method (re)constructs the data.

@normen I understand the problem, but I don’t understand the solution. How can I get away w/ an empty constructor when my constructor for BitmapTextDrawable (which extends BitmapText) requires a font?

public BitmapTextDrawable(){
super(MyUtils.loadARandomFont())
}

BitmapText has problems and cannot be saved and loaded from JME capsules without some major changes. You can’t subclass it to make it work, really… and in general subclassing BitmapText is probably a bad idea anyway. BitmapText must be created with a font and then that font cannot be changed for that instance.

You could wrap BitmapText in another object to be able to save and load it because then you could delay creation until you knew the font. Then just delegate through the methods that you want to be able to call on it.

but it still gives me an error even if I load a font… see below:

I used:

    private void loadCustomNode(File customNodeFile) {
    
        ppa.getAssetManager().registerLocator( customNodeFile.getParent(), FileLocator.class);
        Node loadedNode = (Node) ppa.getAssetManager().loadModel(customNodeFile.getName());
        loadedNode.setName("loaded node");
       
        // attach imported node to mode node
        nModeNode.attachChild(loadedNode);
        
    }

where Bitmaptextdrawable has this following constructor:

public BitmapTextDrawable() {
        super(loadFont());
       
    }
 
    
    private static BitmapFont loadFont() {
        textFont =  MapDisplay.visualizer.getAssetManager().
                loadFont("Interface/Fonts/Default.fnt");
        return textFont;
    }

I got this error:

Jul 2, 2013 12:10:50 PM com.jme3.export.SavableClassUtil fromName
SEVERE: Could not access constructor of class 'com.jme3.font.BitmapTextPage'! 
Some types need to have the BinaryImporter set up in a special way. Please doublecheck the setup.
Jul 2, 2013 12:10:50 PM class com.jme3.export.binary.BinaryImporter readObject(int id)
SEVERE: Exception
java.lang.InstantiationException: com.jme3.font.BitmapTextPage
	at java.lang.Class.newInstance0(Class.java:340)
	at java.lang.Class.newInstance(Class.java:308)
	at com.jme3.export.SavableClassUtil.fromName(SavableClassUtil.java:172)
	at com.jme3.export.SavableClassUtil.fromName(SavableClassUtil.java:204)
	at com.jme3.export.binary.BinaryImporter.readObject(BinaryImporter.java:330)
	at com.jme3.export.binary.BinaryInputCapsule.resolveIDs(BinaryInputCapsule.java:484)
	at com.jme3.export.binary.BinaryInputCapsule.readSavableArray(BinaryInputCapsule.java:472)
	at com.jme3.export.binary.BinaryInputCapsule.readSavableArrayList(BinaryInputCapsule.java:588)
	at com.jme3.scene.Node.read(Node.java:599)
	at com.jme3.export.binary.BinaryImporter.readObject(BinaryImporter.java:341)
	at com.jme3.export.binary.BinaryInputCapsule.resolveIDs(BinaryInputCapsule.java:484)
	at com.jme3.export.binary.BinaryInputCapsule.readSavableArray(BinaryInputCapsule.java:472)
	at com.jme3.export.binary.BinaryInputCapsule.readSavableArrayList(BinaryInputCapsule.java:588)
	at com.jme3.scene.Node.read(Node.java:599)
	at com.jme3.export.binary.BinaryImporter.readObject(BinaryImporter.java:341)
	at com.jme3.export.binary.BinaryInputCapsule.resolveIDs(BinaryInputCapsule.java:484)
	at com.jme3.export.binary.BinaryInputCapsule.readSavableArray(BinaryInputCapsule.java:472)
	at com.jme3.export.binary.BinaryInputCapsule.readSavableArrayList(BinaryInputCapsule.java:588)
	at com.jme3.scene.Node.read(Node.java:599)
	at com.jme3.export.binary.BinaryImporter.readObject(BinaryImporter.java:341)
	at com.jme3.export.binary.BinaryImporter.load(BinaryImporter.java:243)
	at com.jme3.export.binary.BinaryImporter.load(BinaryImporter.java:126)
	at com.jme3.export.binary.BinaryImporter.load(BinaryImporter.java:110)
	at com.jme3.asset.DesktopAssetManager.loadAsset(DesktopAssetManager.java:282)
	at com.jme3.asset.DesktopAssetManager.loadModel(DesktopAssetManager.java:410)
	at com.jme3.asset.DesktopAssetManager.loadModel(DesktopAssetManager.java:420)
	at com.geo.sim.animation.animator3d.Adapters.DrawMode.loadCustomNode(DrawMode.java:232)
	at com.geo.sim.animation.animator3d.Adapters.DrawMode.importCustomNode(DrawMode.java:220)
	at com.geo.sim.animation.animator3d.Adapters.DrawMode.access$4(DrawMode.java:195)
	at com.geo.sim.animation.animator3d.Adapters.DrawMode$4.execute(DrawMode.java:155)
	at com.geo.sim.animation.animator3d.Controller.CommandManager.onKeyEvent(CommandManager.java:192)
	at com.jme3.input.InputManager.processQueue(InputManager.java:773)
	at com.jme3.input.InputManager.update(InputManager.java:851)
	at com.jme3.app.Application.update(Application.java:598)
	at com.jme3.app.SimpleApplication.update(SimpleApplication.java:233)
	at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:149)
	at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:182)
	at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:223)
	at java.lang.Thread.run(Thread.java:662)
Jul 2, 2013 12:11:12 PM com.jme3.app.Application handleError
SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
java.lang.NullPointerException
	at com.jme3.scene.Node.read(Node.java:605)
	at com.jme3.export.binary.BinaryImporter.readObject(BinaryImporter.java:341)
	at com.jme3.export.binary.BinaryInputCapsule.resolveIDs(BinaryInputCapsule.java:484)
	at com.jme3.export.binary.BinaryInputCapsule.readSavableArray(BinaryInputCapsule.java:472)
	at com.jme3.export.binary.BinaryInputCapsule.readSavableArrayList(BinaryInputCapsule.java:588)
	at com.jme3.scene.Node.read(Node.java:599)
	at com.jme3.export.binary.BinaryImporter.readObject(BinaryImporter.java:341)
	at com.jme3.export.binary.BinaryInputCapsule.resolveIDs(BinaryInputCapsule.java:484)
	at com.jme3.export.binary.BinaryInputCapsule.readSavableArray(BinaryInputCapsule.java:472)
	at com.jme3.export.binary.BinaryInputCapsule.readSavableArrayList(BinaryInputCapsule.java:588)
	at com.jme3.scene.Node.read(Node.java:599)
	at com.jme3.export.binary.BinaryImporter.readObject(BinaryImporter.java:341)
	at com.jme3.export.binary.BinaryImporter.load(BinaryImporter.java:243)
	at com.jme3.export.binary.BinaryImporter.load(BinaryImporter.java:126)
	at com.jme3.export.binary.BinaryImporter.load(BinaryImporter.java:110)
	at com.jme3.asset.DesktopAssetManager.loadAsset(DesktopAssetManager.java:282)
	at com.jme3.asset.DesktopAssetManager.loadModel(DesktopAssetManager.java:410)
	at com.jme3.asset.DesktopAssetManager.loadModel(DesktopAssetManager.java:420)
	at com.geo.sim.animation.animator3d.Adapters.DrawMode.loadCustomNode(DrawMode.java:232)
	at com.geo.sim.animation.animator3d.Adapters.DrawMode.importCustomNode(DrawMode.java:220)
	at com.geo.sim.animation.animator3d.Adapters.DrawMode.access$4(DrawMode.java:195)
	at com.geo.sim.animation.animator3d.Adapters.DrawMode$4.execute(DrawMode.java:155)
	at com.geo.sim.animation.animator3d.Controller.CommandManager.onKeyEvent(CommandManager.java:192)
	at com.jme3.input.InputManager.processQueue(InputManager.java:773)
	at com.jme3.input.InputManager.update(InputManager.java:851)
	at com.jme3.app.Application.update(Application.java:598)
	at com.jme3.app.SimpleApplication.update(SimpleApplication.java:233)
	at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:149)
	at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:182)
	at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:223)
	at java.lang.Thread.run(Thread.java:662)
AL lib: ReleaseALC: 1 device not closed

I’m starting to think that it’s impossible to import BitmapText

I love quoting myself… :-/

@pspeed said: BitmapText has problems and cannot be saved and loaded from JME capsules without some major changes.

booooooooooooooooooooooooooooo :S

okay so any way around this? I am thinking of implementing a way to export into an xml trace language that captures the text , position, color and size, and when importing read that xml trace. Any better approaches you can suggest?

Sigh… I’ll quote myself again.

@pspeed said: You could wrap BitmapText in another object to be able to save and load it because then you could delay creation until you knew the font. Then just delegate through the methods that you want to be able to call on it.

hahaah thanks! could you please send me a link to that post?

@homsi said: hahaah thanks! could you please send me a link to that post?

Are you joking? It’s three or four posts up in this thread.