package com.nilunder.bdx.components;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import com.nilunder.bdx.Component;
import com.nilunder.bdx.GameObject;
import com.nilunder.bdx.State;
import com.nilunder.bdx.utils.Timer;
public class MeshAnim extends Component<GameObject> {
public static class Animation extends ArrayList<String>{
public String name;
public float fps;
public boolean looping;
public int playHead;
public int playDir;
public Animation(String name, float fps, boolean looping){
this.name = name;
this.fps = fps;
this.looping = looping;
playHead = 0;
playDir = 1;
}
public String nextFrame(){
if (onLastFrame()){
if (looping)
reset();
else
playHead -= playDir;
}
String frame = get(playHead);
playHead += playDir;
return frame;
}
public boolean onLastFrame(){
return playHead == size() || playHead == -1;
}
public void reset(){
if (playDir > 0)
playHead = 0;
else
playHead = size() - 1;
}
}
public float speed;
public HashMap<String, Animation> animations;
public Animation active;
public String currentMesh;
private int prevFrame;
private Timer ticker;
public MeshAnim(GameObject g){
super(g);
animations = new HashMap<String, Animation>();
ticker = new Timer();
speed = 1;
state = play;
currentMesh = g.mesh().name();
}
public void add(String name, String[] frames){
add(name, frames, 12, true);
}
public void add(String name, String[] frames, float fps, boolean looping){
Animation anim = new Animation(name, fps, looping);
anim.addAll(Arrays.asList(frames));
animations.put(name, anim);
}
public ArrayList<String> animationNames(){
return new ArrayList<String>(animations.keySet());
}
public void play(String name){
Animation next = animations.get(name);
if (active != next){
active = next;
active.playDir = speed * active.fps < 0 ? -1 : 1;
active.reset();
ticker.done(true); // immediate play
}
if (!active.looping && active.onLastFrame()){
active.playDir = speed * active.fps < 0 ? -1 : 1;
active.reset();
ticker.done(true);
}
}
public void showNextFrame(){
active.playDir = speed * active.fps < 0 ? -1 : 1;
String frame = active.nextFrame();
if (!currentMesh.equals(frame)) {
currentMesh = frame;
g.mesh(currentMesh);
}
}
public void frame(int frame){
active.playHead = frame; // Set the frame, and
ticker.done(true); // Update the mesh immediately
}
public int frame(){
return active.playHead - active.playDir;
}
public boolean frameChanged() {
return prevFrame != frame();
}
private State play = new State(){
private float nz(float n){
return n <= 0 ? 0.000001f : n;
}
public void main(){
if (active == null)
return;
prevFrame = frame();
ticker.interval = 1f / nz(Math.abs(active.fps) * Math.abs(speed));
if (ticker.tick()){
showNextFrame();
}
}
};
}