Started implementing the JmeCloneable stuff for Spatial

and Mesh.  Still need to catch some of the outer subclasses of
Node and Geometry.  Nothing is hooked up or tested yet.
This commit is contained in:
Paul Speed 2016-03-25 04:31:10 -04:00
parent 911b4be868
commit 2bdb3de2f5
14 changed files with 827 additions and 545 deletions

View File

@ -123,7 +123,7 @@ public class StatsView extends Node implements Control, JmeCloneable {
}
@Override
public Object jmeClone() {
public StatsView jmeClone() {
throw new UnsupportedOperationException("Not yet implemented.");
}

View File

@ -33,6 +33,8 @@ package com.jme3.light;
import com.jme3.export.*;
import com.jme3.scene.Spatial;
import com.jme3.util.clone.Cloner;
import com.jme3.util.clone.JmeCloneable;
import com.jme3.util.SortUtil;
import java.io.IOException;
import java.util.*;
@ -43,7 +45,7 @@ import java.util.*;
*
* @author Kirill Vainer
*/
public final class LightList implements Iterable<Light>, Savable, Cloneable {
public final class LightList implements Iterable<Light>, Savable, Cloneable, JmeCloneable {
private Light[] list, tlist;
private float[] distToOwner;
@ -302,6 +304,24 @@ public final class LightList implements Iterable<Light>, Savable, Cloneable {
}
}
@Override
public LightList jmeClone() {
try{
LightList clone = (LightList)super.clone();
clone.tlist = null; // list used for sorting only
return clone;
}catch (CloneNotSupportedException ex){
throw new AssertionError();
}
}
@Override
public void cloneFields( Cloner cloner, Object original ) {
this.owner = cloner.clone(owner);
this.list = cloner.clone(list);
this.distToOwner = cloner.clone(distToOwner);
}
public void write(JmeExporter ex) throws IOException {
OutputCapsule oc = ex.getCapsule(this);
// oc.write(owner, "owner", null);

View File

@ -39,6 +39,7 @@ import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.export.OutputCapsule;
import com.jme3.export.binary.BinaryImporter;
import com.jme3.util.clone.Cloner;
import com.jme3.util.SafeArrayList;
import java.io.IOException;
import java.util.*;
@ -70,6 +71,18 @@ public class AssetLinkNode extends Node {
assetLoaderKeys.add(key);
}
/**
* Called internally by com.jme3.util.clone.Cloner. Do not call directly.
*/
@Override
public void cloneFields( Cloner cloner, Object original ) {
// This is a change in behavior because the old version did not clone
// this list... changes to one clone would be reflected in all.
// I think that's probably undesirable. -pspeed
this.assetLoaderKeys = cloner.clone(assetLoaderKeys);
this.assetChildren = new HashMap<ModelKey, Spatial>();
}
/**
* Add a "linked" child. These are loaded from the assetManager when the
* AssetLinkNode is loaded from a binary file.

View File

@ -48,6 +48,8 @@ import com.jme3.math.Vector3f;
import com.jme3.scene.mesh.IndexBuffer;
import com.jme3.util.SafeArrayList;
import com.jme3.util.TempVars;
import com.jme3.util.clone.Cloner;
import com.jme3.util.clone.JmeCloneable;
/**
* BatchNode holds geometries that are a batched version of all the geometries that are in its sub scenegraph.
@ -662,7 +664,7 @@ public class BatchNode extends GeometryGroupNode {
vars.release();
}
protected class Batch {
protected class Batch implements JmeCloneable {
/**
* update the batchesByGeom map for this batch with the given List of geometries
* @param list
@ -679,6 +681,21 @@ public class BatchNode extends GeometryGroupNode {
public final Geometry getGeometry() {
return geometry;
}
@Override
public Batch jmeClone() {
try {
return (Batch)super.clone();
} catch (CloneNotSupportedException ex) {
throw new AssertionError();
}
}
@Override
public void cloneFields( Cloner cloner, Object original ) {
this.geometry = cloner.clone(geometry);
}
}
protected void setNeedsFullRebatch(boolean needsFullRebatch) {
@ -705,6 +722,24 @@ public class BatchNode extends GeometryGroupNode {
return clone;
}
/**
* Called internally by com.jme3.util.clone.Cloner. Do not call directly.
*/
@Override
public void cloneFields( Cloner cloner, Object original ) {
this.batches = cloner.clone(batches);
this.tmpFloat = cloner.clone(tmpFloat);
this.tmpFloatN = cloner.clone(tmpFloatN);
this.tmpFloatT = cloner.clone(tmpFloatT);
HashMap<Geometry, Batch> newBatchesByGeom = new HashMap<Geometry, Batch>();
for( Map.Entry<Geometry, Batch> e : batchesByGeom.entrySet() ) {
newBatchesByGeom.put(cloner.clone(e.getKey()), cloner.clone(e.getValue()));
}
this.batchesByGeom = newBatchesByGeom;
}
@Override
public int collideWith(Collidable other, CollisionResults results) {
int total = 0;

View File

@ -36,6 +36,7 @@ import com.jme3.export.JmeImporter;
import com.jme3.renderer.Camera;
import com.jme3.scene.control.CameraControl;
import com.jme3.scene.control.CameraControl.ControlDirection;
import com.jme3.util.clone.Cloner;
import java.io.IOException;
/**
@ -94,6 +95,17 @@ public class CameraNode extends Node {
// camControl.getCamera().lookAt(position, upVector);
// }
/**
* Called internally by com.jme3.util.clone.Cloner. Do not call directly.
*/
@Override
public void cloneFields( Cloner cloner, Object original ) {
// A change in behavior... I think previously CameraNode was probably
// not really cloneable... or at least its camControl would be pointing
// to the wrong control. -pspeed
this.camControl = cloner.clone(camControl);
}
@Override
public void read(JmeImporter im) throws IOException {
super.read(im);

View File

@ -43,6 +43,7 @@ import com.jme3.material.Material;
import com.jme3.math.Matrix4f;
import com.jme3.renderer.Camera;
import com.jme3.scene.VertexBuffer.Type;
import com.jme3.util.clone.Cloner;
import com.jme3.util.TempVars;
import java.io.IOException;
import java.util.Queue;
@ -539,6 +540,16 @@ public class Geometry extends Spatial {
return geomClone;
}
/**
* Called internally by com.jme3.util.clone.Cloner. Do not call directly.
*/
@Override
public void cloneFields( Cloner cloner, Object original ) {
this.mesh = cloner.clone(mesh);
this.material = cloner.clone(material);
this.groupNode = cloner.clone(groupNode);
}
@Override
public void write(JmeExporter ex) throws IOException {
super.write(ex);

View File

@ -36,6 +36,7 @@ import com.jme3.export.JmeImporter;
import com.jme3.light.Light;
import com.jme3.scene.control.LightControl;
import com.jme3.scene.control.LightControl.ControlDirection;
import com.jme3.util.clone.Cloner;
import java.io.IOException;
/**
@ -94,6 +95,17 @@ public class LightNode extends Node {
return lightControl.getLight();
}
/**
* Called internally by com.jme3.util.clone.Cloner. Do not call directly.
*/
@Override
public void cloneFields( Cloner cloner, Object original ) {
// A change in behavior... I think previously LightNode was probably
// not really cloneable... or at least its lightControl would be pointing
// to the wrong control. -pspeed
this.lightControl = cloner.clone(lightControl);
}
@Override
public void read(JmeImporter im) throws IOException {
super.read(im);

View File

@ -51,6 +51,8 @@ import com.jme3.util.BufferUtils;
import com.jme3.util.IntMap;
import com.jme3.util.IntMap.Entry;
import com.jme3.util.SafeArrayList;
import com.jme3.util.clone.Cloner;
import com.jme3.util.clone.JmeCloneable;
import java.io.IOException;
import java.nio.*;
import java.util.ArrayList;
@ -72,7 +74,7 @@ import java.util.ArrayList;
*
* @author Kirill Vainer
*/
public class Mesh implements Savable, Cloneable {
public class Mesh implements Savable, Cloneable, JmeCloneable {
/**
* The mode of the Mesh specifies both the type of primitive represented
@ -299,6 +301,35 @@ public class Mesh implements Savable, Cloneable {
return clone;
}
/**
* Called internally by com.jme3.util.clone.Cloner. Do not call directly.
*/
@Override
public Mesh jmeClone() {
try {
return (Mesh)super.clone();
} catch (CloneNotSupportedException ex) {
throw new AssertionError();
}
}
/**
* Called internally by com.jme3.util.clone.Cloner. Do not call directly.
*/
@Override
public void cloneFields( Cloner cloner, Object original ) {
// Probably could clone this now but it will get regenerated anyway.
this.collisionTree = null;
this.meshBound = cloner.clone(meshBound);
this.buffersList = cloner.clone(buffersList);
this.buffers = cloner.clone(buffers);
this.lodLevels = cloner.clone(lodLevels);
this.elementLengths = cloner.clone(elementLengths);
this.modeStart = cloner.clone(modeStart);
}
/**
* Generates the {@link Type#BindPosePosition}, {@link Type#BindPoseNormal},
* and {@link Type#BindPoseTangent}

View File

@ -40,6 +40,7 @@ import com.jme3.export.Savable;
import com.jme3.material.Material;
import com.jme3.util.SafeArrayList;
import com.jme3.util.TempVars;
import com.jme3.util.clone.Cloner;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@ -707,6 +708,19 @@ public class Node extends Spatial {
return nodeClone;
}
/**
* Called internally by com.jme3.util.clone.Cloner. Do not call directly.
*/
@Override
public void cloneFields( Cloner cloner, Object original ) {
this.children = cloner.clone(children);
// Only the outer cloning thing knows whether this should be nulled
// or not... after all, we might be cloning a root node in which case
// cloning this list is fine.
this.updateList = cloner.clone(updateList);
}
@Override
public void write(JmeExporter e) throws IOException {
super.write(e);

View File

@ -47,6 +47,8 @@ import com.jme3.renderer.queue.RenderQueue;
import com.jme3.renderer.queue.RenderQueue.Bucket;
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
import com.jme3.scene.control.Control;
import com.jme3.util.clone.Cloner;
import com.jme3.util.clone.JmeCloneable;
import com.jme3.util.SafeArrayList;
import com.jme3.util.TempVars;
import java.io.IOException;
@ -63,7 +65,7 @@ import java.util.logging.Logger;
* @author Joshua Slack
* @version $Revision: 4075 $, $Data$
*/
public abstract class Spatial implements Savable, Cloneable, Collidable, CloneableSmartAsset {
public abstract class Spatial implements Savable, Cloneable, Collidable, CloneableSmartAsset, JmeCloneable {
private static final Logger logger = Logger.getLogger(Spatial.class.getName());
@ -1344,6 +1346,52 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
*/
public abstract Spatial deepClone();
/**
* Called internally by com.jme3.util.clone.Cloner. Do not call directly.
*/
@Override
public Spatial jmeClone() {
try {
Spatial clone = (Spatial)super.clone();
return clone;
} catch (CloneNotSupportedException ex) {
throw new AssertionError();
}
}
/**
* Called internally by com.jme3.util.clone.Cloner. Do not call directly.
*/
@Override
public void cloneFields( Cloner cloner, Object original ) {
// Clone all of the fields that need fix-ups and/or potential
// sharing.
this.parent = cloner.clone(parent);
this.worldBound = cloner.clone(worldBound);
this.worldLights = cloner.clone(worldLights);
this.localLights = cloner.clone(localLights);
this.worldTransform = cloner.clone(worldTransform);
this.localTransform = cloner.clone(localTransform);
this.controls = cloner.clone(controls);
// Cloner doesn't handle maps on its own just yet.
// Note: this is more advanced cloning than the old clone() method
// did because it just shallow cloned the map. In this case, we want
// to avoid all of the nasty cloneForSpatial() fixup style code that
// used to inject stuff into the clone's user data. By using cloner
// to clone the user data we get this automatically.
userData = (HashMap<String, Savable>)userData.clone();
for( Map.Entry<String, Savable> e : userData.entrySet() ) {
Savable value = e.getValue();
if( value instanceof Cloneable ) {
// Note: all JmeCloneable objects are also Cloneable so this
// catches both cases.
e.setValue(cloner.clone(value));
}
}
}
public void setUserData(String key, Object data) {
if (userData == null) {
userData = new HashMap<String, Savable>();

View File

@ -47,6 +47,7 @@ import com.jme3.scene.VertexBuffer.Type;
import com.jme3.scene.VertexBuffer.Usage;
import com.jme3.util.BufferUtils;
import com.jme3.util.TempVars;
import com.jme3.util.clone.Cloner;
import java.io.IOException;
import java.nio.FloatBuffer;
import java.util.ArrayList;
@ -343,6 +344,16 @@ public class InstancedGeometry extends Geometry {
return allData.toArray(new VertexBuffer[allData.size()]);
}
/**
* Called internally by com.jme3.util.clone.Cloner. Do not call directly.
*/
@Override
public void cloneFields( Cloner cloner, Object original ) {
this.globalInstanceData = cloner.clone(globalInstanceData);
this.transformInstanceData = cloner.clone(transformInstanceData);
this.geometries = cloner.clone(geometries);
}
@Override
public void write(JmeExporter exporter) throws IOException {
super.write(exporter);

View File

@ -48,6 +48,7 @@ import com.jme3.util.clone.Cloner;
import com.jme3.util.clone.JmeCloneable;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class InstancedNode extends GeometryGroupNode {
@ -59,7 +60,7 @@ public class InstancedNode extends GeometryGroupNode {
setGeometryStartIndex(geom, startIndex);
}
private static final class InstanceTypeKey implements Cloneable {
private static final class InstanceTypeKey implements Cloneable, JmeCloneable {
Mesh mesh;
Material material;
@ -106,6 +107,21 @@ public class InstancedNode extends GeometryGroupNode {
throw new AssertionError();
}
}
@Override
public Object jmeClone() {
try {
return super.clone();
} catch( CloneNotSupportedException e ) {
throw new AssertionError();
}
}
@Override
public void cloneFields( Cloner cloner, Object original ) {
this.mesh = cloner.clone(mesh);
this.material = cloner.clone(material);
}
}
private static class InstancedNodeControl implements Control, JmeCloneable {
@ -329,6 +345,27 @@ public class InstancedNode extends GeometryGroupNode {
return clone;
}
/**
* Called internally by com.jme3.util.clone.Cloner. Do not call directly.
*/
@Override
public void cloneFields( Cloner cloner, Object original ) {
this.control = cloner.clone(control);
this.lookUp = cloner.clone(lookUp);
HashMap<Geometry, InstancedGeometry> newIgByGeom = new HashMap<Geometry, InstancedGeometry>();
for( Map.Entry<Geometry, InstancedGeometry> e : igByGeom.entrySet() ) {
newIgByGeom.put(cloner.clone(e.getKey()), cloner.clone(e.getValue()));
}
this.igByGeom = newIgByGeom;
HashMap<InstanceTypeKey, InstancedGeometry> newInstancesMap = new HashMap<InstanceTypeKey, InstancedGeometry>();
for( Map.Entry<InstanceTypeKey, InstancedGeometry> e : instancesMap.entrySet() ) {
newInstancesMap.put(cloner.clone(e.getKey()), cloner.clone(e.getValue()));
}
this.instancesMap = newInstancesMap;
}
@Override
public void onTransformChange(Geometry geom) {
// Handled automatically

View File

@ -32,6 +32,8 @@
package com.jme3.util;
import com.jme3.util.IntMap.Entry;
import com.jme3.util.clone.Cloner;
import com.jme3.util.clone.JmeCloneable;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
@ -43,7 +45,7 @@ import java.util.NoSuchElementException;
*
* @author Nate
*/
public final class IntMap<T> implements Iterable<Entry<T>>, Cloneable {
public final class IntMap<T> implements Iterable<Entry<T>>, Cloneable, JmeCloneable {
private Entry[] table;
private final float loadFactor;
@ -93,6 +95,26 @@ public final class IntMap<T> implements Iterable<Entry<T>>, Cloneable {
return null;
}
/**
* Called internally by com.jme3.util.clone.Cloner. Do not call directly.
*/
@Override
public Object jmeClone() {
try {
return super.clone();
} catch (CloneNotSupportedException ex) {
throw new AssertionError();
}
}
/**
* Called internally by com.jme3.util.clone.Cloner. Do not call directly.
*/
@Override
public void cloneFields( Cloner cloner, Object original ) {
this.table = cloner.clone(table);
}
public boolean containsValue(Object value) {
Entry[] table = this.table;
for (int i = table.length; i-- > 0;){
@ -268,7 +290,7 @@ public final class IntMap<T> implements Iterable<Entry<T>>, Cloneable {
}
public static final class Entry<T> implements Cloneable {
public static final class Entry<T> implements Cloneable, JmeCloneable {
final int key;
T value;
@ -303,5 +325,20 @@ public final class IntMap<T> implements Iterable<Entry<T>>, Cloneable {
}
return null;
}
@Override
public Object jmeClone() {
try {
return super.clone();
} catch (CloneNotSupportedException ex) {
throw new AssertionError();
}
}
@Override
public void cloneFields( Cloner cloner, Object original ) {
this.value = cloner.clone(value);
this.next = cloner.clone(next);
}
}
}

View File

@ -1,11 +1,12 @@
# THIS IS AN AUTO-GENERATED FILE..
# DO NOT MODIFY!
build.date=1900-01-01
build.date=2016-03-25
git.revision=0
git.branch=unknown
git.hash=
git.hash.short=
git.tag=
name.full=jMonkeyEngine 3.1.0-UNKNOWN
version.full=3.1.0-UNKNOWN
version.number=3.1.0
version.tag=SNAPSHOT