Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 38 additions & 2 deletions jme3-core/src/main/java/com/jme3/cinematic/MotionPath.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2009-2021 jMonkeyEngine
* Copyright (c) 2009-2025 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -45,6 +45,8 @@
import com.jme3.scene.shape.Box;
import com.jme3.scene.shape.Curve;
import com.jme3.util.TempVars;
import com.jme3.util.clone.Cloner;
import com.jme3.util.clone.JmeCloneable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
Expand All @@ -54,7 +56,7 @@
* Motion path is used to create a path between way points.
* @author Nehon
*/
public class MotionPath implements Savable {
public class MotionPath implements JmeCloneable, Savable {

private Node debugNode;
private AssetManager assetManager;
Expand Down Expand Up @@ -177,6 +179,40 @@ public void read(JmeImporter im) throws IOException {
spline = (Spline) in.readSavable("spline", null);
}

/**
* Callback from {@link com.jme3.util.clone.Cloner} to convert this
* shallow-cloned MotionPath into a deep-cloned one, using the specified
* cloner and original to resolve copied fields.
*
* @param cloner the cloner that's cloning this MotionPath (not null)
* @param original the object from which this MotionPath was shallow-cloned
* (not null, unaffected)
*/
@Override
public void cloneFields(Cloner cloner, Object original) {
this.debugNode = cloner.clone(debugNode);
this.spline = cloner.clone(spline);
/*
* The clone will share both the asset manager and the list of listeners
* of the original MotionPath.
*/
}

/**
* Creates a shallow clone for the JME cloner.
*
* @return a new object
*/
@Override
public MotionPath jmeClone() {
try {
MotionPath clone = (MotionPath) clone();
return clone;
} catch (CloneNotSupportedException exception) {
throw new RuntimeException(exception);
}
}

/**
* compute the index of the waypoint and the interpolation value according to a distance
* returns a vector 2 containing the index in the x field and the interpolation value in the y field
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2009-2021 jMonkeyEngine
* Copyright (c) 2009-2025 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -312,6 +312,9 @@ public Object jmeClone() {

@Override
public void cloneFields(Cloner cloner, Object original) {
this.lookAt = cloner.clone(lookAt);
this.path = cloner.clone(path);
this.rotation = cloner.clone(rotation);
this.spatial = cloner.clone(spatial);
}

Expand Down
41 changes: 40 additions & 1 deletion jme3-core/src/main/java/com/jme3/math/Spline.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
package com.jme3.math;

import com.jme3.export.*;
import com.jme3.util.clone.Cloner;
import com.jme3.util.clone.JmeCloneable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
Expand All @@ -41,7 +43,7 @@
*
* @author Nehon
*/
public class Spline implements Savable {
public class Spline implements JmeCloneable, Savable {

public enum SplineType {
Linear,
Expand Down Expand Up @@ -536,4 +538,41 @@ public void read(JmeImporter im) throws IOException {
weights = in.readFloatArray("weights", null);
basisFunctionDegree = in.readInt("basisFunctionDegree", 0);
}

/**
* Callback from {@link com.jme3.util.clone.Cloner} to convert this
* shallow-cloned spline into a deep-cloned one, using the specified cloner
* and original to resolve copied fields.
*
* @param cloner the cloner that's cloning this spline (not null)
* @param original the object from which this spline was shallow-cloned (not
* null, unaffected)
*/
@Override
public void cloneFields(Cloner cloner, Object original) {
this.controlPoints = cloner.clone(controlPoints);
if (segmentsLength != null) {
this.segmentsLength = new ArrayList<>(segmentsLength);
}
this.CRcontrolPoints = cloner.clone(CRcontrolPoints);
if (knots != null) {
this.knots = new ArrayList<>(knots);
}
this.weights = cloner.clone(weights);
}

/**
* Creates a shallow clone for the JME cloner.
*
* @return a new object
*/
@Override
public Spline jmeClone() {
try {
Spline clone = (Spline) clone();
return clone;
} catch (CloneNotSupportedException exception) {
throw new RuntimeException(exception);
}
}
}
75 changes: 75 additions & 0 deletions jme3-core/src/test/java/com/jme3/cinematic/MotionPathTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright (c) 2025 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme3.cinematic;

import com.jme3.math.Vector3f;
import com.jme3.util.clone.Cloner;
import org.junit.Assert;
import org.junit.Test;

/**
* Verifies that the {@link MotionPath} class works.
*
* @author Stephen Gold
*/
public class MotionPathTest {

/**
* Verifies that MotionPath cloning works.
*/
@Test
public void cloneMotionPath() {
MotionPath original = new MotionPath();
original.setCycle(true);
original.addWayPoint(new Vector3f(20, 3, 0));
original.addWayPoint(new Vector3f(0, 3, 20));
original.addWayPoint(new Vector3f(-20, 3, 0));
original.addWayPoint(new Vector3f(0, 3, -20));
original.setCurveTension(0.83f);

MotionPath clone = Cloner.deepClone(original);

// Verify that the clone is non-null and distinct from the original:
Assert.assertNotNull(clone);
Assert.assertTrue(clone != original);

// Compare the return values of various getters:
Assert.assertEquals(
clone.getCurveTension(), original.getCurveTension(), 0f);
Assert.assertEquals(clone.getLength(), original.getLength(), 0f);
Assert.assertEquals(clone.getNbWayPoints(), original.getNbWayPoints());
Assert.assertEquals(
clone.getPathSplineType(), original.getPathSplineType());
Assert.assertEquals(clone.getWayPoint(0), original.getWayPoint(0));
Assert.assertEquals(clone.isCycle(), original.isCycle());
}
}
Loading