parent
a8845a1506
commit
ce88350abf
@ -1,87 +0,0 @@ |
|||||||
package com.jme3.anim.tween; |
|
||||||
|
|
||||||
import com.jme3.anim.AnimClip; |
|
||||||
import com.jme3.anim.TransformTrack; |
|
||||||
import com.jme3.anim.tween.action.Action; |
|
||||||
import com.jme3.anim.util.HasLocalTransform; |
|
||||||
import com.jme3.anim.util.Weighted; |
|
||||||
import com.jme3.export.InputCapsule; |
|
||||||
import com.jme3.export.JmeExporter; |
|
||||||
import com.jme3.export.JmeImporter; |
|
||||||
import com.jme3.export.OutputCapsule; |
|
||||||
import com.jme3.math.Transform; |
|
||||||
import com.jme3.util.clone.Cloner; |
|
||||||
import com.jme3.util.clone.JmeCloneable; |
|
||||||
|
|
||||||
import java.io.IOException; |
|
||||||
|
|
||||||
public class AnimClipTween implements Tween, Weighted, JmeCloneable { |
|
||||||
|
|
||||||
private AnimClip clip; |
|
||||||
private Transform transform = new Transform(); |
|
||||||
private float weight = 1f; |
|
||||||
private Action parentAction; |
|
||||||
|
|
||||||
public AnimClipTween() { |
|
||||||
} |
|
||||||
|
|
||||||
public AnimClipTween(AnimClip clip) { |
|
||||||
this.clip = clip; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public double getLength() { |
|
||||||
return clip.getLength(); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean interpolate(double t) { |
|
||||||
// Sanity check the inputs
|
|
||||||
if (t < 0) { |
|
||||||
return true; |
|
||||||
} |
|
||||||
if (parentAction != null) { |
|
||||||
weight = parentAction.getWeightForTween(this); |
|
||||||
} |
|
||||||
if (weight == 0) { |
|
||||||
//weight is 0 let's not interpolate
|
|
||||||
return t < clip.getLength(); |
|
||||||
} |
|
||||||
TransformTrack[] tracks = clip.getTracks(); |
|
||||||
for (TransformTrack track : tracks) { |
|
||||||
HasLocalTransform target = track.getTarget(); |
|
||||||
transform.set(target.getLocalTransform()); |
|
||||||
track.getTransformAtTime(t, transform); |
|
||||||
|
|
||||||
if (weight == 1f) { |
|
||||||
target.setLocalTransform(transform); |
|
||||||
} else { |
|
||||||
Transform tr = target.getLocalTransform(); |
|
||||||
tr.interpolateTransforms(tr, transform, weight); |
|
||||||
target.setLocalTransform(tr); |
|
||||||
} |
|
||||||
} |
|
||||||
return t < clip.getLength(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public Object jmeClone() { |
|
||||||
try { |
|
||||||
AnimClipTween clone = (AnimClipTween) super.clone(); |
|
||||||
return clone; |
|
||||||
} catch (CloneNotSupportedException ex) { |
|
||||||
throw new AssertionError(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void cloneFields(Cloner cloner, Object original) { |
|
||||||
clip = cloner.clone(clip); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void setParentAction(Action action) { |
|
||||||
this.parentAction = action; |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,6 @@ |
|||||||
|
package com.jme3.anim.tween; |
||||||
|
|
||||||
|
public interface ContainsTweens { |
||||||
|
|
||||||
|
public Tween[] getTweens(); |
||||||
|
} |
@ -0,0 +1,40 @@ |
|||||||
|
package com.jme3.anim.tween.action; |
||||||
|
|
||||||
|
import com.jme3.anim.tween.ContainsTweens; |
||||||
|
import com.jme3.anim.tween.Tween; |
||||||
|
import com.jme3.util.SafeArrayList; |
||||||
|
|
||||||
|
public class BaseAction extends Action { |
||||||
|
|
||||||
|
private Tween tween; |
||||||
|
private SafeArrayList<Action> subActions = new SafeArrayList<>(Action.class); |
||||||
|
|
||||||
|
public BaseAction(Tween tween) { |
||||||
|
this.tween = tween; |
||||||
|
length = tween.getLength(); |
||||||
|
gatherActions(tween); |
||||||
|
} |
||||||
|
|
||||||
|
private void gatherActions(Tween tween) { |
||||||
|
if (tween instanceof Action) { |
||||||
|
subActions.add((Action) tween); |
||||||
|
} else if (tween instanceof ContainsTweens) { |
||||||
|
Tween[] tweens = ((ContainsTweens) tween).getTweens(); |
||||||
|
for (Tween t : tweens) { |
||||||
|
gatherActions(t); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setWeight(float weight) { |
||||||
|
for (Action action : subActions.getArray()) { |
||||||
|
action.setWeight(weight); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean interpolate(double t) { |
||||||
|
return tween.interpolate(t); |
||||||
|
} |
||||||
|
} |
@ -1,80 +1,129 @@ |
|||||||
package com.jme3.anim.tween.action; |
package com.jme3.anim.tween.action; |
||||||
|
|
||||||
import com.jme3.anim.tween.Tween; |
import com.jme3.anim.util.HasLocalTransform; |
||||||
import com.jme3.anim.tween.Tweens; |
import com.jme3.math.Transform; |
||||||
|
|
||||||
public class BlendAction extends Action { |
import java.util.Collection; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
public class BlendAction extends BlendableAction { |
||||||
|
|
||||||
private Tween firstActiveTween; |
private int firstActiveIndex; |
||||||
private Tween secondActiveTween; |
private int secondActiveIndex; |
||||||
private BlendSpace blendSpace; |
private BlendSpace blendSpace; |
||||||
private float blendWeight; |
private float blendWeight; |
||||||
|
private double[] timeFactor; |
||||||
|
private Map<HasLocalTransform, Transform> targetMap = new HashMap<>(); |
||||||
|
|
||||||
public BlendAction(BlendSpace blendSpace, Tween... tweens) { |
public BlendAction(BlendSpace blendSpace, BlendableAction... actions) { |
||||||
super(tweens); |
super(actions); |
||||||
|
timeFactor = new double[actions.length]; |
||||||
this.blendSpace = blendSpace; |
this.blendSpace = blendSpace; |
||||||
blendSpace.setBlendAction(this); |
blendSpace.setBlendAction(this); |
||||||
|
|
||||||
for (Tween tween : tweens) { |
for (BlendableAction action : actions) { |
||||||
if (tween.getLength() > length) { |
if (action.getLength() > length) { |
||||||
length = tween.getLength(); |
length = action.getLength(); |
||||||
|
} |
||||||
|
Collection<HasLocalTransform> targets = action.getTargets(); |
||||||
|
for (HasLocalTransform target : targets) { |
||||||
|
Transform t = targetMap.get(target); |
||||||
|
if (t == null) { |
||||||
|
t = new Transform(); |
||||||
|
targetMap.put(target, t); |
||||||
|
} |
||||||
} |
} |
||||||
} |
} |
||||||
|
|
||||||
//Blending effect maybe unexpected when blended animation don't have the same length
|
//Blending effect maybe unexpected when blended animation don't have the same length
|
||||||
//Stretching any tween that doesn't have the same length.
|
//Stretching any action that doesn't have the same length.
|
||||||
for (int i = 0; i < tweens.length; i++) { |
for (int i = 0; i < this.actions.length; i++) { |
||||||
if (tweens[i].getLength() != length) { |
this.timeFactor[i] = 1; |
||||||
tweens[i] = Tweens.stretch(length, tweens[i]); |
if (this.actions[i].getLength() != length) { |
||||||
|
double actionLength = this.actions[i].getLength(); |
||||||
|
if (actionLength > 0 && length > 0) { |
||||||
|
this.timeFactor[i] = this.actions[i].getLength() / length; |
||||||
|
} |
||||||
} |
} |
||||||
} |
} |
||||||
|
|
||||||
} |
} |
||||||
|
|
||||||
@Override |
public void doInterpolate(double t) { |
||||||
public float getWeightForTween(Tween tween) { |
|
||||||
blendWeight = blendSpace.getWeight(); |
blendWeight = blendSpace.getWeight(); |
||||||
if (tween == firstActiveTween) { |
BlendableAction firstActiveAction = (BlendableAction) actions[firstActiveIndex]; |
||||||
return 1f; |
BlendableAction secondActiveAction = (BlendableAction) actions[secondActiveIndex]; |
||||||
|
firstActiveAction.setCollectTransformDelegate(this); |
||||||
|
secondActiveAction.setCollectTransformDelegate(this); |
||||||
|
|
||||||
|
//only interpolate the first action if the weight if below 1.
|
||||||
|
if (blendWeight < 1f) { |
||||||
|
firstActiveAction.setWeight(1f); |
||||||
|
firstActiveAction.interpolate(t * timeFactor[firstActiveIndex]); |
||||||
|
if (blendWeight == 0) { |
||||||
|
for (HasLocalTransform target : targetMap.keySet()) { |
||||||
|
collect(target, targetMap.get(target)); |
||||||
|
} |
||||||
|
} |
||||||
} |
} |
||||||
return weight * blendWeight; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
//Second action should be interpolated
|
||||||
public boolean doInterpolate(double t) { |
secondActiveAction.setWeight(blendWeight); |
||||||
if (firstActiveTween == null) { |
secondActiveAction.interpolate(t * timeFactor[secondActiveIndex]); |
||||||
blendSpace.getWeight(); |
|
||||||
} |
|
||||||
|
|
||||||
boolean running = this.firstActiveTween.interpolate(t); |
firstActiveAction.setCollectTransformDelegate(null); |
||||||
this.secondActiveTween.interpolate(t); |
secondActiveAction.setCollectTransformDelegate(null); |
||||||
|
|
||||||
if (!running) { |
} |
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
return true; |
protected Action[] getActions() { |
||||||
|
return actions; |
||||||
} |
} |
||||||
|
|
||||||
@Override |
public BlendSpace getBlendSpace() { |
||||||
public void reset() { |
return blendSpace; |
||||||
|
} |
||||||
|
|
||||||
|
protected void setFirstActiveIndex(int index) { |
||||||
|
this.firstActiveIndex = index; |
||||||
} |
} |
||||||
|
|
||||||
protected Tween[] getTweens() { |
protected void setSecondActiveIndex(int index) { |
||||||
return tweens; |
this.secondActiveIndex = index; |
||||||
} |
} |
||||||
|
|
||||||
public BlendSpace getBlendSpace() { |
@Override |
||||||
return blendSpace; |
public Collection<HasLocalTransform> getTargets() { |
||||||
|
return targetMap.keySet(); |
||||||
} |
} |
||||||
|
|
||||||
protected void setFirstActiveTween(Tween firstActiveTween) { |
@Override |
||||||
this.firstActiveTween = firstActiveTween; |
public void collectTransform(HasLocalTransform target, Transform t, float weight, BlendableAction source) { |
||||||
|
|
||||||
|
Transform tr = targetMap.get(target); |
||||||
|
if (weight == 1) { |
||||||
|
tr.set(t); |
||||||
|
} else if (weight > 0) { |
||||||
|
tr.interpolateTransforms(tr, t, weight); |
||||||
|
} |
||||||
|
|
||||||
|
if (source == actions[secondActiveIndex]) { |
||||||
|
collect(target, tr); |
||||||
|
} |
||||||
} |
} |
||||||
|
|
||||||
protected void setSecondActiveTween(Tween secondActiveTween) { |
private void collect(HasLocalTransform target, Transform tr) { |
||||||
this.secondActiveTween = secondActiveTween; |
if (collectTransformDelegate != null) { |
||||||
|
collectTransformDelegate.collectTransform(target, tr, this.weight, this); |
||||||
|
} else { |
||||||
|
if (getTransitionWeight() == 1) { |
||||||
|
target.setLocalTransform(tr); |
||||||
|
} else { |
||||||
|
Transform trans = target.getLocalTransform(); |
||||||
|
trans.interpolateTransforms(trans, tr, getTransitionWeight()); |
||||||
|
target.setLocalTransform(trans); |
||||||
|
} |
||||||
|
} |
||||||
} |
} |
||||||
|
|
||||||
} |
} |
||||||
|
@ -0,0 +1,83 @@ |
|||||||
|
package com.jme3.anim.tween.action; |
||||||
|
|
||||||
|
import com.jme3.anim.tween.AbstractTween; |
||||||
|
import com.jme3.anim.tween.Tween; |
||||||
|
import com.jme3.anim.util.HasLocalTransform; |
||||||
|
import com.jme3.math.Transform; |
||||||
|
|
||||||
|
import java.util.Collection; |
||||||
|
|
||||||
|
public abstract class BlendableAction extends Action { |
||||||
|
|
||||||
|
protected BlendableAction collectTransformDelegate; |
||||||
|
private float transitionWeight = 1.0f; |
||||||
|
private double transitionLength = 0.4f; |
||||||
|
private TransitionTween transition = new TransitionTween(transitionLength); |
||||||
|
|
||||||
|
public BlendableAction(Tween... tweens) { |
||||||
|
super(tweens); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public void setCollectTransformDelegate(BlendableAction delegate) { |
||||||
|
this.collectTransformDelegate = delegate; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean interpolate(double t) { |
||||||
|
// Sanity check the inputs
|
||||||
|
if (t < 0) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
if (collectTransformDelegate == null) { |
||||||
|
if (transition.getLength() > getLength()) { |
||||||
|
transition.setLength(getLength()); |
||||||
|
} |
||||||
|
transition.interpolate(t); |
||||||
|
} else { |
||||||
|
transitionWeight = 1f; |
||||||
|
} |
||||||
|
|
||||||
|
if (weight == 0) { |
||||||
|
//weight is 0 let's not interpolate
|
||||||
|
return t < getLength(); |
||||||
|
} |
||||||
|
|
||||||
|
doInterpolate(t); |
||||||
|
|
||||||
|
return t < getLength(); |
||||||
|
} |
||||||
|
|
||||||
|
protected abstract void doInterpolate(double t); |
||||||
|
|
||||||
|
public abstract Collection<HasLocalTransform> getTargets(); |
||||||
|
|
||||||
|
public abstract void collectTransform(HasLocalTransform target, Transform t, float weight, BlendableAction source); |
||||||
|
|
||||||
|
public double getTransitionLength() { |
||||||
|
return transitionLength; |
||||||
|
} |
||||||
|
|
||||||
|
public void setTransitionLength(double transitionLength) { |
||||||
|
this.transitionLength = transitionLength; |
||||||
|
} |
||||||
|
|
||||||
|
protected float getTransitionWeight() { |
||||||
|
return transitionWeight; |
||||||
|
} |
||||||
|
|
||||||
|
private class TransitionTween extends AbstractTween { |
||||||
|
|
||||||
|
|
||||||
|
public TransitionTween(double length) { |
||||||
|
super(length); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void doInterpolate(double t) { |
||||||
|
transitionWeight = (float) t; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,64 @@ |
|||||||
|
package com.jme3.anim.tween.action; |
||||||
|
|
||||||
|
import com.jme3.anim.AnimClip; |
||||||
|
import com.jme3.anim.TransformTrack; |
||||||
|
import com.jme3.anim.tween.AbstractTween; |
||||||
|
import com.jme3.anim.util.HasLocalTransform; |
||||||
|
import com.jme3.math.Transform; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Collection; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
public class ClipAction extends BlendableAction { |
||||||
|
|
||||||
|
private AnimClip clip; |
||||||
|
private Transform transform = new Transform(); |
||||||
|
|
||||||
|
public ClipAction(AnimClip clip) { |
||||||
|
this.clip = clip; |
||||||
|
length = clip.getLength(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void doInterpolate(double t) { |
||||||
|
TransformTrack[] tracks = clip.getTracks(); |
||||||
|
for (TransformTrack track : tracks) { |
||||||
|
HasLocalTransform target = track.getTarget(); |
||||||
|
transform.set(target.getLocalTransform()); |
||||||
|
track.getTransformAtTime(t, transform); |
||||||
|
|
||||||
|
if (collectTransformDelegate != null) { |
||||||
|
collectTransformDelegate.collectTransform(target, transform, weight, this); |
||||||
|
} else { |
||||||
|
this.collectTransform(target, transform, getTransitionWeight(), this); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void reset() { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Collection<HasLocalTransform> getTargets() { |
||||||
|
List<HasLocalTransform> targets = new ArrayList<>(clip.getTracks().length); |
||||||
|
for (TransformTrack track : clip.getTracks()) { |
||||||
|
targets.add(track.getTarget()); |
||||||
|
} |
||||||
|
return targets; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void collectTransform(HasLocalTransform target, Transform t, float weight, BlendableAction source) { |
||||||
|
if (weight == 1f) { |
||||||
|
target.setLocalTransform(t); |
||||||
|
} else { |
||||||
|
Transform tr = target.getLocalTransform(); |
||||||
|
tr.interpolateTransforms(tr, t, weight); |
||||||
|
target.setLocalTransform(tr); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
@ -1,75 +0,0 @@ |
|||||||
package com.jme3.anim.tween.action; |
|
||||||
|
|
||||||
import com.jme3.anim.tween.AbstractTween; |
|
||||||
import com.jme3.anim.tween.Tween; |
|
||||||
|
|
||||||
public class SequenceAction extends Action { |
|
||||||
|
|
||||||
private int currentIndex = 0; |
|
||||||
private double accumTime; |
|
||||||
private double transitionTime = 0; |
|
||||||
private float mainWeight = 1.0f; |
|
||||||
private double transitionLength = 0.4f; |
|
||||||
private TransitionTween transition = new TransitionTween(transitionLength); |
|
||||||
|
|
||||||
|
|
||||||
public SequenceAction(Tween... tweens) { |
|
||||||
super(tweens); |
|
||||||
for (Tween tween : tweens) { |
|
||||||
length += tween.getLength(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public float getWeightForTween(Tween tween) { |
|
||||||
return weight * mainWeight; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean doInterpolate(double t) { |
|
||||||
Tween currentTween = tweens[currentIndex]; |
|
||||||
if (transition.getLength() > currentTween.getLength()) { |
|
||||||
transition.setLength(currentTween.getLength()); |
|
||||||
} |
|
||||||
|
|
||||||
transition.interpolate(t - transitionTime); |
|
||||||
|
|
||||||
boolean running = currentTween.interpolate(t - accumTime); |
|
||||||
if (!running) { |
|
||||||
accumTime += currentTween.getLength(); |
|
||||||
currentIndex++; |
|
||||||
transitionTime = accumTime; |
|
||||||
transition.setLength(transitionLength); |
|
||||||
} |
|
||||||
|
|
||||||
if (t >= length) { |
|
||||||
reset(); |
|
||||||
return false; |
|
||||||
} |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
public void reset() { |
|
||||||
currentIndex = 0; |
|
||||||
accumTime = 0; |
|
||||||
transitionTime = 0; |
|
||||||
mainWeight = 1; |
|
||||||
} |
|
||||||
|
|
||||||
public void setTransitionLength(double transitionLength) { |
|
||||||
this.transitionLength = transitionLength; |
|
||||||
} |
|
||||||
|
|
||||||
private class TransitionTween extends AbstractTween { |
|
||||||
|
|
||||||
|
|
||||||
public TransitionTween(double length) { |
|
||||||
super(length); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
protected void doInterpolate(double t) { |
|
||||||
mainWeight = (float) t; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue