public static void TestParallel() { CommandQueue queue = new CommandQueue(); double a = 0.0, b = 0.0, c = 0.0;; queue.Enqueue( Cmd.Repeat(2, Cmd.Parallel( Cmd.Duration((t) => a = t, 4.0), Cmd.Duration((t) => b = t, 3.0), Cmd.Duration((t) => { c = t; Assert.IsTrue(b < c, "Runner not operating con-currently."); Assert.IsTrue(a < b, "Runner not operating con-currently."); }, 2.0) ) ) ); while (!queue.Update(DELTA_TIME_RATE)) { } Assert.AreEqual(a, 1.0, 0.001); Assert.AreEqual(b, 1.0, 0.001); Assert.AreEqual(c, 1.0, 0.001); }
public static CommandDelegate ChangeTo(Ref <Rect> rect, Rect endRect, double duration, Vector2 anchorPoint, CommandEase ease = null) { CheckArgumentNonNull(rect, "rect"); Rect startRect = new Rect(); Vector2 startAnchorPoint = Vector2.zero; Vector2 endAnchorPoint = Vector2.zero; return(Cmd.Sequence( Cmd.Do(delegate() { startRect = rect.Value; startAnchorPoint = new Vector2( startRect.x + startRect.width * anchorPoint.x, startRect.y + startRect.height * anchorPoint.y ); endAnchorPoint = new Vector2( endRect.x + endRect.width * anchorPoint.x, endRect.y + endRect.height * anchorPoint.y ); }), Cmd.Duration(delegate(double t) { Rect newRect = new Rect(); newRect.width = (endRect.width - startRect.width) * (float)t + startRect.width; newRect.height = (endRect.height - startRect.height) * (float)t + startRect.height; Vector2 newAnchorPoint = Vector2.Lerp(startAnchorPoint, endAnchorPoint, (float)t); newRect.x = newAnchorPoint.x - anchorPoint.x * newRect.width; newRect.y = newAnchorPoint.y - anchorPoint.y * newRect.height; rect.Value = newRect; }, duration, ease) )); }
/// <summary> /// Oscillates around a value. This will animation from /// startValue > startValue + amount > startValue - amount- > startValue, /// in a smooth circular motion. /// </summary> /// <param name="amount"> /// The maximum amount to oscillate away from the default value. /// </param> public static CommandDelegate Oscillate(Ref <float> single, float amount, double duration, CommandEase ease = null) { CheckArgumentNonNull(single, "single"); float baseValue = 0f; return(Cmd.Sequence( Cmd.Do(() => baseValue = single.Value), Cmd.Duration(t => { single.Value = baseValue + Mathf.Sin((float)t * 2f * Mathf.PI) * amount; }, duration, ease) )); }
public static CommandDelegate TintTo(Ref <Color> color, Color endColor, double duration, CommandEase ease = null) { CheckArgumentNonNull(color, "color"); Color startColor = Color.white; return(Cmd.Sequence( Cmd.Do(delegate() { startColor = color.Value; }), Cmd.Duration(delegate(double t) { color.Value = Color.Lerp(startColor, endColor, (float)t); }, duration, ease) )); }
public static CommandDelegate ChangeTo(Ref <Vector2> vector, Vector2 endVector, double duration, CommandEase ease = null) { CheckArgumentNonNull(vector, "vector"); Vector2 startVector = Vector2.zero; return(Cmd.Sequence( Cmd.Do(delegate() { startVector = vector.Value; }), Cmd.Duration(delegate(double t) { vector.Value = (endVector - startVector) * (float)t + startVector; }, duration, ease) )); }
public static void TestTiming() { CommandQueue queue = new CommandQueue(); const double FIRST_Command_DURATION = 4.5; const double SECOND_Command_DURATION = 1.0; const double WAIT_DURATION = 1.5; const int REPEAT_COUNT = 8640; double lastT = 0.0; // This test ensures that between alternating CommandDurations, // there is no accumulation of error in timing. We use a repeat // here to accentuate the error. queue.Enqueue( Cmd.Repeat(REPEAT_COUNT, Cmd.Sequence( Cmd.WaitForSeconds(WAIT_DURATION), Cmd.Do(() => lastT = 0.0), Cmd.Duration((t) => { Assert.IsTrue(t <= 1.0); Assert.IsTrue(lastT <= t); lastT = t; }, FIRST_Command_DURATION), Cmd.Do(() => lastT = 0.0), Cmd.Parallel( Cmd.Duration((t) => {}, SECOND_Command_DURATION / 2.0), // The following two Duration Cmd should finish in the same Update call. Cmd.Duration((t) => {}, SECOND_Command_DURATION - (DELTA_TIME_RATE / 2.0)), Cmd.Duration((t) => { Assert.IsTrue(t <= 1.0); Assert.IsTrue(lastT <= t); lastT = t; }, SECOND_Command_DURATION) ) ) ) ); double totalTime = 0.0; while (!queue.Update(DELTA_TIME_RATE)) { totalTime += DELTA_TIME_RATE; } const double EXPECTED_TIME = (FIRST_Command_DURATION + SECOND_Command_DURATION + WAIT_DURATION) * REPEAT_COUNT; Assert.AreEqual(totalTime, EXPECTED_TIME, DELTA_TIME_RATE, "Time delta accumulation too large."); }
public static CommandDelegate TintBy(Ref <Color> color, Color offset, double duration, CommandEase ease = null) { CheckArgumentNonNull(color, "color"); double lastT = 0.0; return(Cmd.Sequence( Cmd.Do(delegate() { lastT = 0.0; }), Cmd.Duration(delegate(double t) { color.Value += offset * (float)(t - lastT); lastT = t; }, duration, ease) )); }
public static CommandDelegate ChangeBy(Ref <Vector2> vector, Vector2 offset, double duration, CommandEase ease = null) { CheckArgumentNonNull(vector, "vector"); double lastT = 0.0; return(Cmd.Sequence( Cmd.Do(delegate() { lastT = 0.0; }), Cmd.Duration(delegate(double t) { vector.Value += offset * (float)(t - lastT); lastT = t; }, duration, ease) )); }
public static CommandDelegate RotateFrom(Ref <Quaternion> rotation, Quaternion startRotation, double duration, CommandEase ease = null) { CheckArgumentNonNull(rotation, "rotation"); Quaternion endRotation = Quaternion.identity; return(Cmd.Sequence( Cmd.Do(delegate() { endRotation = rotation.Value; }), Cmd.Duration( delegate(double t) { rotation.Value = Quaternion.LerpUnclamped(startRotation, endRotation, (float)t); }, duration, ease) )); }
/// <summary> /// Performs a squash and stretch animation, while changing to a target scale. /// </summary> /// <param name="scale">The value to animate.</param> /// <param name="endScale">The final scale.</param> /// <param name="amplitude">The amplitude of a squash and strech</param> /// <param name="duration">The duration of the animation</param> /// <param name="normal"> The normal of the animation. </param> /// <param name="tangent"> The tangent of the animation. </param> public static CommandDelegate ScaleSquashAndStretchTo(Ref <Vector3> scale, Vector3 endScale, float amplitude, double duration, Vector3 normal, Vector3 tangent) { CheckArgumentNonNull(scale, "scale"); var squashRef = Ref <Vector3> .Create(Vector3.one); var scaleRef = Ref <Vector3> .Create(); return(Cmd.Sequence( Cmd.Do(() => scaleRef.Value = scale.Value), Cmd.Parallel( SquashAndStretch(squashRef, amplitude, duration, normal, tangent), Cmd.ChangeTo(scaleRef, endScale, duration / 4, Ease.Smooth()), Cmd.Duration(t => scale.Value = Vector3.Scale(squashRef.Value, scaleRef.Value), duration) ) )); }
public static CommandDelegate RotateBy(Ref <Quaternion> rotation, Quaternion offsetRotation, double duration, CommandEase ease = null) { CheckArgumentNonNull(rotation, "rotation"); double lastT = 0.0; return(Cmd.Sequence( Cmd.Do(delegate() { lastT = 0.0; }), Cmd.Duration(delegate(double t) { rotation.Value *= Quaternion.LerpUnclamped(Quaternion.identity, offsetRotation, (float)t) * Quaternion.Inverse(Quaternion.LerpUnclamped(Quaternion.identity, offsetRotation, (float)lastT)); lastT = t; }, duration, ease) )); }
public static void TestRunToEnd() { CommandQueue queue = new CommandQueue(); double time = 0.0; bool started = false; bool finished = false; queue.Enqueue( Cmd.Do(() => started = true), Cmd.Duration(t => time = t, 1.0), Cmd.Do(() => finished = true) ); Assert.AreEqual(false, started); queue.RunToEnd(); Assert.AreEqual(true, started); Assert.AreEqual(1.0, time); Assert.AreEqual(true, finished); }
public static CommandDelegate ScaleBy(Ref <Vector2> scale, Vector2 scaleFactor, double duration, CommandEase ease = null) { CheckArgumentNonNull(scale, "scale"); Vector2 lastScaleFactor = Vector2.one; return(Cmd.Sequence( Cmd.Do(delegate() { lastScaleFactor = Vector2.one; }), Cmd.Duration(delegate(double t) { Vector2 newScaleFactor = (float)t * (scaleFactor - Vector2.one) + Vector2.one; scale.Value = new Vector2( scale.Value.x * newScaleFactor.x / lastScaleFactor.x, scale.Value.y * newScaleFactor.y / lastScaleFactor.y ); lastScaleFactor = newScaleFactor; }, duration, ease) )); }
public static CommandDelegate TintBy(Ref <Color32> color, Color32 offset, double duration, CommandEase ease = null) { CheckArgumentNonNull(color, "color"); double lastT = 0.0; return(Cmd.Sequence( Cmd.Do(delegate() { lastT = 0.0; }), Cmd.Duration(delegate(double t) { color.Value = new Color32( (byte)(color.Value.r + offset.r * (t - lastT)), (byte)(color.Value.g + offset.g * (t - lastT)), (byte)(color.Value.b + offset.b * (t - lastT)), (byte)(color.Value.a + offset.a * (t - lastT)) ); lastT = t; }, duration, ease) )); }
/// <summary> /// Wobble a value. This oscilates a value, with a decay. /// </summary> /// <param name="amplitude">Amplitude.</param> /// <param name="duration">Duration.</param> public static CommandDelegate Wobble(Ref <float> single, float amount, double duration) { CheckArgumentNonNull(single, "val"); float intervals = 3f; float decay = Mathf.Log(100f * amount); float baseVal = 0f; return(Cmd.Sequence( Cmd.Do(() => { baseVal = single.Value; }), Cmd.Duration( t => { float decayCoeef = Mathf.Exp((float)t * decay); single.Value = baseVal + amount * Mathf.Sin(intervals * (float)t * 2 * Mathf.PI) / decayCoeef; }, duration ), Cmd.Do(() => { single.Value = baseVal; }) )); }
/// <summary> /// Squashes the y axis, while inversely stretching the x axis. /// </summary> /// <param name="val">The value to animate.</param> /// <param name="amplitude">The size of the squash.</param> /// <param name="duration">The duration of the squash.</param> public static CommandDelegate SquashAndStretch(Ref <Vector2> scale, float amplitude, double duration) { CheckArgumentNonNull(scale, "scale"); Vector2 startScale = Vector2.zero; float area = 0f; Ref <float> widthRef = new Ref <float>( () => scale.Value.x, (t) => { Vector2 tempVal = scale.Value; tempVal.x = t; scale.Value = tempVal; } ); return(Cmd.Sequence( Cmd.Do(() => { area = scale.Value.x * scale.Value.y; startScale = scale.Value; }), Cmd.Parallel( Wobble(widthRef, amplitude, duration), Cmd.Duration((t) => { Vector2 tempVal = scale.Value; if (tempVal.x != 0f) { tempVal.y = area / tempVal.x; } scale.Value = tempVal; }, duration) ), Cmd.Do(() => { scale.Value = startScale; }) )); }