瀏覽代碼

Better blending structure

Rémy Bouquet 7 年之前
父節點
當前提交
ce88350abf

+ 17 - 23
jme3-core/src/main/java/com/jme3/anim/AnimComposer.java

@@ -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;
     }

+ 0 - 87
jme3-core/src/main/java/com/jme3/anim/tween/AnimClipTween.java

@@ -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;
-    }
-}

+ 6 - 0
jme3-core/src/main/java/com/jme3/anim/tween/ContainsTweens.java

@@ -0,0 +1,6 @@
+package com.jme3.anim.tween;
+
+public interface ContainsTweens {
+
+    public Tween[] getTweens();
+}

+ 23 - 7
jme3-core/src/main/java/com/jme3/anim/tween/Tweens.java

@@ -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 + "]";
         }
     }
 

+ 11 - 28
jme3-core/src/main/java/com/jme3/anim/tween/action/Action.java

@@ -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;
-    }
 }

+ 40 - 0
jme3-core/src/main/java/com/jme3/anim/tween/action/BaseAction.java

@@ -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);
+    }
+}

+ 91 - 42
jme3-core/src/main/java/com/jme3/anim/tween/action/BlendAction.java

@@ -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;
+                }
             }
         }
-
     }
 
-    @Override
-    public float getWeightForTween(Tween tween) {
+    public void doInterpolate(double t) {
         blendWeight = blendSpace.getWeight();
-        if (tween == firstActiveTween) {
-            return 1f;
+        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));
+                }
+            }
         }
-        return weight * blendWeight;
-    }
 
-    @Override
-    public boolean doInterpolate(double t) {
-        if (firstActiveTween == null) {
-            blendSpace.getWeight();
-        }
+        //Second action should be interpolated
+        secondActiveAction.setWeight(blendWeight);
+        secondActiveAction.interpolate(t * timeFactor[secondActiveIndex]);
 
-        boolean running = this.firstActiveTween.interpolate(t);
-        this.secondActiveTween.interpolate(t);
+        firstActiveAction.setCollectTransformDelegate(null);
+        secondActiveAction.setCollectTransformDelegate(null);
 
-        if (!running) {
-            return false;
-        }
+    }
 
-        return true;
+    protected Action[] getActions() {
+        return actions;
     }
 
-    @Override
-    public void reset() {
+    public BlendSpace getBlendSpace() {
+        return blendSpace;
+    }
 
+    protected void setFirstActiveIndex(int index) {
+        this.firstActiveIndex = index;
     }
 
-    protected Tween[] getTweens() {
-        return tweens;
+    protected void setSecondActiveIndex(int index) {
+        this.secondActiveIndex = index;
     }
 
-    public BlendSpace getBlendSpace() {
-        return blendSpace;
+    @Override
+    public Collection<HasLocalTransform> getTargets() {
+        return targetMap.keySet();
     }
 
-    protected void setFirstActiveTween(Tween firstActiveTween) {
-        this.firstActiveTween = firstActiveTween;
+    @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);
+        }
     }
 
-    protected void setSecondActiveTween(Tween secondActiveTween) {
-        this.secondActiveTween = secondActiveTween;
+    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);
+            }
+        }
     }
+
 }

+ 83 - 0
jme3-core/src/main/java/com/jme3/anim/tween/action/BlendableAction.java

@@ -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;
+        }
+    }
+
+}

+ 64 - 0
jme3-core/src/main/java/com/jme3/anim/tween/action/ClipAction.java

@@ -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);
+        }
+    }
+
+
+}

+ 6 - 8
jme3-core/src/main/java/com/jme3/anim/tween/action/LinearBlendSpace.java

@@ -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;

+ 0 - 75
jme3-core/src/main/java/com/jme3/anim/tween/action/SequenceAction.java

@@ -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;
-        }
-    }
-}

+ 5 - 5
jme3-examples/src/main/java/jme3test/model/anim/TestAnimMigration.java

@@ -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);