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
68 changes: 65 additions & 3 deletions jme3-core/src/main/java/com/jme3/anim/AnimClip.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2009-2020 jMonkeyEngine
* Copyright (c) 2009-2021 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -38,6 +38,8 @@
import java.io.IOException;

/**
* A named set of animation tracks that can be played in synchrony.
*
* Created by Nehon on 20/12/2017.
*/
public class AnimClip implements JmeCloneable, Savable {
Expand All @@ -47,13 +49,27 @@ public class AnimClip implements JmeCloneable, Savable {

private AnimTrack[] tracks;

/**
* No-argument constructor needed by SavableClassUtil.
*/
protected AnimClip() {
}

/**
* Instantiate a zero-length clip with the specified name.
*
* @param name desired name for the new clip
*/
public AnimClip(String name) {
this.name = name;
}

/**
* Replace all tracks in this clip. This method may increase the clip's
* length, but it will never reduce it.
*
* @param tracks the tracks to use (alias created)
*/
public void setTracks(AnimTrack[] tracks) {
this.tracks = tracks;
for (AnimTrack track : tracks) {
Expand All @@ -63,20 +79,38 @@ public void setTracks(AnimTrack[] tracks) {
}
}

/**
* Determine the name of this clip.
*
* @return the name
*/
public String getName() {
return name;
}


/**
* Determine the duration of this clip.
*
* @return the duration (in seconds)
*/
public double getLength() {
return length;
}


/**
* Access all the tracks in this clip.
*
* @return the pre-existing array
*/
public AnimTrack[] getTracks() {
return tracks;
}

/**
* Create a shallow clone for the JME cloner.
*
* @return a new instance
*/
@Override
public Object jmeClone() {
try {
Expand All @@ -86,6 +120,15 @@ public Object jmeClone() {
}
}

/**
* Callback from {@link com.jme3.util.clone.Cloner} to convert this
* shallow-cloned clip into a deep-cloned one, using the specified Cloner
* and original to resolve copied fields.
*
* @param cloner the Cloner that's cloning this clip (not null)
* @param original the instance from which this clip was shallow-cloned (not
* null, unaffected)
*/
@Override
public void cloneFields(Cloner cloner, Object original) {
AnimTrack[] newTracks = new AnimTrack[tracks.length];
Expand All @@ -95,11 +138,23 @@ public void cloneFields(Cloner cloner, Object original) {
this.tracks = newTracks;
}

/**
* Represent this clip as a String.
*
* @return a descriptive string of text (not null, not empty)
*/
@Override
public String toString() {
return "Clip " + name + ", " + length + 's';
}

/**
* Serialize this clip to the specified exporter, for example when saving to
* a J3O file.
*
* @param ex the exporter to write to (not null)
* @throws IOException from the exporter
*/
@Override
public void write(JmeExporter ex) throws IOException {
OutputCapsule oc = ex.getCapsule(this);
Expand All @@ -108,6 +163,13 @@ public void write(JmeExporter ex) throws IOException {

}

/**
* De-serialize this clip from the specified importer, for example when
* loading from a J3O file.
*
* @param im the importer to read from (not null)
* @throws IOException from the importer
*/
@Override
public void read(JmeImporter im) throws IOException {
InputCapsule ic = im.getCapsule(this);
Expand Down
61 changes: 61 additions & 0 deletions jme3-core/src/main/java/com/jme3/anim/AnimComposer.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ public class AnimComposer extends AbstractControl {
private float globalSpeed = 1f;
private Map<String, Layer> layers = new LinkedHashMap<>();

/**
* Instantiate a composer with a single layer, no actions, and no clips.
*/
public AnimComposer() {
layers.put(DEFAULT_LAYER, new Layer(this));
}
Expand Down Expand Up @@ -314,6 +317,12 @@ public Action removeAction(String name) {
return actions.remove(name);
}

/**
* Add a layer to this composer.
*
* @param name the desired name for the new layer
* @param mask the desired mask for the new layer (alias created)
*/
public void makeLayer(String name, AnimationMask mask) {
Layer l = new Layer(this);
l.mask = mask;
Expand Down Expand Up @@ -363,6 +372,9 @@ public BlendAction actionBlended(String name, BlendSpace blendSpace, String... c
return action;
}

/**
* Reset all layers to t=0 with no current action.
*/
public void reset() {
for (Layer layer : layers.values()) {
layer.currentAction = null;
Expand Down Expand Up @@ -391,6 +403,11 @@ public Set<String> getAnimClipsNames() {
return Collections.unmodifiableSet(animClipMap.keySet());
}

/**
* used internally
*
* @param tpf time per frame (in seconds)
*/
@Override
protected void controlUpdate(float tpf) {
for (Layer layer : layers.values()) {
Expand All @@ -410,19 +427,40 @@ protected void controlUpdate(float tpf) {
}
}

/**
* used internally
*
* @param rm the RenderManager rendering the controlled Spatial (not null)
* @param vp the ViewPort being rendered (not null)
*/
@Override
protected void controlRender(RenderManager rm, ViewPort vp) {

}

/**
* Determine the global speed applied to all layers.
*
* @return the speed factor (1=normal speed)
*/
public float getGlobalSpeed() {
return globalSpeed;
}

/**
* Alter the global speed applied to all layers.
*
* @param globalSpeed the desired speed factor (1=normal speed, default=1)
*/
public void setGlobalSpeed(float globalSpeed) {
this.globalSpeed = globalSpeed;
}

/**
* Create a shallow clone for the JME cloner.
*
* @return a new instance
*/
@Override
public Object jmeClone() {
try {
Expand All @@ -433,6 +471,15 @@ public Object jmeClone() {
}
}

/**
* Callback from {@link com.jme3.util.clone.Cloner} to convert this
* shallow-cloned composer into a deep-cloned one, using the specified
* Cloner and original to resolve copied fields.
*
* @param cloner the Cloner that's cloning this composer (not null)
* @param original the instance from which this composer was shallow-cloned
* (not null, unaffected)
*/
@Override
public void cloneFields(Cloner cloner, Object original) {
super.cloneFields(cloner, original);
Expand All @@ -456,6 +503,13 @@ public void cloneFields(Cloner cloner, Object original) {

}

/**
* De-serialize this composer from the specified importer, for example when
* loading from a J3O file.
*
* @param im the importer to use (not null)
* @throws IOException from the importer
*/
@Override
@SuppressWarnings("unchecked")
public void read(JmeImporter im) throws IOException {
Expand All @@ -465,6 +519,13 @@ public void read(JmeImporter im) throws IOException {
globalSpeed = ic.readFloat("globalSpeed", 1f);
}

/**
* Serialize this composer to the specified exporter, for example when
* saving to a J3O file.
*
* @param ex the exporter to use (not null)
* @throws IOException from the exporter
*/
@Override
public void write(JmeExporter ex) throws IOException {
super.write(ex);
Expand Down
19 changes: 17 additions & 2 deletions jme3-core/src/main/java/com/jme3/anim/AnimTrack.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,25 @@
import com.jme3.export.Savable;
import com.jme3.util.clone.JmeCloneable;

/**
* Interface to derive animation data from a track.
*
* @param <T> the type of data that's being animated, such as Transform
*/
public interface AnimTrack<T> extends Savable, JmeCloneable {

/**
* Determine the track value for the specified time.
*
* @param time the track time (in seconds)
* @param store storage for the value (not null, modified)
*/
public void getDataAtTime(double time, T store);
public double getLength();


/**
* Determine the duration of the track.
*
* @return the duration (in seconds, &ge;0)
*/
public double getLength();
}
8 changes: 7 additions & 1 deletion jme3-core/src/main/java/com/jme3/anim/AnimationMask.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2009-2020 jMonkeyEngine
* Copyright (c) 2009-2021 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -38,6 +38,12 @@
*/
public interface AnimationMask {

/**
* Test whether the animation should applied to the specified element.
*
* @param target the target element
* @return true if animation should be applied, otherwise false
*/
boolean contains(Object target);

}
20 changes: 19 additions & 1 deletion jme3-core/src/main/java/com/jme3/anim/Armature.java
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,11 @@ public Joint[] getRoots() {
return rootJoints;
}

/**
* Access all joints in this Armature.
*
* @return a new list of pre-existing joints
*/
public List<Joint> getJointList() {
return Arrays.asList(jointList);
}
Expand Down Expand Up @@ -290,7 +295,13 @@ public void cloneFields(Cloner cloner, Object original) {
}
}


/**
* De-serialize this Armature from the specified importer, for example when
* loading from a J3O file.
*
* @param im the importer to read from (not null)
* @throws IOException from the importer
*/
@Override
@SuppressWarnings("unchecked")
public void read(JmeImporter im) throws IOException {
Expand Down Expand Up @@ -324,6 +335,13 @@ public void read(JmeImporter im) throws IOException {
applyInitialPose();
}

/**
* Serialize this Armature to the specified exporter, for example when
* saving to a J3O file.
*
* @param ex the exporter to write to (not null)
* @throws IOException from the exporter
*/
@Override
public void write(JmeExporter ex) throws IOException {
OutputCapsule output = ex.getCapsule(this);
Expand Down
18 changes: 18 additions & 0 deletions jme3-core/src/main/java/com/jme3/anim/ArmatureMask.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import java.util.BitSet;

/**
* An AnimationMask to select joints from a single Armature.
*/
public class ArmatureMask implements AnimationMask {

final private BitSet affectedJoints = new BitSet();
Expand Down Expand Up @@ -62,12 +65,27 @@ public boolean contains(Object target) {
return affectedJoints.get(((Joint) target).getId());
}

/**
* Create an ArmatureMask that selects the named Joint and all its
* descendants.
*
* @param armature the Armature containing the joints (not null)
* @param fromJoint the name of the ancestor joint
* @return a new mask
*/
public static ArmatureMask createMask(Armature armature, String fromJoint) {
ArmatureMask mask = new ArmatureMask();
mask.addFromJoint(armature, fromJoint);
return mask;
}

/**
* Create an ArmatureMask that selects the named joints.
*
* @param armature the Armature containing the joints (not null)
* @param joints the names of the joints to be included
* @return a new mask
*/
public static ArmatureMask createMask(Armature armature, String... joints) {
ArmatureMask mask = new ArmatureMask();
mask.addBones(armature, joints);
Expand Down
Loading