Hi folks,
I`d like to save a custom Control that extends AbstractControl. But when i try to Load it the Game outputs a RuntimeException. I have no Idea, what the problem could be.
I reproduced the Problem in a simple TestCase. You can find the code and output below.
Main.java:
package mygame;
import com.jme3.app.SimpleApplication;
import com.jme3.asset.plugins.FileLocator;
import com.jme3.export.binary.BinaryExporter;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.shape.Box;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Main extends SimpleApplication {
public static void main(String[] args) {
Main app = new Main();
app.start();
}
@Override
public void simpleInitApp() {
Box b = new Box(1, 1, 1);
Geometry boxGeometry = new Geometry("Box", b);
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", ColorRGBA.Blue);
boxGeometry.setMaterial(mat);
RotationControl rotationControl = new RotationControl();
boxGeometry.addControl(rotationControl);
Node sceneNode = new Node("sceneNode");
sceneNode.attachChild(boxGeometry);
rootNode.attachChild(sceneNode);
save(System.getProperty("user.home")+"\\Models\\someRandomNameThatIsNotOccupiedByAnyOtherFile_th45a6t4h.j3o");
load(System.getProperty("user.home")+"\\Models\\","someRandomNameThatIsNotOccupiedByAnyOtherFile_th45a6t4h.j3o");
}
@Override
public void simpleUpdate(float tpf) {
}
@Override
public void simpleRender(RenderManager rm) {
}
public boolean save(String filePath){
BinaryExporter exporter = BinaryExporter.getInstance();
File file = new File(filePath);
try {
exporter.save(rootNode.getChild("sceneNode"), file);
}
catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, "Error: Failed to save game!", ex);
return false;
}
return true;
}
public boolean load(String parentPath, String fileName){
assetManager.registerLocator(parentPath, FileLocator.class);
rootNode.detachAllChildren();
Node sceneNode = (Node) assetManager.loadModel(fileName);
rootNode.attachChild(sceneNode);
return true;
}
}
RotationControl.java:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package mygame;
import com.jme3.export.InputCapsule;
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.export.OutputCapsule;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.control.AbstractControl;
import java.io.IOException;
public class RotationControl extends AbstractControl {
private String someString="someText";
@Override
protected void controlUpdate(float tpf) {
spatial.rotate(new Quaternion().fromAngleAxis(tpf*0.1f, Vector3f.UNIT_Y));
}
@Override
protected void controlRender(RenderManager rm, ViewPort vp) {
//throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public void write(JmeExporter ex) throws IOException{
OutputCapsule capsule = ex.getCapsule(this);
capsule.write(someString, "someString", "");
someString = null;
System.out.println("Saved");
}
@Override
public void read(JmeImporter im) throws IOException{
InputCapsule capsule = im.getCapsule(this);
someString= capsule.readString("someString", "");
System.out.println("Loaded");
}
}
Output:
run:
Sep 06, 2015 10:07:33 PM java.util.prefs.WindowsPreferences <init>
Warnung: Could not open/create prefs root node Software\JavaSoft\Prefs at root 0x80000002. Windows RegCreateKeyEx(...) returned error code 5.
Sep 06, 2015 10:07:35 PM com.jme3.system.JmeDesktopSystem initialize
Information: Running on jMonkeyEngine 3.0.10
Sep 06, 2015 10:07:35 PM com.jme3.system.Natives extractNativeLibs
Information: Extraction Directory: C:\[...]\SaveLoadTestCase
Sep 06, 2015 10:07:36 PM com.jme3.system.lwjgl.LwjglContext printContextInitInfo
Information: Lwjgl 2.9.0 context running on thread LWJGL Renderer Thread
Sep 06, 2015 10:07:36 PM com.jme3.system.lwjgl.LwjglContext printContextInitInfo
Information: Adapter: igdumdim64
Sep 06, 2015 10:07:36 PM com.jme3.system.lwjgl.LwjglContext printContextInitInfo
Information: Driver Version: 10.18.10.4252
Sep 06, 2015 10:07:36 PM com.jme3.system.lwjgl.LwjglContext printContextInitInfo
Information: Vendor: Intel
Sep 06, 2015 10:07:36 PM com.jme3.system.lwjgl.LwjglContext printContextInitInfo
Information: OpenGL Version: 4.0.0 - Build 10.18.10.4252
Sep 06, 2015 10:07:36 PM com.jme3.system.lwjgl.LwjglContext printContextInitInfo
Information: Renderer: Intel(R) HD Graphics 4000
Sep 06, 2015 10:07:36 PM com.jme3.system.lwjgl.LwjglContext printContextInitInfo
Information: GLSL Ver: 4.00 - Build 10.18.10.4252
Sep 06, 2015 10:07:36 PM com.jme3.asset.AssetConfig loadText
Warnung: Cannot find loader com.jme3.scene.plugins.blender.BlenderModelLoader
WARNING: Found unknown Windows version: Windows 8
Attempting to use default windows plug-in.
Loading: net.java.games.input.DirectAndRawInputEnvironmentPlugin
Sep 06, 2015 10:07:36 PM com.jme3.audio.lwjgl.LwjglAudioRenderer initInThread
Information: Audio Device: OpenAL Soft
Sep 06, 2015 10:07:36 PM com.jme3.audio.lwjgl.LwjglAudioRenderer initInThread
Information: Audio Vendor: OpenAL Community
Sep 06, 2015 10:07:36 PM com.jme3.audio.lwjgl.LwjglAudioRenderer initInThread
Information: Audio Renderer: OpenAL Soft
Sep 06, 2015 10:07:36 PM com.jme3.audio.lwjgl.LwjglAudioRenderer initInThread
Information: Audio Version: 1.1 ALSOFT 1.15.1
Sep 06, 2015 10:07:36 PM com.jme3.audio.lwjgl.LwjglAudioRenderer initInThread
Information: AudioRenderer supports 64 channels
Sep 06, 2015 10:07:36 PM com.jme3.audio.lwjgl.LwjglAudioRenderer initInThread
Information: Audio effect extension version: 1.0
Sep 06, 2015 10:07:36 PM com.jme3.audio.lwjgl.LwjglAudioRenderer initInThread
Information: Audio max auxilary sends: 4
Saved
Loaded
Sep 06, 2015 10:07:37 PM com.jme3.app.Application handleError
Schwerwiegend: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
java.lang.RuntimeException: Can't clone control for spatial
at com.jme3.scene.control.AbstractControl.cloneForSpatial(AbstractControl.java:104)
at com.jme3.scene.Spatial.clone(Spatial.java:1185)
at com.jme3.scene.Geometry.clone(Geometry.java:440)
at com.jme3.scene.Geometry.clone(Geometry.java:60)
at com.jme3.scene.Spatial.clone(Spatial.java:1172)
at com.jme3.scene.Node.clone(Node.java:565)
at com.jme3.scene.Node.clone(Node.java:60)
at com.jme3.scene.Spatial.clone(Spatial.java:1214)
at com.jme3.scene.Spatial.clone(Spatial.java:66)
at com.jme3.asset.CloneableAssetProcessor.createClone(CloneableAssetProcessor.java:48)
at com.jme3.asset.DesktopAssetManager.loadAsset(DesktopAssetManager.java:327)
at com.jme3.asset.DesktopAssetManager.loadModel(DesktopAssetManager.java:374)
at com.jme3.asset.DesktopAssetManager.loadModel(DesktopAssetManager.java:378)
at mygame.Main.load(Main.java:73)
at mygame.Main.simpleInitApp(Main.java:44)
at com.jme3.app.SimpleApplication.initialize(SimpleApplication.java:226)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.initInThread(LwjglAbstractDisplay.java:130)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:207)
at java.lang.Thread.run(Thread.java:744)
Caused by: java.lang.CloneNotSupportedException: mygame.RotationControl
at java.lang.Object.clone(Native Method)
at com.jme3.scene.control.AbstractControl.cloneForSpatial(AbstractControl.java:99)
... 18 more
BUILD SUCCESSFUL (total time: 7 seconds)