Better blending structure
This commit is contained in:
parent
a8845a1506
commit
ce88350abf
@ -1,11 +1,8 @@
|
||||
package com.jme3.anim;
|
||||
|
||||
import com.jme3.anim.tween.AnimClipTween;
|
||||
import com.jme3.anim.tween.Tween;
|
||||
import com.jme3.anim.tween.action.Action;
|
||||
import com.jme3.anim.tween.action.BlendAction;
|
||||
import com.jme3.anim.tween.action.BlendSpace;
|
||||
import com.jme3.anim.tween.action.SequenceAction;
|
||||
import com.jme3.anim.tween.Tweens;
|
||||
import com.jme3.anim.tween.action.*;
|
||||
import com.jme3.export.*;
|
||||
import com.jme3.renderer.RenderManager;
|
||||
import com.jme3.renderer.ViewPort;
|
||||
@ -62,40 +59,37 @@ public class AnimComposer extends AbstractControl {
|
||||
}
|
||||
|
||||
public void setCurrentAction(String name) {
|
||||
Action action = action(name);
|
||||
if (currentAction != null) {
|
||||
currentAction.reset();
|
||||
}
|
||||
currentAction = action;
|
||||
currentAction = action(name);
|
||||
time = 0;
|
||||
}
|
||||
|
||||
public Action action(String name) {
|
||||
Action action = actions.get(name);
|
||||
if (action == null) {
|
||||
AnimClipTween tween = tweenFromClip(name);
|
||||
action = new SequenceAction(tween);
|
||||
AnimClip clip = animClipMap.get(name);
|
||||
if (clip == null) {
|
||||
throw new IllegalArgumentException("Cannot find clip named " + name);
|
||||
}
|
||||
action = new ClipAction(clip);
|
||||
actions.put(name, action);
|
||||
}
|
||||
return action;
|
||||
}
|
||||
|
||||
public AnimClipTween tweenFromClip(String clipName) {
|
||||
AnimClip clip = animClipMap.get(clipName);
|
||||
if (clip == null) {
|
||||
throw new IllegalArgumentException("Cannot find clip named " + clipName);
|
||||
}
|
||||
return new AnimClipTween(clip);
|
||||
}
|
||||
|
||||
public SequenceAction actionSequence(String name, Tween... tweens) {
|
||||
SequenceAction action = new SequenceAction(tweens);
|
||||
public BaseAction actionSequence(String name, Tween... tweens) {
|
||||
BaseAction action = new BaseAction(Tweens.sequence(tweens));
|
||||
actions.put(name, action);
|
||||
return action;
|
||||
}
|
||||
|
||||
public BlendAction actionBlended(String name, BlendSpace blendSpace, Tween... tweens) {
|
||||
BlendAction action = new BlendAction(blendSpace, tweens);
|
||||
public BlendAction actionBlended(String name, BlendSpace blendSpace, String... clips) {
|
||||
BlendableAction[] acts = new BlendableAction[clips.length];
|
||||
for (int i = 0; i < acts.length; i++) {
|
||||
BlendableAction ba = (BlendableAction) action(clips[i]);
|
||||
acts[i] = ba;
|
||||
}
|
||||
BlendAction action = new BlendAction(blendSpace, acts);
|
||||
actions.put(name, action);
|
||||
return action;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
@ -221,7 +221,7 @@ public class Tweens {
|
||||
}
|
||||
}
|
||||
|
||||
private static class Sequence implements Tween {
|
||||
private static class Sequence implements Tween, ContainsTweens {
|
||||
private final Tween[] delegates;
|
||||
private int current = 0;
|
||||
private double baseTime;
|
||||
@ -279,9 +279,14 @@ public class Tweens {
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + "[delegates=" + Arrays.asList(delegates) + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tween[] getTweens() {
|
||||
return delegates;
|
||||
}
|
||||
}
|
||||
|
||||
private static class Parallel implements Tween {
|
||||
private static class Parallel implements Tween, ContainsTweens {
|
||||
private final Tween[] delegates;
|
||||
private final boolean[] done;
|
||||
private double length;
|
||||
@ -343,6 +348,11 @@ public class Tweens {
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + "[delegates=" + Arrays.asList(delegates) + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tween[] getTweens() {
|
||||
return delegates;
|
||||
}
|
||||
}
|
||||
|
||||
private static class Delay extends AbstractTween {
|
||||
@ -356,14 +366,15 @@ public class Tweens {
|
||||
}
|
||||
}
|
||||
|
||||
private static class Stretch implements Tween {
|
||||
private static class Stretch implements Tween, ContainsTweens {
|
||||
|
||||
private final Tween delegate;
|
||||
private final Tween[] delegate = new Tween[1];
|
||||
private final double length;
|
||||
private final double scale;
|
||||
|
||||
public Stretch(Tween delegate, double length) {
|
||||
this.delegate = delegate;
|
||||
this.delegate[0] = delegate;
|
||||
|
||||
this.length = length;
|
||||
|
||||
// Caller desires delegate to be 'length' instead of
|
||||
@ -382,6 +393,11 @@ public class Tweens {
|
||||
return length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tween[] getTweens() {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean interpolate(double t) {
|
||||
if (t < 0) {
|
||||
@ -392,12 +408,12 @@ public class Tweens {
|
||||
} else {
|
||||
t = length;
|
||||
}
|
||||
return delegate.interpolate(t);
|
||||
return delegate[0].interpolate(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + "[delegate=" + delegate + ", length=" + length + "]";
|
||||
return getClass().getSimpleName() + "[delegate=" + delegate[0] + ", length=" + length + "]";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,23 +1,21 @@
|
||||
package com.jme3.anim.tween.action;
|
||||
|
||||
import com.jme3.anim.tween.Tween;
|
||||
import com.jme3.anim.util.Weighted;
|
||||
import com.jme3.export.*;
|
||||
|
||||
import java.io.IOException;
|
||||
public abstract class Action implements Tween {
|
||||
|
||||
public abstract class Action implements Tween, Weighted {
|
||||
|
||||
protected Tween[] tweens;
|
||||
protected Action[] actions;
|
||||
protected float weight = 1;
|
||||
protected double length;
|
||||
protected Action parentAction;
|
||||
|
||||
protected Action(Tween... tweens) {
|
||||
this.tweens = tweens;
|
||||
for (Tween tween : tweens) {
|
||||
if (tween instanceof Weighted) {
|
||||
((Weighted) tween).setParentAction(this);
|
||||
this.actions = new Action[tweens.length];
|
||||
for (int i = 0; i < tweens.length; i++) {
|
||||
Tween tween = tweens[i];
|
||||
if (tween instanceof Action) {
|
||||
this.actions[i] = (Action) tween;
|
||||
} else {
|
||||
this.actions[i] = new BaseAction(tween);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -27,23 +25,8 @@ public abstract class Action implements Tween, Weighted {
|
||||
return length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean interpolate(double t) {
|
||||
if (parentAction != null) {
|
||||
weight = parentAction.getWeightForTween(this);
|
||||
}
|
||||
|
||||
return doInterpolate(t);
|
||||
public void setWeight(float weight) {
|
||||
this.weight = weight;
|
||||
}
|
||||
|
||||
public abstract float getWeightForTween(Tween tween);
|
||||
|
||||
public abstract boolean doInterpolate(double t);
|
||||
|
||||
public abstract void reset();
|
||||
|
||||
@Override
|
||||
public void setParentAction(Action parentAction) {
|
||||
this.parentAction = parentAction;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
import com.jme3.anim.tween.Tween;
|
||||
import com.jme3.anim.tween.Tweens;
|
||||
import com.jme3.anim.util.HasLocalTransform;
|
||||
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 Tween secondActiveTween;
|
||||
private int firstActiveIndex;
|
||||
private int secondActiveIndex;
|
||||
private BlendSpace blendSpace;
|
||||
private float blendWeight;
|
||||
private double[] timeFactor;
|
||||
private Map<HasLocalTransform, Transform> targetMap = new HashMap<>();
|
||||
|
||||
public BlendAction(BlendSpace blendSpace, Tween... tweens) {
|
||||
super(tweens);
|
||||
public BlendAction(BlendSpace blendSpace, BlendableAction... actions) {
|
||||
super(actions);
|
||||
timeFactor = new double[actions.length];
|
||||
this.blendSpace = blendSpace;
|
||||
blendSpace.setBlendAction(this);
|
||||
|
||||
for (Tween tween : tweens) {
|
||||
if (tween.getLength() > length) {
|
||||
length = tween.getLength();
|
||||
for (BlendableAction action : actions) {
|
||||
if (action.getLength() > length) {
|
||||
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
|
||||
//Stretching any tween that doesn't have the same length.
|
||||
for (int i = 0; i < tweens.length; i++) {
|
||||
if (tweens[i].getLength() != length) {
|
||||
tweens[i] = Tweens.stretch(length, tweens[i]);
|
||||
//Stretching any action that doesn't have the same length.
|
||||
for (int i = 0; i < this.actions.length; i++) {
|
||||
this.timeFactor[i] = 1;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void doInterpolate(double t) {
|
||||
blendWeight = blendSpace.getWeight();
|
||||
BlendableAction firstActiveAction = (BlendableAction) actions[firstActiveIndex];
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//Second action should be interpolated
|
||||
secondActiveAction.setWeight(blendWeight);
|
||||
secondActiveAction.interpolate(t * timeFactor[secondActiveIndex]);
|
||||
|
||||
@Override
|
||||
public float getWeightForTween(Tween tween) {
|
||||
blendWeight = blendSpace.getWeight();
|
||||
if (tween == firstActiveTween) {
|
||||
return 1f;
|
||||
}
|
||||
return weight * blendWeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doInterpolate(double t) {
|
||||
if (firstActiveTween == null) {
|
||||
blendSpace.getWeight();
|
||||
}
|
||||
|
||||
boolean running = this.firstActiveTween.interpolate(t);
|
||||
this.secondActiveTween.interpolate(t);
|
||||
|
||||
if (!running) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
firstActiveAction.setCollectTransformDelegate(null);
|
||||
secondActiveAction.setCollectTransformDelegate(null);
|
||||
|
||||
}
|
||||
|
||||
protected Tween[] getTweens() {
|
||||
return tweens;
|
||||
protected Action[] getActions() {
|
||||
return actions;
|
||||
}
|
||||
|
||||
public BlendSpace getBlendSpace() {
|
||||
return blendSpace;
|
||||
}
|
||||
|
||||
protected void setFirstActiveTween(Tween firstActiveTween) {
|
||||
this.firstActiveTween = firstActiveTween;
|
||||
protected void setFirstActiveIndex(int index) {
|
||||
this.firstActiveIndex = index;
|
||||
}
|
||||
|
||||
protected void setSecondActiveTween(Tween secondActiveTween) {
|
||||
this.secondActiveTween = secondActiveTween;
|
||||
protected void setSecondActiveIndex(int index) {
|
||||
this.secondActiveIndex = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<HasLocalTransform> getTargets() {
|
||||
return targetMap.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
private void collect(HasLocalTransform target, Transform tr) {
|
||||
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,7 +1,5 @@
|
||||
package com.jme3.anim.tween.action;
|
||||
|
||||
import com.jme3.anim.tween.Tween;
|
||||
|
||||
public class LinearBlendSpace implements BlendSpace {
|
||||
|
||||
private BlendAction action;
|
||||
@ -17,24 +15,24 @@ public class LinearBlendSpace implements BlendSpace {
|
||||
@Override
|
||||
public void setBlendAction(BlendAction action) {
|
||||
this.action = action;
|
||||
Tween[] tweens = action.getTweens();
|
||||
step = maxValue / (float) (tweens.length - 1);
|
||||
Action[] actions = action.getActions();
|
||||
step = maxValue / (float) (actions.length - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getWeight() {
|
||||
Tween[] tweens = action.getTweens();
|
||||
Action[] actions = action.getActions();
|
||||
float lowStep = 0, highStep = 0;
|
||||
int lowIndex = 0, highIndex = 0;
|
||||
for (int i = 0; i < tweens.length && highStep < value; i++) {
|
||||
for (int i = 0; i < actions.length && highStep < value; i++) {
|
||||
lowStep = highStep;
|
||||
lowIndex = i;
|
||||
highStep += step;
|
||||
}
|
||||
highIndex = lowIndex + 1;
|
||||
|
||||
action.setFirstActiveTween(tweens[lowIndex]);
|
||||
action.setSecondActiveTween(tweens[highIndex]);
|
||||
action.setFirstActiveIndex(lowIndex);
|
||||
action.setSecondActiveIndex(highIndex);
|
||||
|
||||
if (highStep == lowStep) {
|
||||
return 0;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ package jme3test.model.anim;
|
||||
import com.jme3.anim.AnimComposer;
|
||||
import com.jme3.anim.SkinningControl;
|
||||
import com.jme3.anim.tween.action.BlendAction;
|
||||
import com.jme3.anim.tween.action.BlendableAction;
|
||||
import com.jme3.anim.tween.action.LinearBlendSpace;
|
||||
import com.jme3.anim.util.AnimMigrationUtils;
|
||||
import com.jme3.app.ChaseCameraAppState;
|
||||
@ -159,13 +160,12 @@ public class TestAnimMigration extends SimpleApplication {
|
||||
anims.add(name);
|
||||
}
|
||||
composer.actionSequence("Sequence",
|
||||
composer.tweenFromClip("Walk"),
|
||||
composer.tweenFromClip("Run"),
|
||||
composer.tweenFromClip("Jumping"));
|
||||
composer.action("Walk"),
|
||||
composer.action("Run"),
|
||||
composer.action("Jumping"));
|
||||
|
||||
action = composer.actionBlended("Blend", new LinearBlendSpace(4),
|
||||
composer.tweenFromClip("Walk"),
|
||||
composer.tweenFromClip("Jumping"));
|
||||
"Walk", "Punches", "Jumping", "Taunt");
|
||||
|
||||
action.getBlendSpace().setValue(2);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user