[SOLVED] When AnimComposer reaches the end of an Action


#1

In JME 3.2, each AnimChannel has a LoopMode that controls what it does when it reaches the end of an Animation. Furthermore, there’s an AnimEventListener interface that makes it simple to detect when an AnimChannel reaches the end of an Animation.

I’m currently reworking TestBoneRagdoll to use the new animation system. I’ve figured out how to play an action using AnimComposer.setCurrentAction() but not how to prevent the action from looping or detect when it is about to loop.

Has anyone figured out how do these things in JME 3.3?


#2

@sgold thanks for asking this :slightly_smiling_face:

There are couple of ways to do this.

As you know I made a PR to add support for looping in AnimComposer. It is not merged yet.

workaround is to create your own Action by extending BaseAction.

for example :

public class CharacterAction extends BaseAction {
        
        AnimComposer ac;
        String layer;
        boolean loop;
        
        public CharacterAction(Tween delegate, AnimComposer ac, String layer, boolean loop) {
            super(delegate);
            this.ac = ac;
            this.layer = layer;
            this.loop = loop;
        }

        public boolean isLooping() {
            return loop;
        }
        
        public void setLooping(boolean loop){
            this.loop = loop;
        }
        
        @Override
        public boolean interpolate(double t) {
            boolean running = super.interpolate(t);
            if (!loop && !running) {
               // animation done running, now we can :
               // set speed on this action to 0 to stop
               this.setSpeed(0);
               
               // or we can remove this action from the layer it is attached to 
               ac.removeCurrentAction(layer); 
               //or this if we are using DEFAULT_LAYER 
               ac.removeCurrentAction(AnimComposer.DEFAULT_LAYER);
               
            }
            return running;
        }
        
    }

You can use this method to add your own action :

Another way is to add a CallMethod tween at the end of sequence then this CallMethod tween will get run at the end of animation.

For example you can call “removeCurrentAction” method on AnimComposer :

BaseAction myAction = new BaseAction(Tweens.sequence(delegate, Tweens.callMethod(ac, "removeCurrentAction", layer)));


#3

Thank you!

I used the CallMethod technique in both TestBoneRagdoll and TestRagdollCharacter.

For me, the key insight was that Action implements Tween. Once I realized that, things went fairly smoothly.