Skip to content

Commit 01fbd16

Browse files
committed
test case and solution for issue #1548 (MorphControl doesn't override methods) (#1549)
* TestMorph: test cloning and serialization * solve issue #1548 (MorphControl doesn't override methods)
1 parent 51d0388 commit 01fbd16

File tree

2 files changed

+90
-5
lines changed

2 files changed

+90
-5
lines changed

jme3-core/src/main/java/com/jme3/anim/MorphControl.java

+75-4
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@
3131
*/
3232
package com.jme3.anim;
3333

34+
import com.jme3.export.InputCapsule;
35+
import com.jme3.export.JmeExporter;
36+
import com.jme3.export.JmeImporter;
37+
import com.jme3.export.OutputCapsule;
3438
import com.jme3.export.Savable;
3539
import com.jme3.material.*;
3640
import com.jme3.renderer.*;
@@ -40,7 +44,8 @@
4044
import com.jme3.shader.VarType;
4145
import com.jme3.util.BufferUtils;
4246
import com.jme3.util.SafeArrayList;
43-
47+
import com.jme3.util.clone.Cloner;
48+
import java.io.IOException;
4449
import java.nio.FloatBuffer;
4550
import java.util.logging.Level;
4651
import java.util.logging.Logger;
@@ -59,11 +64,13 @@ public class MorphControl extends AbstractControl implements Savable {
5964
private static final int MAX_MORPH_BUFFERS = 14;
6065
private final static float MIN_WEIGHT = 0.005f;
6166

62-
final private SafeArrayList<Geometry> targets = new SafeArrayList<>(Geometry.class);
63-
final private TargetLocator targetLocator = new TargetLocator();
67+
private static final String TAG_APPROXIMATE = "approximateTangents";
68+
69+
private SafeArrayList<Geometry> targets = new SafeArrayList<>(Geometry.class);
70+
private TargetLocator targetLocator = new TargetLocator();
6471

6572
private boolean approximateTangents = true;
66-
final private MatParamOverride nullNumberOfBones = new MatParamOverride(VarType.Int, "NumberOfBones", null);
73+
private MatParamOverride nullNumberOfBones = new MatParamOverride(VarType.Int, "NumberOfBones", null);
6774

6875
private float[] tmpPosArray;
6976
private float[] tmpNormArray;
@@ -373,6 +380,70 @@ public boolean isApproximateTangents() {
373380
return approximateTangents;
374381
}
375382

383+
/**
384+
* Callback from {@link com.jme3.util.clone.Cloner} to convert this
385+
* shallow-cloned Control into a deep-cloned one, using the specified Cloner
386+
* and original to resolve copied fields.
387+
*
388+
* @param cloner the Cloner that's cloning this Control (not null, modified)
389+
* @param original the instance from which this Control was shallow-cloned
390+
* (not null, unaffected)
391+
*/
392+
@Override
393+
public void cloneFields(Cloner cloner, Object original) {
394+
super.cloneFields(cloner, original);
395+
396+
targets = cloner.clone(targets);
397+
targetLocator = new TargetLocator();
398+
nullNumberOfBones = cloner.clone(nullNumberOfBones);
399+
tmpPosArray = null;
400+
tmpNormArray = null;
401+
tmpTanArray = null;
402+
}
403+
404+
/**
405+
* Create a shallow clone for the JME cloner.
406+
*
407+
* @return a new instance
408+
*/
409+
@Override
410+
public MorphControl jmeClone() {
411+
try {
412+
MorphControl clone = (MorphControl) super.clone();
413+
return clone;
414+
} catch (CloneNotSupportedException exception) {
415+
throw new RuntimeException(exception);
416+
}
417+
}
418+
419+
/**
420+
* De-serialize this Control from the specified importer, for example when
421+
* loading from a J3O file.
422+
*
423+
* @param importer (not null)
424+
* @throws IOException from the importer
425+
*/
426+
@Override
427+
public void read(JmeImporter importer) throws IOException {
428+
super.read(importer);
429+
InputCapsule capsule = importer.getCapsule(this);
430+
approximateTangents = capsule.readBoolean(TAG_APPROXIMATE, true);
431+
}
432+
433+
/**
434+
* Serialize this Control to the specified exporter, for example when saving
435+
* to a J3O file.
436+
*
437+
* @param exporter (not null)
438+
* @throws IOException from the exporter
439+
*/
440+
@Override
441+
public void write(JmeExporter exporter) throws IOException {
442+
super.write(exporter);
443+
OutputCapsule capsule = exporter.getCapsule(this);
444+
capsule.write(approximateTangents, TAG_APPROXIMATE, true);
445+
}
446+
376447
private class TargetLocator extends SceneGraphVisitorAdapter {
377448
@Override
378449
public void visit(Geometry geom) {

jme3-examples/src/main/java/jme3test/model/anim/TestMorph.java

+15-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.jme3.anim.MorphControl;
44
import com.jme3.app.ChaseCameraAppState;
55
import com.jme3.app.SimpleApplication;
6+
import com.jme3.export.binary.BinaryExporter;
67
import com.jme3.font.BitmapFont;
78
import com.jme3.font.BitmapText;
89
import com.jme3.input.KeyInput;
@@ -16,7 +17,7 @@
1617
import com.jme3.scene.mesh.MorphTarget;
1718
import com.jme3.scene.shape.Box;
1819
import com.jme3.util.BufferUtils;
19-
20+
import com.jme3.util.clone.Cloner;
2021
import java.nio.FloatBuffer;
2122

2223
public class TestMorph extends SimpleApplication {
@@ -90,6 +91,19 @@ public void simpleInitApp() {
9091

9192
g.setMorphState(weights);
9293
g.addControl(new MorphControl());
94+
/*
95+
* Attach a clone of the morphing box model, in order to test cloning.
96+
*/
97+
Geometry g2 = Cloner.deepClone(g);
98+
g2.move(-4f, 0f, 0f);
99+
rootNode.attachChild(g2);
100+
/*
101+
* Attach a saveAndLoad() copy of the morphing box model,
102+
* in order to test serialization.
103+
*/
104+
Geometry g3 = BinaryExporter.saveAndLoad(assetManager, g);
105+
g3.move(-4f, 4f, 0f);
106+
rootNode.attachChild(g3);
93107

94108
ChaseCameraAppState chase = new ChaseCameraAppState();
95109
chase.setTarget(rootNode);

0 commit comments

Comments
 (0)