package actor;
import java.util.Properties;
import java.util.StringTokenizer;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.File;
import java.io.FileReader;
import java.io.BufferedReader;
public class KeyFrameAnimation
{
private String name;
private KeyFrame[] frames;
private double rate, travel;
private int repeats, frameCount;
protected KeyFrameAnimation
(String name, KeyFrame[] frames, double rate, double travel)
{
this( name, frames, rate, travel, Integer.MAX_VALUE);
}
KeyFrameAnimation(Properties properties)
{
this.setProperties(properties);
}
protected KeyFrameAnimation(File file) throws IOException,
FileNotFoundException{
setProperties(file);
}
KeyFrameAnimation
(String name, KeyFrame[] frames, double rate, double travel, int repeats)
{
this.name = name;
this.frames = frames;
this.rate = rate;
this.travel = travel;
this.repeats = repeats;
this.frameCount = frames.length;
}
public Properties getProperties()
{
Properties p = new Properties();
p.setProperty("name", this.getName());
p.setProperty("rate", this.getRate()+"");
p.setProperty("travel", this.getTravel()+"");
p.setProperty("frames", this.framesToString());
p.setProperty("frameCount", this.getFrameCount()+"");
return p;
}
public String toString()
{
return getProperties().toString();
}
private void setProperties(File file) throws FileNotFoundException, IOException
{
BufferedReader fileReader = new BufferedReader(new FileReader(file));
String nextLine = fileReader.readLine();
String input = "";
while(nextLine != null){
input += "\n" + nextLine;
nextLine = fileReader.readLine();
}
setProperties(input);
}
private void setProperties(String properties)
{
Properties prop = new Properties();
String withoutBraces = properties.substring(1, properties.length() - 1);
int i_delimiter = -1;
int i_nextDelimiter = withoutBraces.indexOf(", ", i_delimiter + 1);
do
{
String nextPair = withoutBraces.substring(i_delimiter + 2, i_nextDelimiter);
int i_equals = nextPair.indexOf("=");
String property = nextPair.substring(0,i_equals);
String value = nextPair.substring(i_equals + 1, nextPair.length());
prop.setProperty(property,value);
i_delimiter = i_nextDelimiter;
i_nextDelimiter = withoutBraces.indexOf(", ", i_delimiter + 1);
if (i_nextDelimiter == -1)
{
i_nextDelimiter = withoutBraces.length();
}
}
while(i_delimiter != withoutBraces.length());
setProperties(prop);
}
private void setProperties(Properties p)
{
this.name = p.getProperty("name");
this.rate = Double.parseDouble(p.getProperty("rate"));
this.travel = Double.parseDouble(p.getProperty("travel"));
this.frameCount = Integer.parseInt(p.getProperty("frameCount"));
this.frames = new KeyFrame[frameCount];
for(int i = 0; i < frames.length; i++){
frames[i] = new KeyFrame();
Point3D[] positions = new Point3D[6];
frames[i].setVertexPositions(positions);
for(int j = 0; j < 6; j++){
positions[j] = new Point3D(0,0,0);
}
}
this.repeats = Integer.MAX_VALUE;
String rpts = p.getProperty("repeats");
if (rpts != null)
this.repeats = Integer.parseInt(rpts);
this.setFramesFromString(p.getProperty("frames"));
}
void setFramesFromString(String framesAsString)
{
int beginNextFrame = framesAsString.indexOf("[");
int frameNum = 0;
while (true)
{
KeyFrame currentFrame = this.frames[frameNum];
currentFrame.setCycleTime(Double.parseDouble
(framesAsString.substring(beginNextFrame + 1,
framesAsString.indexOf(",",beginNextFrame))));
Point3D[] vertexPos = currentFrame.getVertexPositions();
int beginNextPos = framesAsString.indexOf("[",beginNextFrame + 1);
for(int i = 0; i < vertexPos.length; i++)
{
Point3D currentPos = vertexPos[i];
if(beginNextPos == -1){
throw new RuntimeException("Properties in bad format");
}
String posAsString = framesAsString.substring
(beginNextPos + 1, framesAsString.indexOf("]",beginNextPos + 1));
StringTokenizer tok = new StringTokenizer(posAsString,",");
double x = Double.parseDouble(tok.nextToken());
double y = Double.parseDouble(tok.nextToken());
double z = Double.parseDouble(tok.nextToken());
currentPos.set(x,y,z);
beginNextPos = framesAsString.indexOf("[",beginNextPos + 1);
}
frameNum++;
beginNextFrame = framesAsString.indexOf("][",beginNextFrame + 1) + 1;
if(beginNextFrame <= 0) break;
}
}
String framesToString()
{
String fs = "";
for (int i = 0; i < frames.length; i++)
{
KeyFrame kf = frames[i];
Point3D[] vps = kf.getVertexPositions();
fs += "["+ kf.getCycleTime() + ",";
for (int j = 0; j < vps.length; j++) {
fs += vps[j];
if (j < vps.length-1)
fs += ",";
}
fs += "]";
}
return fs;
}
public Point3D[] getVertexOffsets(double elapsedTime, double beat)
{
KeyFrame lerpFrame = calculateInterpolatedAnimationFrame(elapsedTime, beat);
return lerpFrame.getVertexPositions();
}
public KeyFrame calculateInterpolatedAnimationFrame(
double elapsed,
double beat)
{
int keyIdx = (int)beat;
KeyFrame kf0 = getFrame(keyIdx);
KeyFrame kf1 = getFrame((keyIdx + 1) % getFrameCount());
Point3D[] lerpPoint = KeyFrame.keyFrameLerp(beat, kf0, kf1);
return new KeyFrame(lerpPoint);
}
public int getFrameCount()
{
if (frames == null || frames.length==0)
return frameCount;
return frames.length;
}
private void setFrameCount(int frames)
{
this.frameCount = frames;
}
public KeyFrame[] getFrames()
{
return frames;
}
public KeyFrame getFrame(int idx)
{
return frames[idx];
}
public double getRate()
{
return rate;
}
public double getTravel()
{
return travel;
}
public String getName()
{
return name;
}
}