public static void AddKeyIfChanged(this AnimationCurve curve, Keyframe keyframe) { var keys = curve.keys; //If this is the first key on this curve, always add //NOTE: Add TWO copies of the first frame, then we adjust the last frame as we move along //This guarantees a minimum of two keys in each curve if (keys.Length == 0) { curve.AddKey(keyframe); keyframe.time += float.Epsilon; curve.AddKey(keyframe); } else { //TODO: This method of keyframe reduction causes artifacts in animations that are supposed to deliberately pause //Find the last keyframe Keyframe lastKey = keys[keys.Length - 1]; if (lastKey.time >= keyframe.time) Debug.LogError("Keyframes not supplied in consecutive order!!!"); //Grab 2 frames ago var last2Key = keys[keys.Length - 2]; //If the previous 2 frames were different, add a new frame if (lastKey.value != last2Key.value) { curve.AddKey(keyframe); } //The previous frame is redundant - just move it else { curve.MoveKey(keys.Length - 1, keyframe); } } }
/// <summary> /// Sets all of the keys on the AnimationCurve to the given value. /// If there are no keys, we add one. /// </summary> /// <param name="extends">Extends.</param> /// <param name="value">Value.</param> public static void SetValue(this AnimationCurve extends, float value) { extends.Clear(); extends.AddKey(0.0f, value); extends.AddKey(1.0f, value); }
public static void AddKey(this AnimationCurve curve, Keyframe keyframe, TimelineKey lastKey) { var keys = curve.keys; //Early out - if this is the first key on this curve just add it if (keys.Length == 0) { curve.AddKey(keyframe); return; } if(lastKey == null) { Debug.Log(string.Format("ERROR: NULL lastkey passed to AddKey when curve contains {0} keys", keys.Length)); return; } //Get the last keyframe Keyframe lastKeyframe = keys[keys.Length - 1]; //If no TimelineKey is supplied, default to Linear curve CurveType curveType = lastKey.CurveType; switch (curveType) { case CurveType.Instant: lastKeyframe.outTangent = 0; curve.MoveKey(keys.Length - 1, lastKeyframe); keyframe.inTangent = float.PositiveInfinity; curve.AddKey(keyframe); break; case CurveType.Linear: var val = (keyframe.value - lastKeyframe.value) / (keyframe.time - lastKeyframe.time); lastKeyframe.outTangent = val; curve.MoveKey(keys.Length - 1, lastKeyframe); keyframe.inTangent = val; curve.AddKey(keyframe); break; case CurveType.Quadratic: { //Increase to cubic var c1 = (2 * lastKey.CurveParams[0]) / 3; var c2 = 1 - (2 * lastKey.CurveParams[0] + 1) / 3; //Convert [0,1] into unity-acceptable tangents c1 *= 3 * (keyframe.value - lastKeyframe.value) / (keyframe.time - lastKeyframe.time); c2 *= 3 * (keyframe.value - lastKeyframe.value) / (keyframe.time - lastKeyframe.time); //Set the out tangent for the previous frame and update lastKeyframe.outTangent = c1; curve.MoveKey(keys.Length - 1, lastKeyframe); //Set the in tangent for the current frame and add keyframe.inTangent = c2; curve.AddKey(keyframe); break; } case CurveType.Cubic: { //Get curve parameters var c1 = lastKey.CurveParams[0]; var c2 = 1 - lastKey.CurveParams[1]; //Convert [0,1] into unity-acceptable tangents c1 *= 3 * (keyframe.value - lastKeyframe.value) / (keyframe.time - lastKeyframe.time); c2 *= 3 * (keyframe.value - lastKeyframe.value) / (keyframe.time - lastKeyframe.time); //Set the out tangent for the previous frame and update lastKeyframe.outTangent = c1; curve.MoveKey(keys.Length - 1, lastKeyframe); //Set the in tangent for the current frame and add keyframe.inTangent = c2; curve.AddKey(keyframe); break; } default: Debug.LogWarning("CurveType " + curveType.ToString() + " not yet supported!"); break; } }
/// <summary> /// Add the specified key and set the in/out tangents for a linear curve /// </summary> public static void AddLinearKey(this AnimationCurve curve, Keyframe keyframe) { var keys = curve.keys; //Second or later keyframe - make the slopes linear if (keys.Length > 0) { var lastFrame = keys[keys.Length - 1]; float slope = (keyframe.value - lastFrame.value) / (keyframe.time - lastFrame.time); lastFrame.outTangent = keyframe.inTangent = slope; //Update the last keyframe curve.MoveKey(keys.Length - 1, lastFrame); } //Add the new frame curve.AddKey(keyframe); }
/// <summary> /// Reads file and loads key into agent /// </summary> /// <param name="aAgent">the agent</param> /// <param name="aFileName">pathname of file to read</param> /// <param name="aGetPassPhraseCallback">method that returns passphrase</param> /// <param name="aConstraints">additional constraints</param> /// <exception cref="AgentFailureException"> /// Agent returned SSH_AGENT_FAILURE /// </exception> /// <exception cref="KeyFormatterException"> /// File format was not recognized /// </exception> /// <exception cref="UnauthorizedAccessException"></exception> /// <exception cref="ArgumentException"></exception> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="PathTooLongException"></exception> /// <exception cref="DirectoryNotFoundException"></exception> /// <exception cref="FileNotFoundException"></exception> /// <exception cref="NotSupportedException"></exception> /// <returns>The ssh key that was read from the file</returns> public static ISshKey AddKeyFromFile(this IAgent aAgent, string aFileName, KeyFormatter.GetPassphraseCallback aGetPassPhraseCallback, ICollection<Agent.KeyConstraint> aConstraints = null) { string firstLine; using (var fileReader = File.OpenText(aFileName)) { firstLine = fileReader.ReadLine(); } var formatter = KeyFormatter.GetFormatter(firstLine); formatter.GetPassphraseCallbackMethod = aGetPassPhraseCallback; var key = formatter.DeserializeFile(aFileName); if (aConstraints != null) { foreach (var constraint in aConstraints) { key.AddConstraint(constraint); } } // prevent error in Pageant by attempting to remove key before adding it // this makes behavior more consistent with OpenSSH if (aAgent is PageantClient) { try { aAgent.RemoveKey (key); } catch (Exception) { /* error will occur if key is not loaded */ } } aAgent.AddKey(key); return key; }