//Get the next variable frame public VarFrame getNextFrame(string varName) { foreach (CustAnim anim in animations) { if (anim.name.ToUpper() == currentAnim.ToUpper()) { foreach (VarFrame frame in anim.varFrames) { if (frame.varName == varName) { //This frame has to be for us if (frame.frameTime >= currTime) { return(frame); } } } break; } } //Debug.Log("Animation " + currentAnim + " not found or animation does not contain variable " + varName); VarFrame newFrame = new VarFrame(); newFrame.animName = "NA"; return(newFrame); }
//Get the previous variable frame public VarFrame getPreviousFrame(string varName) { foreach (CustAnim anim in animations) { if (anim.name.ToUpper() == currentAnim.ToUpper()) { VarFrame prevFrame = new VarFrame(); foreach (VarFrame frame in anim.varFrames) { if (frame.varName == varName) { //This frame has to be for us if (frame.frameTime <= currTime) { if ((frame.creationFrame && currTime < 32f) || currTime >= anim.duration) { //This is within the first frame of existence, likely a starting time, or otherwise the last frame where we "stay" unless we loop return(frame); } else { //Store this one for later, for now we can assume the file is in chronological order until we have a better JSON or XML format prevFrame = frame; } } else { //We went too far now, return the previous one return(prevFrame); } } } break; } } //Debug.Log("Animation " + currentAnim + " not found or animation does not contain variable " + varName); VarFrame newFrame = new VarFrame(); newFrame.animName = "NA"; return(newFrame); }
//Add a variable keyframe to the animation public void AddVarFrame(string animName, VarFrame frame) { bool foundAnim = false; foreach (CustAnim anim in animations) { if (anim.name.ToUpper() == animName.ToUpper()) { if (!anim.variables.ContainsKey(frame.varName)) { //Creation frame! frame.creationFrame = true; anim.variables.Add(frame.varName, frame.value); } anim.varFrames.Add(frame); foundAnim = true; break; } } if (!foundAnim) { CustAnim anim = new CustAnim(); anim.name = animName; if (!anim.variables.ContainsKey(frame.varName)) { //Creation frame! frame.creationFrame = true; anim.variables.Add(frame.varName, frame.value); } anim.varFrames.Add(frame); animations.Add(anim); } }
//Parse the data from file into animation data private void parseLines(List <string> data) { foreach (string line in data) { string[] split = line.Split(','); if (split.Length > 12) { //Key frame KeyFrame frame = new KeyFrame(); if (split.Length > 13) { //For a new object int id = 0; int.TryParse(split[0], out id); frame.objID = id; frame.objDesc = split[1]; frame.animName = split[2]; int childOf = 0; int.TryParse(split[3], out childOf); frame.childOf = childOf; int frameTime = 0; int.TryParse(split[4], out frameTime); frame.frameTime = frameTime; int instant = 0; int.TryParse(split[5], out instant); if (instant > 0) { frame.instant = true; } float pX = 0f; float pY = 0f; float pZ = 0f; float.TryParse(split[6], out pX); float.TryParse(split[7], out pY); float.TryParse(split[8], out pZ); frame.position = new Vector3(pX, pY, pZ); float rX = 0f; float rY = 0f; float rZ = 0f; float.TryParse(split[9], out rX); float.TryParse(split[10], out rY); float.TryParse(split[11], out rZ); frame.rotation = new Vector3(rX, rY, rZ); float sX = 0f; float sY = 0f; float sZ = 0f; float.TryParse(split[12], out sX); float.TryParse(split[13], out sY); float.TryParse(split[14], out sZ); frame.scale = new Vector3(sX, sY, sZ); myAnim.AddKeyFrame(frame.animName, frame); } else { //For an existing object int id = 0; int.TryParse(split[0], out id); frame.objID = id; frame.animName = split[1]; int frameTime = 0; int.TryParse(split[2], out frameTime); frame.frameTime = frameTime; int instant = 0; int.TryParse(split[3], out instant); if (instant > 0) { frame.instant = true; } float pX = 0f; float pY = 0f; float pZ = 0f; float.TryParse(split[4], out pX); float.TryParse(split[5], out pY); float.TryParse(split[6], out pZ); frame.position = new Vector3(pX, pY, pZ); float rX = 0f; float rY = 0f; float rZ = 0f; float.TryParse(split[7], out rX); float.TryParse(split[8], out rY); float.TryParse(split[9], out rZ); frame.rotation = new Vector3(rX, rY, rZ); float sX = 0f; float sY = 0f; float sZ = 0f; float.TryParse(split[10], out sX); float.TryParse(split[11], out sY); float.TryParse(split[12], out sZ); frame.scale = new Vector3(sX, sY, sZ); myAnim.AddKeyFrame(frame.animName, frame); } } else if (split.Length > 4) { //Variable frame VarFrame frame = new VarFrame(); frame.varName = split[0]; frame.animName = split[1]; int frameTime = 0; int instant = 0; float value = 0f; int.TryParse(split[2], out frameTime); frame.frameTime = frameTime; int.TryParse(split[3], out instant); if (instant > 0) { frame.instant = true; } float.TryParse(split[4], out value); frame.value = value; myAnim.AddVarFrame(split[1], frame); } else if (split.Length > 2) { //Animation configuration string animName = split[0]; int loopVal = 0; int.TryParse(split[1], out loopVal); bool loop = false; if (loopVal > 0) { loop = true; } string goToAnim = split[2]; if (goToAnim.ToUpper() == "NA") { goToAnim = ""; } myAnim.AnimConfig(animName, loop, goToAnim); } } myAnim.isLoaded = true; Debug.Log(data[0]);//Done loading }
//Update all code to do with the animation itself public void update() { foreach (CustAnim anim in animations) { if (anim.name.ToUpper() == currentAnim.ToUpper()) { //This is our animation foreach (KeyValuePair <int, GameObject> pair in anim.assignedObjects) { //Animate each object KeyFrame prev = getPreviousFrame(pair.Value, pair.Key); KeyFrame next = getNextFrame(pair.Value, pair.Key); if (prev.animName != "NA" && next.animName != "NA") { //We can only animate if the frames exist if (prev.creationFrame) { if (prev.childOf > 0) { if (anim.assignedObjects.ContainsKey(prev.childOf)) { //Also make sure we are parented properly pair.Value.transform.parent = anim.assignedObjects[prev.childOf].transform; } } //Set the base value to start pair.Value.transform.localPosition = prev.position; pair.Value.transform.localEulerAngles = prev.rotation; pair.Value.transform.localScale = prev.scale; } if (next.instant) { //We don't interpolate, we just stay at the previous frame values pair.Value.transform.localPosition = prev.position; pair.Value.transform.localEulerAngles = prev.rotation; pair.Value.transform.localScale = prev.scale; } else { //Smooth interpolation between previous and next frame float percentage = (currTime - prev.frameTime) / (next.frameTime - prev.frameTime); if (float.IsNaN(percentage)) { percentage = 0f; } pair.Value.transform.localPosition = Vector3.Lerp(prev.position, next.position, percentage); pair.Value.transform.localEulerAngles = Vector3.Lerp(prev.rotation, next.rotation, percentage); pair.Value.transform.localScale = Vector3.Lerp(prev.scale, next.scale, percentage); } } } //Animate our variables List <string> modVars = new List <string>(); List <float> valVars = new List <float>(); foreach (KeyValuePair <string, float> pair in anim.variables) { VarFrame prev = getPreviousFrame(pair.Key); VarFrame next = getNextFrame(pair.Key); if (prev.animName != "NA" && next.animName != "NA") { if (next.instant) { //Stay at previous value modVars.Add(pair.Key); valVars.Add(prev.value); } else { //Smooth interpolation between previous and next frame float percentage = (currTime - prev.frameTime) / (next.frameTime - prev.frameTime); if (float.IsNaN(percentage)) { percentage = 0f; } modVars.Add(pair.Key); valVars.Add(Mathf.Lerp(prev.value, next.value, percentage)); } } } for (int i = 0; i < modVars.Count; i++) { anim.variables[modVars[i]] = valVars[i]; } //Timing and transitions if (isPlaying) { //Advance time and update currTime += 1000f * animSpeed * Time.deltaTime; } if (currTime >= anim.duration) { if (anim.loop) { currTime = 0f; //Restart the animation } else if (anim.goToAnim != "") { setAnim(anim.goToAnim); //Set the animation we are going to } else { isPlaying = false; //Done playing currTime = anim.duration; //Set to end frame } } break; } } }