2296 lines
76 KiB
C#
2296 lines
76 KiB
C#
// ReSharper disable AnnotateNotNullParameter
|
|
#if TEST_FRAMEWORK_INSTALLED
|
|
using System;
|
|
using System.Collections;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading.Tasks;
|
|
using JetBrains.Annotations;
|
|
using NUnit.Framework;
|
|
using PrimeTween;
|
|
using UnityEngine;
|
|
using UnityEngine.TestTools;
|
|
using Assert = NUnit.Framework.Assert;
|
|
using Object = UnityEngine.Object;
|
|
using Random = UnityEngine.Random;
|
|
|
|
public partial class Tests {
|
|
[UnityTest]
|
|
public IEnumerator ElapsedTime() {
|
|
var timeStart = Time.time;
|
|
var d1 = getDt() * 4f;
|
|
var d2 = getDt() * 2f;
|
|
var c1 = 2;
|
|
var c2 = 3;
|
|
var c3 = 2;
|
|
var seq = Tween.Custom(0, 1, d1, delegate { }, cycles: c1)
|
|
.Chain(Tween.Custom(0, 1, d2, delegate { }, cycles: c2));
|
|
seq.SetRemainingCycles(c3);
|
|
Assert.AreEqual((d1 * c1 + d2 * c2) * c3, seq.durationTotal, 0.00001f);
|
|
while (seq.isAlive) {
|
|
var expected = Time.time - timeStart;
|
|
// Debug.Log($"expected {expected} / elapsedTimeTotal {seq.elapsedTimeTotal}");
|
|
if (seq.cyclesDone == 0) {
|
|
Assert.AreEqual(expected, seq.elapsedTime, 0.001f);
|
|
}
|
|
Assert.AreEqual(expected, seq.elapsedTimeTotal, getDt() * 2); // fails with lower tolerance because Sequence doesn't measure the elapsedTimeTotal, but calculates it from duration * cyclesDone
|
|
yield return null;
|
|
}
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator SequenceNestingCycles() {
|
|
float duration = getDt();
|
|
{
|
|
int numCompleted = 0;
|
|
var s1 = Sequence.Create(Tween.Delay(duration, () => numCompleted++));
|
|
yield return Sequence.Create(Tween.Delay(duration))
|
|
.Chain(s1)
|
|
.ToYieldInstruction();
|
|
Assert.AreEqual(1, numCompleted);
|
|
}
|
|
{
|
|
int numCompleted = 0;
|
|
var s1 = Sequence.Create(Tween.Delay(duration, () => numCompleted++));
|
|
yield return Sequence.Create(2)
|
|
.Chain(Tween.Delay(duration))
|
|
.Chain(s1)
|
|
.ToYieldInstruction();
|
|
Assert.AreEqual(2, numCompleted);
|
|
}
|
|
{
|
|
int numCompleted = 0;
|
|
var s1 = Sequence.Create(2)
|
|
.Chain(Tween.Delay(duration, () => numCompleted++));
|
|
|
|
yield return Sequence.Create(2)
|
|
.Chain(Tween.Delay(duration))
|
|
.Chain(s1)
|
|
.ToYieldInstruction();
|
|
Assert.AreEqual(4, numCompleted);
|
|
}
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator SequenceNestingDepsChain() {
|
|
const float duration = 100f;
|
|
var s1 = Sequence.Create(Tween.Delay(duration));
|
|
var t1 = Tween.Delay(duration);
|
|
var t2 = Tween.Delay(duration);
|
|
var s2 = Sequence.Create(t1).Group(t2);
|
|
s1.Chain(s2);
|
|
Assert.AreEqual(duration, s2.root.tween.waitDelay);
|
|
Assert.AreEqual(0f, t1.tween.waitDelay);
|
|
Assert.AreEqual(0f, t2.tween.waitDelay);
|
|
yield return null;
|
|
Assert.AreEqual(0f, t1.elapsedTime);
|
|
Assert.AreEqual(0f, t2.elapsedTime);
|
|
s1.Stop();
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator SequenceNestingDepsGroup() {
|
|
const float duration = 100f;
|
|
var t1 = Tween.Delay(duration);
|
|
var t2 = Tween.Delay(duration);
|
|
var nested = Sequence.Create(t1).Group(t2);
|
|
var seq = Sequence.Create(Tween.Delay(duration))
|
|
.ChainDelay(duration)
|
|
.Group(nested);
|
|
Assert.AreEqual(0, t1.tween.waitDelay);
|
|
Assert.AreEqual(0, t2.tween.waitDelay);
|
|
yield return null;
|
|
Assert.AreEqual(0, t1.elapsedTime);
|
|
Assert.AreEqual(0, t2.elapsedTime);
|
|
seq.Stop();
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator SequenceNestingAfterTweenChainOp() {
|
|
var duration = 0.001f + Random.value * 0.05f; // longest
|
|
var s1 = Sequence.Create(Tween.Delay(duration));
|
|
var s2 = Sequence.Create();
|
|
s1.Chain(s2);
|
|
|
|
var t1 = Tween.Delay(0.01f);
|
|
s1.Chain(t1);
|
|
Assert.AreEqual(duration, t1.tween.waitDelay);
|
|
|
|
var t2 = Tween.Delay(0.01f);
|
|
s1.Group(t2);
|
|
Assert.AreEqual(duration, t2.tween.waitDelay);
|
|
|
|
yield return s1.ToYieldInstruction();
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator SequenceNestingChainOrder() {
|
|
var t1 = Tween.Delay(0.01f);
|
|
var s1 = Sequence.Create(t1);
|
|
var t2 = Tween.Delay(0.05f);
|
|
s1.Chain(t2);
|
|
|
|
var t3 = Tween.Delay(0.01f);
|
|
var t4 = Tween.Delay(0.01f);
|
|
var s2 = Sequence.Create(t3).Group(t4);
|
|
s1.Chain(s2);
|
|
Assert.AreEqual(t2.durationWithWaitDelay, s2.root.tween.waitDelay);
|
|
Assert.AreEqual(0f, t3.tween.waitDelay);
|
|
Assert.AreEqual(0f, t4.tween.waitDelay);
|
|
var t5 = Tween.Delay(0.01f);
|
|
s1.Group(t5);
|
|
Assert.AreEqual(t2.durationWithWaitDelay, t5.tween.waitDelay);
|
|
yield return s1.ToYieldInstruction();
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator SequenceNestingGroupOrder() {
|
|
const float t1Dur = 0.017f;
|
|
var t1 = Tween.Delay(t1Dur);
|
|
var s1 = Sequence.Create(t1);
|
|
const float longestDur = 0.05f;
|
|
var t2 = Tween.Delay(longestDur);
|
|
s1.Chain(t2);
|
|
Assert.AreEqual(t1.durationWithWaitDelay, t2.tween.waitDelay);
|
|
var t3 = Tween.Delay(0.01f);
|
|
s1.Group(t3);
|
|
Assert.AreEqual(t1.durationWithWaitDelay, t3.tween.waitDelay);
|
|
|
|
var s2 = Sequence.Create(Tween.Delay(0.01f));
|
|
var t4 = Tween.Delay(0.01f);
|
|
s2.Group(t4);
|
|
|
|
s1.Group(s2);
|
|
Assert.AreEqual(0f, t4.tween.waitDelay);
|
|
|
|
var t5 = Tween.Delay(0.01f);
|
|
s1.Group(t5);
|
|
Assert.AreEqual(t1Dur, t5.tween.waitDelay);
|
|
|
|
var t6 = Tween.Delay(0.01f);
|
|
var seqDur = s1.durationTotal;
|
|
s1.Chain(t6);
|
|
Assert.AreEqual(seqDur, t6.tween.waitDelay);
|
|
|
|
yield return s1.ToYieldInstruction();
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator SequenceNestingRestart() {
|
|
int numCallback = 0;
|
|
yield return Sequence.Create(2)
|
|
.Chain(Tween.Delay(0.01f))
|
|
.Chain(Sequence.Create(Tween.Delay(0.01f)))
|
|
.ChainCallback(() => numCallback++)
|
|
.ToYieldInstruction();
|
|
Assert.AreEqual(2, numCallback);
|
|
}
|
|
|
|
[Test]
|
|
public void SequenceNestingPause2() {
|
|
{
|
|
var s1 = Sequence.Create();
|
|
|
|
var s2 = Sequence.Create();
|
|
s2.isPaused = true;
|
|
LogAssert.Expect(LogType.Error, new Regex("'isPaused' was ignored after adding"));
|
|
s1.Group(s2);
|
|
expectCantManipulateTweenInsideSequence();
|
|
_ = s2.isPaused;
|
|
s1.Complete();
|
|
}
|
|
{
|
|
var s1 = Sequence.Create();
|
|
s1.isPaused = true;
|
|
var s2 = Sequence.Create();
|
|
s2.isPaused = true;
|
|
s1.Chain(s2);
|
|
expectCantManipulateTweenInsideSequence();
|
|
_ = s2.isPaused;
|
|
s1.Complete();
|
|
LogAssert.NoUnexpectedReceived();
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void SequenceNestingPause() {
|
|
var s = Sequence.Create(Tween.Delay(0.01f))
|
|
.Chain(Sequence.Create(Tween.Delay(0.01f)));
|
|
Assert.AreEqual(1, numNestedSequences(s));
|
|
s.isPaused = true;
|
|
int count = 0;
|
|
foreach (var t in s.getAllChildren()) {
|
|
count++;
|
|
var child = t;
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
expectCantManipulateTweenInsideSequence();
|
|
child.isPaused = !child.isPaused;
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
expectCantManipulateTweenInsideSequence();
|
|
child.timeScale += 1f;
|
|
}
|
|
Assert.AreEqual(3, count);
|
|
|
|
s.isPaused = false;
|
|
count = 0;
|
|
foreach (var _ in s.getAllTweens()) {
|
|
count++;
|
|
}
|
|
Assert.AreEqual(4, count);
|
|
}
|
|
|
|
[Test]
|
|
public void SequenceNestingLongestTween() {
|
|
float dur = Random.value + 0.1f;
|
|
var t = Tween.Delay(dur);
|
|
var sequence = Sequence.Create(Tween.Delay(dur))
|
|
.Chain(Sequence.Create(Tween.Delay(dur)))
|
|
.Chain(Sequence.Create(t));
|
|
Assert.AreEqual(dur * 3, sequence.durationTotal, 0.0001f);
|
|
sequence.Stop();
|
|
Assert.IsFalse(t.isAlive);
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator SequenceNestingStopChildInTheMiddle() {
|
|
Tween.StopAll();
|
|
int numS1Completed = 0;
|
|
int numS2Completed = 0;
|
|
int numS3Completed = 0;
|
|
float duration = minDuration * Random.Range(1f, 10f);
|
|
var s1 = Sequence.Create(Tween.Delay(duration, () => {
|
|
Assert.AreEqual(0, numS1Completed);
|
|
Assert.AreEqual(0, numS3Completed);
|
|
numS1Completed++;
|
|
}));
|
|
var s2 = Sequence.Create(Tween.Delay(duration, () => numS2Completed++));
|
|
var s3 = Sequence.Create(Tween.Delay(duration, () => {
|
|
Assert.AreEqual(1, numS1Completed);
|
|
Assert.AreEqual(0, numS3Completed);
|
|
numS3Completed++;
|
|
}));
|
|
s1.Chain(s2).Chain(s3);
|
|
Assert.AreEqual(2, numNestedSequences(s1));
|
|
expectCantManipulateTweenInsideSequence();
|
|
s2.Stop();
|
|
Assert.AreEqual(2, numNestedSequences(s1));
|
|
yield return s1.ToYieldInstruction();
|
|
Assert.AreEqual(1, numS1Completed);
|
|
Assert.AreEqual(1, numS2Completed);
|
|
Assert.AreEqual(1, numS3Completed);
|
|
yield return null;
|
|
Assert.AreEqual(0, tweensCount);
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator SequenceNestingCompleteLastChild() {
|
|
var duration = getDt();
|
|
var s1 = Sequence.Create(Tween.Delay(duration));
|
|
var s2 = Sequence.Create(Tween.Delay(duration));
|
|
s1.Chain(s2);
|
|
Assert.AreEqual(1, numNestedSequences(s1));
|
|
expectCantManipulateTweenInsideSequence();
|
|
s2.Complete();
|
|
Assert.AreEqual(1, numNestedSequences(s1));
|
|
Assert.IsTrue(s2.isAlive);
|
|
Assert.IsTrue(s1.isAlive);
|
|
yield return s1.ToYieldInstruction();
|
|
}
|
|
|
|
static int numNestedSequences(Sequence seq) {
|
|
Assert.IsTrue(seq.isAlive);
|
|
int result = 0;
|
|
foreach (var t in seq.getAllTweens()) {
|
|
if (t.tween.isSequenceRoot() && !t.tween.isMainSequenceRoot()) {
|
|
result++;
|
|
}
|
|
}
|
|
Assert.IsTrue(result >= 0);
|
|
return result;
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator SequenceNesting() {
|
|
if (tweensCount > 0) {
|
|
Tween.StopAll();
|
|
Assert.AreEqual(0, tweensCount);
|
|
}
|
|
int numS1Completed = 0;
|
|
int numS2Completed = 0;
|
|
var s1 = Sequence.Create(Tween.Delay(0.02f, () => {
|
|
// Debug.Log("1");
|
|
Assert.AreEqual(0, numS1Completed);
|
|
Assert.AreEqual(0, numS2Completed);
|
|
numS1Completed++;
|
|
}));
|
|
var s2 = Sequence.Create(Tween.Delay(0.01f, () => {
|
|
// Debug.Log("2");
|
|
Assert.AreEqual(1, numS1Completed);
|
|
Assert.AreEqual(0, numS2Completed);
|
|
numS2Completed++;
|
|
}));
|
|
s1.Chain(s2);
|
|
Assert.AreEqual(1, numNestedSequences(s1));
|
|
yield return s1.ToYieldInstruction();
|
|
Assert.AreEqual(1, numS1Completed);
|
|
Assert.AreEqual(1, numS2Completed);
|
|
yield return null;
|
|
Assert.AreEqual(0, tweensCount);
|
|
}
|
|
|
|
[Test]
|
|
public void SequenceNestingDifferentSettings() {
|
|
var seq = Sequence.Create();
|
|
seq.timeScale = Random.Range(0.01f, 1.5f);
|
|
|
|
expectErrors();
|
|
seq.Group(createSequenceWithNonDefaultSettings());
|
|
|
|
expectErrors();
|
|
seq.Chain(createSequenceWithNonDefaultSettings());
|
|
LogAssert.NoUnexpectedReceived();
|
|
|
|
return;
|
|
|
|
static void expectErrors() {
|
|
LogAssert.Expect(LogType.Error, new Regex("'isPaused' was ignored after adding"));
|
|
LogAssert.Expect(LogType.Error, new Regex("'timeScale' was ignored after adding"));
|
|
LogAssert.Expect(LogType.Error, new Regex("'useUnscaledTime' was ignored after adding"));
|
|
LogAssert.Expect(LogType.Error, new Regex("'updateType' was ignored after adding"));
|
|
}
|
|
|
|
static Sequence createSequenceWithNonDefaultSettings() {
|
|
var s2 = Sequence.Create(useUnscaledTime: true, updateType: UpdateType.FixedUpdate);
|
|
s2.isPaused = true;
|
|
s2.timeScale = 0.5f;
|
|
return s2;
|
|
}
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator SequenceNestingInfinite() {
|
|
var s1 = Sequence.Create();
|
|
var infSeq = Sequence.Create(cycles: -1);
|
|
expectInfiniteTweenInSequenceError();
|
|
s1.Group(infSeq);
|
|
|
|
expectInfiniteTweenInSequenceError();
|
|
s1.Chain(infSeq);
|
|
|
|
yield return null;
|
|
infSeq.Complete();
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator GetSequenceElapsedTimeWhenAllTargetsDestroyed() {
|
|
var target = new GameObject();
|
|
var s = Sequence.Create(Tween.Delay(target, 0.1f));
|
|
Object.DestroyImmediate(target);
|
|
Assert.IsTrue(s.isAlive);
|
|
var _ = s.elapsedTime;
|
|
yield return s.ToYieldInstruction();
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator StopAllWhenSequenceHasCompletedTweenAndTargetDestroyed() {
|
|
var target = new GameObject();
|
|
var duration = getDt() * 5f;
|
|
var t = Tween.Delay(target, duration);
|
|
int numCompleted = 0;
|
|
var s = Sequence.Create(t)
|
|
.Chain(Tween.Delay(target, duration, () => numCompleted++));
|
|
while (t.interpolationFactor < 1f) {
|
|
yield return null;
|
|
}
|
|
Assert.IsTrue(t.isAlive);
|
|
Assert.IsTrue(s.isAlive);
|
|
int aliveCount = 0;
|
|
foreach (var _ in s.getAllTweens()) {
|
|
if (_.isAlive) {
|
|
aliveCount++;
|
|
}
|
|
}
|
|
Assert.AreEqual(3, aliveCount, "tweens now always alive while their sequence is alive");
|
|
Object.DestroyImmediate(target);
|
|
Assert.AreEqual(3, tweensCount);
|
|
expectOnCompleteIgnored();
|
|
var numCompleteAll = Tween.CompleteAll();
|
|
Assert.AreEqual(3, numCompleteAll);
|
|
Assert.AreEqual(0, numCompleted);
|
|
Assert.AreEqual(0, tweensCount);
|
|
Assert.AreEqual(0, numCompleted);
|
|
LogAssert.NoUnexpectedReceived();
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator StopAllWhenSequenceHasCompletedTween() {
|
|
var duration = getDt() * 10f;
|
|
var t = Tween.Delay(duration);
|
|
var s = Sequence.Create(t)
|
|
.ChainDelay(duration);
|
|
while (t.interpolationFactor < 1f) {
|
|
yield return null;
|
|
}
|
|
Assert.IsTrue(t.isAlive);
|
|
Assert.IsTrue(s.isAlive);
|
|
Assert.AreEqual(3, tweensCount);
|
|
Tween.StopAll();
|
|
Assert.AreEqual(0, tweensCount);
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator StopSequenceFromCallback() {
|
|
var aliveCount = tweensCount;
|
|
if (aliveCount > 0) {
|
|
Assert.AreEqual(Tween.StopAll(null), aliveCount);
|
|
}
|
|
Sequence s = default;
|
|
s = Sequence.Create()
|
|
.ChainCallback(() => {
|
|
s.Stop();
|
|
Assert.IsFalse(s.isAlive);
|
|
});
|
|
yield return s.ToYieldInstruction();
|
|
yield return null;
|
|
Assert.AreEqual(0, tweensCount);
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator ExceptionInOnCompleteNestedSequence() {
|
|
var aliveCount = tweensCount;
|
|
if (aliveCount > 0) {
|
|
Assert.AreEqual(Tween.StopAll(), aliveCount);
|
|
}
|
|
var main = Sequence.Create(Tween.Delay(getDt() * 2));
|
|
expectOnCompleteException();
|
|
var nested = Sequence.Create().ChainCallback(() => throw new Exception());
|
|
main.Group(nested);
|
|
yield return main.ToYieldInstruction();
|
|
yield return null;
|
|
Assert.AreEqual(0, tweensCount);
|
|
LogAssert.NoUnexpectedReceived();
|
|
}
|
|
|
|
static void expectOnCompleteException() {
|
|
LogAssert.Expect(LogType.Error, new Regex("Tween's onComplete callback raised exception"));
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator ExceptionInOnValueChangeNestedSequence() {
|
|
var aliveCount = tweensCount;
|
|
if (aliveCount > 0) {
|
|
Assert.AreEqual(Tween.StopAll(null), aliveCount);
|
|
}
|
|
var main = Sequence.Create(Tween.Delay(getDt() * 2));
|
|
expectTweenWasStoppedBecauseException();
|
|
var nested = Sequence.Create(Tween.Custom(0f, 1f, getDt() * 2, delegate { throw new Exception(); }));
|
|
main.Group(nested);
|
|
yield return main.ToYieldInstruction();
|
|
yield return null;
|
|
Assert.AreEqual(0, tweensCount);
|
|
LogAssert.NoUnexpectedReceived();
|
|
}
|
|
|
|
[Test]
|
|
public async Task SequenceLongestTween() {
|
|
{
|
|
var t1 = Tween.Delay(0.01f);
|
|
var t2 = Tween.Delay(0.02f);
|
|
var s = t1.Group(t2);
|
|
Assert.AreEqual(t2.durationTotal, s.durationTotal);
|
|
await s;
|
|
}
|
|
{
|
|
var t1 = Tween.Delay(0.01f);
|
|
var t2 = Tween.Delay(0.02f);
|
|
var s = t2.Group(t1);
|
|
Assert.AreEqual(t2.durationTotal, s.durationTotal);
|
|
}
|
|
{
|
|
var t1 = Tween.Delay(0.01f);
|
|
var t2 = Tween.Delay(0.02f);
|
|
var s = t1.Chain(t2);
|
|
Assert.AreEqual(t1.durationTotal + t2.durationTotal, s.durationTotal);
|
|
}
|
|
{
|
|
var t1 = Tween.Delay(0.01f);
|
|
var t2 = Tween.Delay(0.02f);
|
|
var s = t2.Chain(t1);
|
|
Assert.AreEqual(t1.durationTotal + t2.durationTotal, s.durationTotal);
|
|
}
|
|
{
|
|
var t1 = Tween.PositionX(transform, 1f, 0.1f, cycles: 3); // longest
|
|
var t2 = Tween.PositionX(transform, 1f, 0.1f);
|
|
var s = t1.Group(t2);
|
|
Assert.AreEqual(t1.durationTotal, s.durationTotal);
|
|
}
|
|
{
|
|
var t1 = Tween.PositionX(transform, 1f, 0.1f, cycles: 3);
|
|
var t2 = Tween.PositionX(transform, 1f, 0.1f);
|
|
var s = t1.Chain(t2);
|
|
Assert.AreEqual(t1.durationTotal + t2.durationTotal, s.durationTotal);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public async Task AwaitFinishedSequence() {
|
|
var t = Tween.Delay(0.01f);
|
|
var s = Sequence.Create(t);
|
|
await s;
|
|
Assert.IsTrue(s.IsCreated);
|
|
Assert.IsFalse(s.isAlive);
|
|
await s;
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator SequenceRestartFromTo() {
|
|
for (int i = 0; i < 1; i++) {
|
|
var target = new GameObject(nameof(SequenceRestartFromTo)).transform;
|
|
Assert.AreEqual(Vector3.zero, target.localPosition);
|
|
var s = Tween.LocalPositionX(target, new TweenSettings<float>(0f, 1f, getDt() * 2f))
|
|
.Chain(Tween.LocalPositionX(target, new TweenSettings<float>(1f, 0.5f, getDt())));
|
|
s.SetRemainingCycles(2);
|
|
if (Random.value < 0.5f) {
|
|
s.Complete();
|
|
} else {
|
|
yield return s.ToYieldInstruction();
|
|
}
|
|
UnityEngine.Assertions.Assert.AreApproximatelyEqual(0.5f, target.localPosition.x);
|
|
Object.Destroy(target.gameObject);
|
|
}
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator SequenceRestartTo() {
|
|
var target = new GameObject(nameof(SequenceRestartTo)).transform;
|
|
Assert.AreEqual(Vector3.zero, target.localPosition);
|
|
var duration = getDt() * 3f;
|
|
var s = Tween.LocalPositionX(target, 1f, duration)
|
|
.Chain(Tween.LocalPositionX(target, 0.5f, duration));
|
|
s.SetRemainingCycles(2);
|
|
if (Random.value < 0.5f) {
|
|
s.Complete();
|
|
} else {
|
|
yield return s.ToYieldInstruction();
|
|
}
|
|
UnityEngine.Assertions.Assert.AreApproximatelyEqual(0.5f, target.localPosition.x);
|
|
Object.Destroy(target.gameObject);
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator SequenceRestartWhenTweenHaveStartDelay() {
|
|
var data = new TweenSettings<Vector3>(Vector3.zero, Vector3.one, getDt() * Random.Range(0.5f, 2f), startDelay: getDt() * Random.Range(0.5f, 2f));
|
|
var t1 = Tween.Position(transform, data);
|
|
var t2 = Tween.Position(transform, data);
|
|
PrimeTweenConfig.warnStructBoxingAllocationInCoroutine = true;
|
|
expectCoroutineBoxingWarning();
|
|
var seq = t1.Chain(t2);
|
|
seq.SetRemainingCycles(2);
|
|
yield return seq;
|
|
LogAssert.NoUnexpectedReceived();
|
|
}
|
|
|
|
static void expectCoroutineBoxingWarning() {
|
|
LogAssert.Expect(LogType.Warning, new Regex("Please use Tween/Sequence.ToYieldInstruction"));
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator StopAllWhenTweenInSequenceIsCompleted() {
|
|
var target = new object();
|
|
var duration = getDt() * 2f;
|
|
var t1 = Tween.Delay(target, duration);
|
|
var t2 = Tween.Delay(target, duration);
|
|
yield return t1.Chain(t2).ToYieldInstruction();
|
|
Tween.StopAll(target);
|
|
Tween.SetPausedAll(true, target);
|
|
Tween.SetPausedAll(false, target);
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator SequenceElapsedTime() {
|
|
yield return null;
|
|
float dt = getDt();
|
|
var dur1 = dt * Random.Range(2, 5);
|
|
var dur2 = dt * Random.Range(2, 5);
|
|
var cycles1 = Random.Range(1, 4);
|
|
var cycles2 = Random.Range(1, 4);
|
|
var t1 = Tween.Position(transform, Vector3.one, dur1, cycles: cycles1);
|
|
var t2 = Tween.Position(transform, Vector3.one, dur2, cycles: cycles2);
|
|
var s = Sequence.Create(t1)
|
|
.Chain(t2);
|
|
|
|
float timeStart = Time.time;
|
|
Assert.IsTrue(t1.isAlive);
|
|
while (t1.interpolationFactor < 1f) {
|
|
yield return null;
|
|
}
|
|
Assert.AreEqual(dur1 * cycles1, Time.time - timeStart, Time.deltaTime);
|
|
|
|
Assert.IsTrue(s.isAlive);
|
|
yield return s;
|
|
Assert.AreEqual(dur1 * cycles1 + dur2 * cycles2, Time.time - timeStart, Time.deltaTime);
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator DefaultPropertiesOfSequence() {
|
|
{
|
|
Assert.AreEqual(0, tweensCount);
|
|
var duration = 0.001f;
|
|
var s = Sequence.Create(-1).Chain(Tween.Delay(duration));
|
|
Assert.AreEqual(-1, s.cyclesTotal);
|
|
Assert.AreEqual(duration, s.duration);
|
|
Assert.IsTrue(float.IsPositiveInfinity(s.durationTotal));
|
|
|
|
yield return null;
|
|
const int expectedCount = 2;
|
|
Assert.AreEqual(expectedCount, tweensCount);
|
|
yield return null;
|
|
Assert.AreEqual(expectedCount, tweensCount);
|
|
yield return null;
|
|
Assert.AreEqual(expectedCount, tweensCount);
|
|
s.Stop();
|
|
Assert.AreEqual(expectedCount, tweensCount);
|
|
yield return null;
|
|
Assert.AreEqual(0, tweensCount);
|
|
}
|
|
{
|
|
var s = Sequence.Create();
|
|
Assert.AreEqual(1, s.cyclesTotal);
|
|
validate(s);
|
|
}
|
|
{
|
|
var s = Sequence.Create();
|
|
validate(s);
|
|
}
|
|
|
|
void validate(Sequence s) {
|
|
Assert.AreEqual(0, s.duration);
|
|
Assert.AreEqual(0, s.durationTotal);
|
|
Assert.AreEqual(0, s.progress);
|
|
Assert.AreEqual(0, s.progressTotal);
|
|
Assert.AreEqual(0, s.cyclesDone);
|
|
Assert.AreEqual(0, s.elapsedTime);
|
|
Assert.AreEqual(0, s.elapsedTimeTotal);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public async Task SequenceProperties() {
|
|
for (int i = 0; i < 1; i++) {
|
|
int cyclesDone = 0;
|
|
Tween tween = default;
|
|
var duration = Mathf.Max(TweenSettings.minDuration, getDt() * Random.Range(0.5f, 6f));
|
|
var sequenceCycles = Random.Range(2, 5);
|
|
// const float duration = 0.1f;
|
|
// const int sequenceCycles = 2;
|
|
Sequence sequence = default;
|
|
validateSequenceDefaultProps(false);
|
|
sequence = Sequence.Create(sequenceCycles);
|
|
float timeStart = Time.time;
|
|
tween = Tween.Custom(transform, 0, 1, duration, ease: Ease.Linear, onValueChange: (_, val) => {
|
|
// Debug.Log($"elapsedTimeTotal: {sequence.elapsedTimeTotal}, val: {val}");
|
|
Assert.IsTrue(tween.isAlive);
|
|
Assert.IsTrue(sequence.isAlive);
|
|
UnityEngine.Assertions.Assert.AreApproximatelyEqual(sequence.duration, duration);
|
|
var durationTotalExpected = duration * sequenceCycles;
|
|
UnityEngine.Assertions.Assert.AreApproximatelyEqual(sequence.durationTotal, durationTotalExpected);
|
|
Assert.AreEqual(tween.duration, duration);
|
|
Assert.AreEqual(tween.durationTotal, duration);
|
|
var elapsedTimeExpected = Time.time - timeStart;
|
|
if (val < 1f) {
|
|
if (sequence.cyclesDone == 0) {
|
|
UnityEngine.Assertions.Assert.AreApproximatelyEqual(sequence.elapsedTime, tween.elapsedTime);
|
|
UnityEngine.Assertions.Assert.AreApproximatelyEqual(tween.elapsedTime, elapsedTimeExpected);
|
|
UnityEngine.Assertions.Assert.AreApproximatelyEqual(sequence.elapsedTime, elapsedTimeExpected);
|
|
}
|
|
if (sequence.root.tween.elapsedTimeTotal >= 0f) {
|
|
Assert.AreEqual(elapsedTimeExpected, sequence.elapsedTimeTotal, getDt());
|
|
Assert.AreEqual(sequence.progress, Mathf.Clamp01(sequence.elapsedTime / sequence.duration));
|
|
Assert.AreEqual(sequence.progressTotal, Mathf.Clamp01(elapsedTimeExpected / durationTotalExpected), 0.001f);
|
|
}
|
|
}
|
|
});
|
|
#pragma warning disable 4014
|
|
sequence.Group(tween);
|
|
#pragma warning restore
|
|
await sequence.ChainCallback(() => cyclesDone++);
|
|
Assert.AreEqual(sequenceCycles, cyclesDone);
|
|
Assert.IsFalse(sequence.isAlive);
|
|
validateSequenceDefaultProps(true);
|
|
Assert.IsFalse(tween.isAlive);
|
|
|
|
void validateSequenceDefaultProps(bool isCreated) {
|
|
for (int j = 0; j < 8; j++) {
|
|
expectIsDeadError(isCreated);
|
|
}
|
|
Assert.AreEqual(0, sequence.elapsedTime);
|
|
Assert.AreEqual(0, sequence.elapsedTimeTotal);
|
|
Assert.AreEqual(0, sequence.cyclesDone);
|
|
Assert.AreEqual(0, sequence.cyclesTotal);
|
|
Assert.AreEqual(0, sequence.duration);
|
|
Assert.AreEqual(0, sequence.durationTotal);
|
|
Assert.AreEqual(0, sequence.progress);
|
|
Assert.AreEqual(0, sequence.progressTotal);
|
|
}
|
|
}
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator ExceptionInSequenceOnCycleComplete() {
|
|
int numExceptions = 0;
|
|
Sequence s = default;
|
|
s = Sequence.Create(2, CycleMode.Restart)
|
|
.Chain(Tween.Delay(getDt()))
|
|
.Chain(Tween.Custom(0f, 1f, getDt(), val => {
|
|
// print($"{s.cyclesDone}, {val}");
|
|
if (s.cyclesDone == 1 && val == 0f) {
|
|
numExceptions++;
|
|
expectTweenWasStoppedBecauseException();
|
|
throw new Exception();
|
|
}
|
|
}))
|
|
.Chain(Tween.Delay(getDt()));
|
|
yield return s;
|
|
Assert.AreEqual(1, numExceptions);
|
|
}
|
|
|
|
[Test]
|
|
public async Task SequenceIncrementalTween() {
|
|
await Tween.Delay(getDt());
|
|
float dur = getDt() * (Random.value + 0.1f);
|
|
var t = Tween.Position(transform, Vector3.one, dur, cycles: 2, cycleMode: CycleMode.Incremental);
|
|
int cyclesDone = 0;
|
|
const int sequenceCycles = 4;
|
|
await Sequence.Create(sequenceCycles)
|
|
.Chain(t)
|
|
.ChainCallback(() => {
|
|
cyclesDone++;
|
|
Assert.AreEqual(0f, t.interpolationFactor % 1f);
|
|
});
|
|
Assert.AreEqual(sequenceCycles, cyclesDone);
|
|
}
|
|
|
|
[Test]
|
|
public void SettingInfiniteLoopsToTweenInSequence() {
|
|
var t = createTween();
|
|
var s = Sequence.Create(t);
|
|
expectCantManipulateTweenInsideSequence();
|
|
t.SetRemainingCycles(-1);
|
|
s.Complete();
|
|
}
|
|
|
|
[Test]
|
|
public void TweenIsReleasedFromSequenceOnReleaseAll() {
|
|
test(true);
|
|
test(false);
|
|
void test(bool isStop) {
|
|
var t = createTween();
|
|
var s = Sequence.Create(t);
|
|
Assert.IsTrue(t.isAlive);
|
|
Assert.IsTrue(s.isAlive);
|
|
if (isStop) {
|
|
Tween.StopAll();
|
|
} else {
|
|
Tween.CompleteAll();
|
|
}
|
|
Assert.IsFalse(t.isAlive);
|
|
Assert.IsFalse(s.isAlive);
|
|
Assert.IsFalse(t.tween.sequence.IsCreated);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void SequenceComplete() {
|
|
int numTweenCompleted = 0;
|
|
var s = Sequence.Create(createCustomTween(0.01f).OnComplete(() => numTweenCompleted++));
|
|
Assert.IsTrue(s.isAlive);
|
|
s.Complete();
|
|
Assert.IsFalse(s.isAlive);
|
|
Assert.AreEqual(1, numTweenCompleted);
|
|
}
|
|
|
|
[Test]
|
|
public void SequenceStop() {
|
|
var s = Sequence.Create(createCustomTween(0.01f));
|
|
Assert.IsTrue(s.isAlive);
|
|
s.Stop();
|
|
Assert.IsFalse(s.isAlive);
|
|
s.Stop();
|
|
Assert.IsFalse(s.isAlive);
|
|
}
|
|
|
|
/*[UnityTest]
|
|
public IEnumerator SequenceRevert() {
|
|
var val = 0f;
|
|
var t = Tween.Custom(this, 0, 1, 1, (_, newVal) => {
|
|
val = newVal;
|
|
});
|
|
var s = Sequence.Create(t);
|
|
yield return null;
|
|
Assert.AreNotEqual(0, val);
|
|
s.Revert();
|
|
Assert.IsFalse(s.isAlive);
|
|
Assert.AreEqual(0, val);
|
|
}*/
|
|
|
|
[UnityTest]
|
|
public IEnumerator CompletedTweenInsideSequenceDoesntCompleteSecondTimeOnCompletingSequence() {
|
|
var numFirstCompleted = 0;
|
|
var numSecondCompleted = 0;
|
|
Tween first = createCustomTween(getDt()).OnComplete(() => numFirstCompleted++);
|
|
Tween second = createCustomTween(getDt() * 5f).OnComplete(() => numSecondCompleted++);
|
|
var sequence = Sequence.Create(first)
|
|
.Group(second);
|
|
while (first.interpolationFactor < 1f) {
|
|
yield return null;
|
|
}
|
|
Assert.IsTrue(first.isAlive);
|
|
Assert.IsTrue(first.tween._isAlive);
|
|
Assert.AreEqual(1, numFirstCompleted);
|
|
|
|
Assert.IsTrue(second.isAlive);
|
|
Assert.IsTrue(sequence.isAlive);
|
|
sequence.Complete();
|
|
Assert.AreEqual(1, numFirstCompleted);
|
|
Assert.AreEqual(1, numSecondCompleted);
|
|
}
|
|
|
|
static Tween createCustomTween(float duration) {
|
|
return Tween.Custom(PrimeTweenManager.Instance, 0, 1, duration, delegate{});
|
|
}
|
|
|
|
[Test]
|
|
public void CompletingSequenceCompletesAllTweensInside() {
|
|
var numFirstCompleted = 0;
|
|
var numSecondCompleted = 0;
|
|
Sequence.Create(createTween().OnComplete(() => numFirstCompleted++))
|
|
.Group(createTween().OnComplete(() => numSecondCompleted++))
|
|
.Complete();
|
|
Assert.AreEqual(1, numFirstCompleted);
|
|
Assert.AreEqual(1, numSecondCompleted);
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator Cycles() {
|
|
var tweenCyclesDone = 0;
|
|
var sequenceCyclesDone = 0;
|
|
const int sequenceCycles = 5;
|
|
const int tweenCycles = 3;
|
|
// tween cycles doesn't matter because OnComplete will only be executed when all cycles complete
|
|
var tween = Tween.Custom(this, 0, 1, Mathf.Max(minDuration, getDt() * Random.Range(0.1f, 0.5f)), cycles: tweenCycles, onValueChange: delegate{})
|
|
.OnComplete(() => {
|
|
// Debug.Log($"[{Time.frameCount}] tweenCycles++");
|
|
tweenCyclesDone++;
|
|
});
|
|
Sequence sequence = default;
|
|
sequence = Sequence.Create(sequenceCycles)
|
|
.Chain(tween)
|
|
.ChainCallback(() => {
|
|
// Debug.Log($"[{Time.frameCount}] sequenceCycles: {sequenceCyclesDone}, actual cyclesDone: {sequence.cyclesDone}");
|
|
Assert.AreEqual(sequenceCyclesDone, sequence.cyclesDone);
|
|
Assert.AreEqual(sequenceCycles, sequence.cyclesTotal);
|
|
sequenceCyclesDone++;
|
|
});
|
|
yield return sequence.ToYieldInstruction();
|
|
Assert.IsFalse(tween.isAlive);
|
|
Assert.IsFalse(sequence.isAlive);
|
|
Assert.AreEqual(sequenceCycles, tweenCyclesDone);
|
|
Assert.AreEqual(sequenceCycles, sequenceCyclesDone);
|
|
}
|
|
|
|
/*static IEnumerator Timeout([NotNull] Func<bool> continueWaiting, float timeout) {
|
|
var timeStarted = Time.time;
|
|
while (continueWaiting()) {
|
|
if (Time.time - timeStarted > timeout) {
|
|
throw new Exception($"Timeout of {timeout} seconds reached.");
|
|
}
|
|
yield return null;
|
|
}
|
|
}*/
|
|
|
|
[Test]
|
|
public void GroupDeadTweenToSequence() {
|
|
var deadTween = createTween();
|
|
deadTween.Complete();
|
|
expectAddDeadToSequenceError();
|
|
Sequence.Create(Tween.Delay(0.001f)).Group(deadTween);
|
|
}
|
|
|
|
Tween createTween() {
|
|
var t = Tween.LocalPosition(transform, Vector3.one, 1);
|
|
Assert.IsTrue(t.isAlive);
|
|
return t;
|
|
}
|
|
|
|
[Test]
|
|
public void ChainDeadTweenToSequence() {
|
|
var tweener = Tween.LocalPosition(transform, Vector3.one, 1);
|
|
tweener.Complete();
|
|
Assert.IsFalse(tweener.isAlive);
|
|
expectAddDeadToSequenceError();
|
|
Sequence.Create(Tween.Delay(0.0001f)).Chain(tweener);
|
|
}
|
|
|
|
static void expectAddDeadToSequenceError() {
|
|
LogAssert.Expect(LogType.Error, Constants.addDeadTweenToSequenceError);
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator SequenceRelease() {
|
|
Tween.StopAll();
|
|
for (int i = 0; i < 5; i++) {
|
|
Assert.AreEqual(0, tweensCount);
|
|
var duration = Mathf.Max(TweenSettings.minDuration, getDt());
|
|
var t = Tween.Delay(duration);
|
|
var s = Sequence.Create(t);
|
|
yield return null;
|
|
// Debug.Log($"duration: {duration}, dt {Time.deltaTime}");
|
|
// print(Time.deltaTime > duration);
|
|
if (Time.deltaTime > duration) {
|
|
Assert.IsFalse(t.isAlive);
|
|
Assert.IsFalse(s.isAlive);
|
|
Tween.StopAll();
|
|
continue;
|
|
}
|
|
Assert.IsTrue(t.isAlive);
|
|
Assert.IsTrue(s.isAlive);
|
|
s.Stop();
|
|
Assert.AreEqual(2, tweensCount);
|
|
yield return null;
|
|
Assert.AreEqual(0, tweensCount);
|
|
}
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator ManipulatingTweensInsideSequenceCoroutine() {
|
|
{
|
|
var nestedTween = Tween.Delay(getDt());
|
|
Sequence.Create(nestedTween);
|
|
expectCantManipulateTweenInsideSequence();
|
|
yield return nestedTween.ToYieldInstruction();
|
|
}
|
|
{
|
|
var nestedSequence = Sequence.Create();
|
|
Sequence.Create().Chain(nestedSequence);
|
|
expectCantManipulateTweenInsideSequence();
|
|
yield return nestedSequence.ToYieldInstruction();
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public async Task ManipulatingTweensInsideSequenceAsync() {
|
|
var t = Tween.Delay(getDt());
|
|
#pragma warning disable 4014
|
|
Sequence.Create(t);
|
|
#pragma warning restore
|
|
expectCantManipulateTweenInsideSequence();
|
|
await t;
|
|
}
|
|
|
|
[Test]
|
|
public void ManipulatingTweensInsideSequence() {
|
|
var go = new GameObject();
|
|
var tween = Tween.Custom(go, 0, 1, 1, delegate{}, cycles: 3, cycleMode: CycleMode.Yoyo);
|
|
Sequence.Create(tween);
|
|
Assert.IsTrue(tween.isAlive);
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
tween.Stop();
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
tween.Complete();
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
tween.SetRemainingCycles(5);
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
tween.SetRemainingCycles(true);
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
tween.Group(new Tween());
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
tween.Chain(new Tween());
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
tween.Group(new Sequence());
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
tween.Chain(new Sequence());
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
Assert.AreEqual(0 , Tween.StopAll(go));
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
Assert.AreEqual(0, Tween.CompleteAll(go));
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
Tween.SetPausedAll(true, go);
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
Tween.SetPausedAll(false, go);
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
expectCantManipulateTweenInsideSequence();
|
|
tween.isPaused = !tween.isPaused;
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
expectCantManipulateTweenInsideSequence();
|
|
tween.timeScale += 0.5f;
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
tween.elapsedTime += 0.1f;
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
tween.elapsedTimeTotal += 0.1f;
|
|
|
|
Tween.StopAll();
|
|
Assert.AreEqual(0, tweensCount);
|
|
LogAssert.NoUnexpectedReceived();
|
|
}
|
|
|
|
static void expectCantManipulateTweenInsideSequence() {
|
|
LogAssert.Expect(LogType.Error, new Regex("It's not allowed to manipulate 'nested' tweens and sequences"));
|
|
}
|
|
|
|
[Test]
|
|
public void AddingInfiniteTweenToSequenceThrows() {
|
|
var infiniteTween = createInfiniteTween();
|
|
expectInfiniteTweenInSequenceError();
|
|
Sequence.Create(infiniteTween);
|
|
|
|
expectInfiniteTweenInSequenceError();
|
|
Sequence.Create(infiniteTween);
|
|
|
|
expectInfiniteTweenInSequenceError();
|
|
Sequence.Create(Tween.Delay(minDuration)).Chain(infiniteTween);
|
|
}
|
|
|
|
static void expectInfiniteTweenInSequenceError() => LogAssert.Expect(LogType.Error, Constants.infiniteTweenInSequenceError);
|
|
|
|
static void expectException<T>(Action code, [NotNull] string message) where T: Exception {
|
|
Assert.IsFalse(string.IsNullOrEmpty(message));
|
|
try {
|
|
code();
|
|
} catch (T e) {
|
|
if (!e.Message.Contains(message)) {
|
|
Debug.LogException(e);
|
|
Assert.Fail();
|
|
}
|
|
return;
|
|
}
|
|
Assert.Fail($"Exception of type {typeof(T)} didn't appear: {message}");
|
|
}
|
|
|
|
[Test]
|
|
public void TestDeadSequence() {
|
|
var s = createDeadSequence();
|
|
|
|
expectError();
|
|
s.Group(createCustomTween(1));
|
|
|
|
expectError();
|
|
s.ChainCallback(delegate { });
|
|
|
|
expectError();
|
|
s.ChainCallback(this, delegate { });
|
|
|
|
expectError();
|
|
s.Chain(createTween());
|
|
|
|
#if PRIME_TWEEN_DOTWEEN_ADAPTER
|
|
expectError();
|
|
s.ChainLast(createTween());
|
|
#endif
|
|
|
|
s.Stop();
|
|
s.Complete();
|
|
// s.Revert();
|
|
|
|
expectError();
|
|
s.SetRemainingCycles(5);
|
|
|
|
expectError();
|
|
s.isPaused = true;
|
|
|
|
void expectError() {
|
|
expectIsDeadError();
|
|
}
|
|
}
|
|
|
|
static Sequence createDeadSequence() {
|
|
var s = Sequence.Create(createCustomTween(1));
|
|
s.Complete();
|
|
Assert.IsFalse(s.isAlive);
|
|
return s;
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator AddingTweenToSequenceModifiesIsPausedToMatchSequence() {
|
|
Tween.StopAll();
|
|
Assert.AreEqual(0, tweensCount);
|
|
var s = Sequence.Create(Tween.PositionY(transform,10f, 0.04f));
|
|
Assert.IsFalse(s.isPaused);
|
|
|
|
var t = Tween.Delay(0.04f);
|
|
Assert.IsFalse(t.isPaused);
|
|
t.isPaused = true;
|
|
Assert.IsTrue(t.isPaused);
|
|
|
|
LogAssert.Expect(LogType.Error, new Regex("'isPaused' was ignored after adding"));
|
|
s.Group(t);
|
|
LogAssert.NoUnexpectedReceived();
|
|
yield return s.ToYieldInstruction();
|
|
}
|
|
|
|
|
|
[Test]
|
|
public void DuplicateTweenAddedToSequence() {
|
|
var t = createTween();
|
|
var s = Sequence.Create(t);
|
|
expectNestTweenTwiceError();
|
|
s.Group(t);
|
|
|
|
expectNestTweenTwiceError();
|
|
var s2 = Sequence.Create();
|
|
s2.Group(t);
|
|
|
|
expectNestTweenTwiceError();
|
|
Sequence.Create(t);
|
|
}
|
|
|
|
static void expectNestTweenTwiceError() => LogAssert.Expect(LogType.Error, new Regex(Constants.nestTweenTwiceError));
|
|
|
|
[UnityTest]
|
|
public IEnumerator TweenIsNotReleasedFromSequenceUntilSequenceReleasesAllTweens() {
|
|
var t = createCustomTween(minDuration);
|
|
var delay = Tween.Delay(getDt() * 4f);
|
|
var s = Sequence.Create(t).Group(delay);
|
|
Assert.IsTrue(t.isAlive);
|
|
yield return s.ToYieldInstruction();
|
|
Assert.IsFalse(t.isAlive);
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator ProcessAllDoesntLeaveUnreleasableTweens() {
|
|
Tween.StopAll();
|
|
Assert.AreEqual(0, tweensCount);
|
|
var t1 = createCustomTween(0.0001f);
|
|
var t2 = createCustomTween(0.1f);
|
|
if (Random.value < 0.5f) {
|
|
t1.Group(t2);
|
|
} else {
|
|
t1.Chain(t2);
|
|
}
|
|
while (t1.interpolationFactor < 1f) {
|
|
yield return null;
|
|
}
|
|
Assert.IsTrue(t1.isAlive);
|
|
Assert.IsTrue(t2.isAlive);
|
|
Assert.AreNotEqual(0, tweensCount);
|
|
Tween.StopAll();
|
|
Assert.AreEqual(0, tweensCount);
|
|
}
|
|
|
|
[Test]
|
|
public void ProcessAllDoesntLeaveUnreleasableTweensWhenTargetDestroyed() {
|
|
if (tweensCount != 0) {
|
|
Tween.StopAll();
|
|
}
|
|
Assert.AreEqual(0, tweensCount);
|
|
var target1 = new GameObject();
|
|
var t1 = Tween.Custom(target1, 0, 1,0.0001f, delegate{});
|
|
var t2 = createCustomTween(0.1f);
|
|
t1.Group(t2);
|
|
Object.DestroyImmediate(target1);
|
|
Assert.AreEqual(3, tweensCount);
|
|
Assert.IsTrue(t1.isAlive);
|
|
Tween.StopAll();
|
|
Assert.AreEqual(0, tweensCount);
|
|
}
|
|
|
|
[Test]
|
|
public void SequenceCompleteWhenMoreThanTwo() {
|
|
createTween()
|
|
.Group(createTween())
|
|
.Group(createTween())
|
|
.Complete();
|
|
}
|
|
|
|
[Test]
|
|
public void SequenceDuration() {
|
|
var dur1 = Random.value;
|
|
var cycles1 = Random.Range(1, 5);
|
|
var s = Sequence.Create(Tween.Custom(this, 0, 1, dur1, cycles: cycles1, onValueChange: delegate{}));
|
|
Assert.AreEqual(dur1 * cycles1, s.duration);
|
|
Assert.AreEqual(dur1 * cycles1, s.durationTotal);
|
|
var dur2 = dur1 + Random.value;
|
|
var cycles2 = cycles1 + Random.Range(1, 5);
|
|
s.Group(Tween.Custom(this, 0, 1, dur2, cycles: cycles2, onValueChange: delegate{}));
|
|
Assert.AreEqual(dur2 * cycles2, s.duration);
|
|
Assert.AreEqual(dur2 * cycles2, s.durationTotal);
|
|
s.Chain(Tween.Delay(1));
|
|
var expected = dur2 * cycles2 + 1;
|
|
const float tolerance = 0.0001f;
|
|
Assert.AreEqual(expected, s.duration, tolerance);
|
|
Assert.AreEqual(expected, s.durationTotal, tolerance);
|
|
var sequenceCycles = Random.Range(1, 100);
|
|
s.SetRemainingCycles(sequenceCycles);
|
|
Assert.AreEqual(expected, s.duration, tolerance);
|
|
Assert.AreEqual(expected * sequenceCycles, s.durationTotal, tolerance);
|
|
s.Complete();
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator SequenceCycles() {
|
|
Application.targetFrameRate = 200;
|
|
int cyclesDone = 0;
|
|
var iniCycles = Random.Range(3, 10);
|
|
// const int iniCycles = 3;
|
|
var s = Sequence.Create(iniCycles)
|
|
.Chain(Tween.PositionX(transform, 3.14f, getDt() * 2f, cycles: 2))
|
|
.ChainCallback(this, _ => cyclesDone++);
|
|
Assert.AreEqual(iniCycles, s.cyclesTotal);
|
|
Assert.AreEqual(0, s.cyclesDone);
|
|
while (s.cyclesDone == 0) {
|
|
yield return null;
|
|
}
|
|
Assert.AreEqual(iniCycles, s.cyclesTotal);
|
|
Assert.AreEqual(cyclesDone, s.cyclesDone);
|
|
var pendingCycles = Random.Range(2, 10);
|
|
// const int pendingCycles = 2;
|
|
s.SetRemainingCycles(pendingCycles);
|
|
var expectedCycles = cyclesDone + pendingCycles;
|
|
Assert.AreEqual(expectedCycles, s.cyclesTotal);
|
|
Assert.AreEqual(1, s.cyclesDone);
|
|
while (s.cyclesDone == 1) {
|
|
yield return null;
|
|
}
|
|
Assert.AreEqual(expectedCycles, s.cyclesTotal);
|
|
Assert.AreEqual(cyclesDone, s.cyclesDone);
|
|
s.Complete();
|
|
Application.targetFrameRate = targetFrameRate;
|
|
}
|
|
|
|
[Test]
|
|
public void AwaitNewlyCreatedSequenceDoesntCompleteSyncButInSameFrame() {
|
|
bool isCompleted = false;
|
|
#pragma warning disable CS4014
|
|
AwaitNewlyCreatedSequenceDoesntCompleteSyncButInSameFrame_internal(() => isCompleted = true);
|
|
#pragma warning restore CS4014
|
|
Assert.IsFalse(isCompleted);
|
|
}
|
|
|
|
static async Task AwaitNewlyCreatedSequenceDoesntCompleteSyncButInSameFrame_internal([NotNull] Action callback) {
|
|
int frameStarted = Time.frameCount;
|
|
await Sequence.Create();
|
|
Assert.AreEqual(frameStarted, Time.frameCount); // completes in same frame, but not immediately
|
|
callback();
|
|
}
|
|
|
|
[Test]
|
|
public void UsingDefaultSequenceCtor() {
|
|
for (int i = 0; i < 26; i++) {
|
|
expectDefaultCtorError();
|
|
}
|
|
var seq = new Sequence();
|
|
seq.elapsedTime += seq.elapsedTime; // +3
|
|
_ = seq.cyclesTotal;
|
|
_ = seq.cyclesDone;
|
|
_ = seq.duration;
|
|
seq.elapsedTimeTotal += seq.elapsedTimeTotal; // +3
|
|
_ = seq.durationTotal;
|
|
_ = seq.progress;
|
|
_ = seq.progressTotal;
|
|
var t = Tween.Delay(0.0001f);
|
|
seq.Group(t);
|
|
seq.Chain(t);
|
|
seq.ChainCallback(() => {});
|
|
seq.ChainCallback(this, delegate {});
|
|
seq.ChainDelay(1f);
|
|
seq.Stop(); // no error
|
|
seq.Complete(); // no error
|
|
seq.SetRemainingCycles(false);
|
|
seq.SetRemainingCycles(10);
|
|
seq.isPaused = !seq.isPaused; // +2
|
|
seq.Chain(Sequence.Create());
|
|
seq.Group(Sequence.Create());
|
|
seq.timeScale += seq.timeScale; // +3
|
|
|
|
#if PRIME_TWEEN_DOTWEEN_ADAPTER
|
|
expectDefaultCtorError();
|
|
seq.ChainLast(t);
|
|
#endif
|
|
Tween.StopAll();
|
|
}
|
|
|
|
static void expectDefaultCtorError() {
|
|
LogAssert.Expect(LogType.Error, Constants.defaultCtorError);
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator OnCompleteCallbackIsCalledOnlyOnce() {
|
|
int numT1Completed = 0;
|
|
var t1 = Tween.Delay(0.05f).OnComplete(() => numT1Completed++);
|
|
var s = t1.Chain(Tween.Delay(0.05f));
|
|
while (t1.interpolationFactor < 1f) {
|
|
yield return null;
|
|
}
|
|
Assert.IsTrue(t1.isAlive);
|
|
Assert.AreEqual(1, numT1Completed);
|
|
s.Complete();
|
|
Assert.AreEqual(1, numT1Completed);
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator SequenceElapsedTime2() {
|
|
Application.targetFrameRate = 200;
|
|
float dt = getDt();
|
|
var cycleTimeStart = Time.time;
|
|
float duration = dt * 5f;
|
|
var s = Tween.Delay(duration)
|
|
.Chain(Tween.Delay(duration))
|
|
.ChainCallback(() => cycleTimeStart = Time.time);
|
|
s.SetRemainingCycles(2);
|
|
var timeStart = Time.time;
|
|
while (s.isAlive) {
|
|
float tolerance = dt * 2;
|
|
Assert.AreEqual(Time.time - timeStart, s.elapsedTimeTotal, tolerance);
|
|
Assert.AreEqual(Time.time - cycleTimeStart, s.elapsedTime, tolerance);
|
|
yield return null;
|
|
}
|
|
Application.targetFrameRate = targetFrameRate;
|
|
}
|
|
|
|
[Test]
|
|
public void SequenceTimeScale() {
|
|
var seq = Sequence.Create();
|
|
const float seqTimeScale = 1.5f;
|
|
seq.timeScale = seqTimeScale;
|
|
var t2 = Tween.Delay(0.1f);
|
|
t2.timeScale = 0.5f;
|
|
LogAssert.Expect(LogType.Error, new Regex("'timeScale' was ignored after adding"));
|
|
seq.Chain(t2);
|
|
foreach (var t in seq.getAllChildren()) {
|
|
Assert.AreEqual(0.5f, t.tween.timeScale);
|
|
}
|
|
|
|
seq.timeScale = 2f;
|
|
Assert.AreEqual(2f, seq.root.timeScale);
|
|
foreach (var t in seq.getAllChildren()) {
|
|
Assert.AreEqual(0.5f, t.tween.timeScale);
|
|
}
|
|
|
|
LogAssert.NoUnexpectedReceived();
|
|
Tween.StopAll();
|
|
}
|
|
|
|
[Test]
|
|
public void CompletingMainSequenceCompletesAllChildrenSequencesAndTweens() {
|
|
int numCallback = 0;
|
|
var nestedSeq2 = Sequence.Create()
|
|
.ChainDelay(1)
|
|
.ChainCallback(() => {
|
|
Assert.AreEqual(1, numCallback);
|
|
numCallback++;
|
|
});
|
|
var nestedSeq1 = Sequence.Create()
|
|
.ChainDelay(1)
|
|
.ChainCallback(() => {
|
|
Assert.AreEqual(0, numCallback);
|
|
numCallback++;
|
|
})
|
|
.Chain(nestedSeq2);
|
|
Sequence.Create(Tween.Delay(1))
|
|
.Group(nestedSeq1)
|
|
.Complete();
|
|
Assert.AreEqual(2, numCallback);
|
|
}
|
|
|
|
[Test]
|
|
public void ManipulateNestedSequence() {
|
|
var nested = Sequence.Create(Tween.Delay(getDt()));
|
|
Sequence.Create().Group(nested);
|
|
|
|
var tween = Tween.Delay(getDt());
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
nested.Group(tween);
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
nested.Chain(Tween.Delay(getDt()));
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
nested.ChainCallback(delegate {});
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
nested.ChainCallback(this, delegate {});
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
nested.ChainCallback(this, delegate {});
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
nested.ChainDelay(0.1f);
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
nested.Stop();
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
nested.Complete();
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
nested.SetRemainingCycles(10);
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
expectCantManipulateTweenInsideSequence();
|
|
nested.isPaused = !nested.isPaused;
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
nested.Chain(Sequence.Create());
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
nested.Group(Sequence.Create());
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
nested.elapsedTime += 0.1f;
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
nested.elapsedTimeTotal += 0.1f;
|
|
|
|
expectCantManipulateTweenInsideSequence();
|
|
expectCantManipulateTweenInsideSequence();
|
|
nested.timeScale += 1f;
|
|
}
|
|
|
|
[Test]
|
|
public async Task OnCompleteExceptionInsideSequenceDoesntStopSequence() {
|
|
// by design: if one tween's onComplete throws exception, Sequence should continue to play further
|
|
{
|
|
int numCallbacks = 0;
|
|
expectOnCompleteException();
|
|
await Sequence.Create(Tween.Delay(getDt(), () => throw new Exception()))
|
|
.Chain(Tween.Delay(getDt(), () => numCallbacks++))
|
|
.ChainCallback(() => numCallbacks++);
|
|
Assert.AreEqual(2, numCallbacks);
|
|
}
|
|
{
|
|
int numCallbacks = 0;
|
|
expectOnCompleteException();
|
|
await Sequence.Create(Tween.Delay(this, getDt(), _ => throw new Exception()))
|
|
.Chain(Tween.Delay(getDt(), () => numCallbacks++))
|
|
.ChainCallback(() => numCallbacks++);
|
|
Assert.AreEqual(2, numCallbacks);
|
|
}
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator TestSequenceEnumerator() {
|
|
const float duration = 0.0001f;
|
|
var t1 = Tween.Delay(duration);
|
|
var s1 = Sequence.Create(t1);
|
|
|
|
var t2 = Tween.Delay(duration);
|
|
var s2 = Sequence.Create(t2);
|
|
|
|
var t3 = Tween.Delay(duration);
|
|
var s3 = Sequence.Create(t3);
|
|
|
|
s2.Chain(s3);
|
|
s1.Chain(s2);
|
|
|
|
var expected = new[] {
|
|
s1.root, t1,
|
|
s2.root, t2,
|
|
s3.root, t3
|
|
};
|
|
int i = 0;
|
|
foreach (var t in s1.getAllTweens()) {
|
|
Assert.AreEqual(expected[i], t);
|
|
i++;
|
|
}
|
|
Assert.AreEqual(6, i);
|
|
i = 1;
|
|
foreach (var t in s1.getSelfChildren()) {
|
|
Assert.AreEqual(expected[i], t);
|
|
i++;
|
|
}
|
|
Assert.AreEqual(3, i);
|
|
|
|
i = 3;
|
|
foreach (var t in s2.getSelfChildren()) {
|
|
Assert.AreEqual(expected[i], t);
|
|
i++;
|
|
}
|
|
Assert.AreEqual(5, i);
|
|
|
|
i = 5;
|
|
foreach (var t in s3.getSelfChildren()) {
|
|
Assert.AreEqual(expected[i], t);
|
|
i++;
|
|
}
|
|
Assert.AreEqual(6, i);
|
|
|
|
yield return null;
|
|
}
|
|
|
|
[Test]
|
|
public void TestSequenceEnumeratorWithEmptySequences() {
|
|
var s1 = Sequence.Create();
|
|
var s2 = Sequence.Create();
|
|
var s3 = Sequence.Create();
|
|
s1.Chain(s2)
|
|
.Chain(s3);
|
|
|
|
var expected = new[] { s1.root, s2.root, s3.root };
|
|
|
|
int i = 0;
|
|
foreach (var t in s1.getAllTweens()) {
|
|
Assert.AreEqual(expected[i], t);
|
|
i++;
|
|
}
|
|
|
|
i = 1;
|
|
foreach (var t in s1.getSelfChildren()) {
|
|
Assert.AreEqual(expected[i], t);
|
|
i++;
|
|
}
|
|
|
|
foreach (var _ in s2.getSelfChildren()) {
|
|
Assert.Fail();
|
|
}
|
|
|
|
foreach (var _ in s3.getSelfChildren()) {
|
|
Assert.Fail();
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void MainSequenceSiblingShouldBeEmpty() {
|
|
var main = Sequence.Create();
|
|
var nested1 = Sequence.Create(Tween.Delay(getDt()));
|
|
main.Chain(nested1);
|
|
Assert.AreEqual(main.root.tween.next, nested1.root);
|
|
Assert.IsFalse(main.root.tween.nextSibling.IsCreated);
|
|
var nested2 = Sequence.Create(Tween.Delay(getDt()));
|
|
main.Chain(nested2);
|
|
Assert.AreEqual(main.root.tween.next, nested1.root);
|
|
Assert.IsFalse(main.root.tween.nextSibling.IsCreated);
|
|
}
|
|
|
|
[Test]
|
|
public void CompleteSequenceOnBackwardCycle() {
|
|
var target = new GameObject().transform;
|
|
const float duration = 1f;
|
|
Sequence.Create(2, CycleMode.Rewind)
|
|
.Chain(Tween.PositionY(target, 1, duration))
|
|
.Chain(Tween.PositionY(target, 0, duration)).Complete();
|
|
Assert.AreEqual(0f, target.position.y);
|
|
Object.Destroy(target.gameObject);
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator CompleteSequenceOnBackwardCycle2() {
|
|
var target = GameObject.CreatePrimitive(PrimitiveType.Cube).transform;
|
|
yield return test(2, false);
|
|
yield return test(2, true);
|
|
yield return test(3, false);
|
|
yield return test(3, true);
|
|
yield return test(4, false);
|
|
yield return test(4, true);
|
|
|
|
IEnumerator test(int cycles, bool completeImmediately) {
|
|
// print($"test {cycles}, {completeImmediately}");
|
|
const float duration = 0.0001f;
|
|
int numCompleted = 0;
|
|
var seq = Sequence.Create(cycles, CycleMode.Yoyo, Ease.OutBounce)
|
|
.Chain(Tween.PositionY(target, 1f, duration).OnComplete(() => numCompleted++))
|
|
.Chain(Tween.PositionY(target, 0f, duration));
|
|
if (completeImmediately) {
|
|
seq.Complete();
|
|
} else {
|
|
yield return seq.ToYieldInstruction();
|
|
}
|
|
if (completeImmediately) {
|
|
Assert.AreEqual(1, numCompleted);
|
|
} else {
|
|
Assert.AreEqual((cycles + 1) / 2, numCompleted);
|
|
}
|
|
Assert.AreEqual(0f, target.position.y);
|
|
}
|
|
|
|
Object.Destroy(target.gameObject);
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator CompleteInfiniteSequence() {
|
|
int numCallbacks = 0;
|
|
var duration = Mathf.Max(minDuration, Random.Range(0f, getDt()));
|
|
Assert.IsTrue(duration >= minDuration);
|
|
var s = Sequence.Create(-1)
|
|
.ChainDelay(duration)
|
|
.ChainCallback(() => numCallbacks++);
|
|
float timeStart = Time.time;
|
|
yield return null;
|
|
yield return null;
|
|
var cyclesDoneExpected = Mathf.FloorToInt((Time.time - timeStart) / duration);
|
|
Assert.AreEqual(cyclesDoneExpected, s.cyclesDone);
|
|
s.Complete();
|
|
Assert.AreEqual(cyclesDoneExpected + 1, numCallbacks);
|
|
}
|
|
|
|
[Test]
|
|
public void OnCompleteWithSequenceBackward() {
|
|
int numCompleted = 0;
|
|
int cycles = Random.Range(1, 7);
|
|
var seq = Sequence.Create(cycles)
|
|
.Group(Sequence.Create(cycles)
|
|
.Group(Sequence.Create(cycles)
|
|
.Group(Tween.Delay(0.1f, () => numCompleted++))));
|
|
seq.isPaused = true;
|
|
seq.elapsedTimeTotal = float.MaxValue;
|
|
int cyclesTotal = cycles * cycles * cycles;
|
|
int cyclesExpected = cyclesTotal;
|
|
Assert.AreEqual(cyclesExpected, numCompleted);
|
|
seq.elapsedTimeTotal = 0f;
|
|
cyclesExpected += cyclesTotal - 1;
|
|
Assert.AreEqual(cyclesExpected, numCompleted);
|
|
|
|
seq.elapsedTimeTotal = float.MaxValue;
|
|
cyclesExpected += cyclesTotal;
|
|
Assert.AreEqual(cyclesExpected, numCompleted);
|
|
|
|
seq.elapsedTimeTotal = 0f;
|
|
cyclesExpected += cyclesTotal - 1;
|
|
Assert.AreEqual(cyclesExpected, numCompleted);
|
|
|
|
seq.Complete();
|
|
cyclesExpected += cycles * cycles;
|
|
Assert.AreEqual(cyclesExpected, numCompleted);
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator UnpauseCompletedSequenceShouldRelease() {
|
|
var s = Tween.Delay(getDt()).Chain(Tween.Delay(getDt()));
|
|
s.isPaused = true;
|
|
s.elapsedTimeTotal = s.durationTotal;
|
|
yield return null;
|
|
yield return null;
|
|
Assert.IsTrue(s.isAlive);
|
|
s.isPaused = false;
|
|
Assert.IsFalse(s.isAlive);
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator UnpauseCompletedTweenShouldRelease() {
|
|
var t = Tween.Delay(getDt());
|
|
t.isPaused = true;
|
|
t.elapsedTimeTotal = t.durationTotal;
|
|
yield return null;
|
|
yield return null;
|
|
Assert.IsTrue(t.isAlive);
|
|
t.isPaused = false;
|
|
Assert.IsFalse(t.isAlive);
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator NestedSequenceCycles() {
|
|
string result = "";
|
|
void append(int i) => result += i.ToString();
|
|
|
|
yield return createNestedSequences(getDt()).ToYieldInstruction();
|
|
Assert.AreEqual("12332331233233", result);
|
|
|
|
createNestedSequences(getDt()).Complete();
|
|
Assert.AreEqual("1233233", result);
|
|
|
|
PrimeTweenConfig.warnZeroDuration = false;
|
|
yield return createNestedSequences(0f).ToYieldInstruction();
|
|
Assert.AreEqual("12332331233233", result);
|
|
|
|
createNestedSequences(0f).Complete();
|
|
Assert.AreEqual("1233233", result);
|
|
|
|
Sequence createNestedSequences(float duration) {
|
|
result = "";
|
|
var s3 = Sequence.Create(2).ChainDelay(duration).ChainCallback(() => append(3));
|
|
var s2 = Sequence.Create(2).ChainDelay(duration).ChainCallback(() => append(2)).Chain(s3);
|
|
var s1 = Sequence.Create(2).ChainDelay(duration).ChainCallback(() => append(1)).Chain(s2);
|
|
return s1;
|
|
}
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator AddTweenToStartedSequence() {
|
|
var s = Sequence.Create(Tween.Delay(1f));
|
|
yield return null;
|
|
Assert.IsTrue(s.isAlive);
|
|
Assert.AreNotEqual(0f, s.elapsedTimeTotal);
|
|
|
|
var t = Tween.Delay(0.1f);
|
|
|
|
expectError();
|
|
s.Chain(t);
|
|
expectError();
|
|
s.Group(t);
|
|
expectError();
|
|
s.Chain(Sequence.Create());
|
|
expectError();
|
|
s.Group(Sequence.Create());
|
|
|
|
Tween.StopAll();
|
|
LogAssert.NoUnexpectedReceived();
|
|
static void expectError() => LogAssert.Expect(LogType.Error, Constants.animationAlreadyStarted);
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator OnCompleteIgnoredErrorOnSequenceEmergencyStop() {
|
|
expectTweenWasStoppedBecauseException();
|
|
expectOnCompleteIgnored();
|
|
yield return Tween.Custom(0f, 1f, getDt(), _ => throw new Exception())
|
|
.Chain(Tween.Delay(getDt(), Assert.Fail))
|
|
.ToYieldInstruction();
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator SequenceIsEmptyEnumerationBug() {
|
|
yield return Sequence.Create()
|
|
.Chain(Sequence.Create().Chain(Sequence.Create()))
|
|
.Chain(Sequence.Create().Chain(Sequence.Create()))
|
|
.ToYieldInstruction();
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator SequenceIsEmptyEnumerationCausesStackOverflowBug() {
|
|
var duration = getDt() * 2f;
|
|
yield return Sequence.Create()
|
|
.Chain(Tween.Delay(duration).Chain(Sequence.Create()))
|
|
.Chain(Tween.Delay(duration).Chain(Sequence.Create()))
|
|
.ToYieldInstruction();
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator SequenceOnComplete() {
|
|
int numCompleted = 0;
|
|
yield return Sequence.Create(2, CycleMode.Yoyo)
|
|
.ChainDelay(getDt())
|
|
.OnComplete(() => numCompleted++)
|
|
.ToYieldInstruction();
|
|
Assert.AreEqual(1, numCompleted);
|
|
|
|
numCompleted = 0;
|
|
yield return Sequence.Create(2, CycleMode.Yoyo)
|
|
.ChainDelay(getDt())
|
|
.OnComplete(this, _ => numCompleted++)
|
|
.ToYieldInstruction();
|
|
Assert.AreEqual(1, numCompleted);
|
|
}
|
|
|
|
[Test]
|
|
public void LongGroupAfterChainOpSequence() {
|
|
var seq = Tween.Delay(0.1f)
|
|
.Chain(Tween.Delay(0.1f));
|
|
|
|
seq.Group(Sequence.Create(Tween.Delay(1f)));
|
|
Assert.AreEqual(1.1f, seq.duration);
|
|
|
|
seq.Group(Sequence.Create(Tween.Delay(2f)));
|
|
Assert.AreEqual(2.1f, seq.duration);
|
|
|
|
seq.Chain(Sequence.Create(Tween.Delay(1f)));
|
|
Assert.AreEqual(3.1f, seq.duration);
|
|
|
|
seq.Stop();
|
|
}
|
|
|
|
[Test]
|
|
public void LongGroupAfterChainOpTween() {
|
|
var seq = Tween.Delay(0.1f)
|
|
.Chain(Tween.Delay(0.1f));
|
|
|
|
seq.Group(Tween.Delay(1f));
|
|
Assert.AreEqual(1.1f, seq.duration);
|
|
|
|
seq.Group(Tween.Delay(2f));
|
|
Assert.AreEqual(2.1f, seq.duration);
|
|
|
|
seq.Chain(Tween.Delay(1f));
|
|
Assert.AreEqual(3.1f, seq.duration);
|
|
|
|
seq.Stop();
|
|
}
|
|
[UnityTest]
|
|
public IEnumerator SequenceRecursiveCreate() {
|
|
var target = new GameObject();
|
|
float duration = getDt() * 2f;
|
|
Sequence seq1 = default;
|
|
Sequence seq2 = default;
|
|
createSeq1();
|
|
|
|
void createSeq1() {
|
|
// print("createSeq1");
|
|
seq1.Stop();
|
|
seq1 = Sequence.Create()
|
|
.Chain(Tween.Delay(target, duration: duration))
|
|
.ChainCallback(() => {
|
|
})
|
|
.Chain(Tween.Delay(target, duration: duration))
|
|
.ChainCallback(() => {
|
|
createSeq2();
|
|
});
|
|
createSeq2();
|
|
}
|
|
|
|
void createSeq2() {
|
|
// print("createSeq2");
|
|
seq2.Stop();
|
|
seq2 = Sequence.Create()
|
|
.Chain(Tween.Delay(target, duration: duration))
|
|
.ChainCallback(() => {
|
|
})
|
|
.Chain(Tween.Delay(target, duration: duration))
|
|
.ChainCallback(() => {
|
|
seq1.Complete();
|
|
});
|
|
}
|
|
|
|
while (seq1.isAlive || seq2.isAlive) {
|
|
yield return null;
|
|
}
|
|
yield return null;
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator StopSequenceFromCallback2() {
|
|
Sequence s = default;
|
|
int numCyclesDone = 0;
|
|
var duration = getDt() * 2f;
|
|
s = Sequence.Create(2)
|
|
.ChainDelay(duration)
|
|
.ChainDelay(duration)
|
|
.ChainCallback(() => {
|
|
numCyclesDone++;
|
|
// print($"numCyclesDone: {numCyclesDone}");
|
|
if (numCyclesDone == 2) {
|
|
s.timeScale = 0f;
|
|
s.SetRemainingCycles(3);
|
|
Tween.StopAll();
|
|
}
|
|
});
|
|
yield return s.ToYieldInstruction();
|
|
yield return null;
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator StopSequenceFromCallback3() {
|
|
var dt = getDt();
|
|
var s2 = Sequence.Create().ChainDelay(dt * 10f);
|
|
var s1 = Sequence.Create()
|
|
.ChainDelay(dt)
|
|
.ChainCallback(() => {
|
|
Assert.IsTrue(s2.isAlive);
|
|
s2.Stop();
|
|
Assert.IsFalse(s2.isAlive);
|
|
});
|
|
yield return s1.ToYieldInstruction();
|
|
yield return null;
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator StopSequenceFromCallback4() {
|
|
Sequence s = default;
|
|
s = Sequence.Create(2)
|
|
.ChainDelay(getDt())
|
|
.ChainCallback(() => {
|
|
s.Stop();
|
|
});
|
|
yield return s.ToYieldInstruction();
|
|
yield return null;
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator SequenceOnCompleteIsCalledAfterAllChildren() {
|
|
bool delayCompleted = false;
|
|
bool sequenceCompleted = false;
|
|
var delay = Tween.Delay(getDt(), () => {
|
|
Assert.IsTrue(!delayCompleted && !sequenceCompleted);
|
|
delayCompleted = true;
|
|
});
|
|
yield return Sequence.Create(delay).OnComplete(() => {
|
|
Assert.IsTrue(delayCompleted);
|
|
Assert.IsFalse(sequenceCompleted);
|
|
sequenceCompleted = true;
|
|
});
|
|
Assert.IsTrue(delayCompleted && sequenceCompleted);
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator SequenceIsNotAliveInOnComplete() {
|
|
Sequence s = default;
|
|
int onCompleted = 0;
|
|
s = Sequence.Create()
|
|
.OnComplete(() => {
|
|
Assert.IsFalse(s.isAlive);
|
|
onCompleted++;
|
|
});
|
|
yield return null;
|
|
Assert.AreEqual(1, onCompleted);
|
|
Assert.IsFalse(s.isAlive);
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator CompleteSequenceInOnComplete() {
|
|
Sequence s = default;
|
|
s = Sequence.Create()
|
|
.OnComplete(() => {
|
|
Assert.IsFalse(s.isAlive);
|
|
s.Complete();
|
|
});
|
|
yield return s.ToYieldInstruction();
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator SequenceSetProgressRecursively() {
|
|
int i = 0;
|
|
Sequence s = default;
|
|
s = Sequence.Create()
|
|
.Chain(Tween.Custom(0f, 1f, getDt() * 2f, _ => {
|
|
i++;
|
|
Assert.IsTrue(i < 100);
|
|
expectRecursiveCallError();
|
|
s.progress += 0.01f;
|
|
expectRecursiveCallError();
|
|
s.progressTotal += 0.01f;
|
|
expectRecursiveCallError();
|
|
s.elapsedTime += 0.01f;
|
|
expectRecursiveCallError();
|
|
s.elapsedTimeTotal += 0.01f;
|
|
}));
|
|
yield return s.ToYieldInstruction();
|
|
}
|
|
|
|
static void expectRecursiveCallError() => LogAssert.Expect(LogType.Error, Constants.recursiveCallError);
|
|
|
|
[UnityTest]
|
|
public IEnumerator SetSequenceProgressTo_1_AtCycleEnd() {
|
|
Sequence s = default;
|
|
s = Sequence.Create(2)
|
|
.ChainDelay(0.01f)
|
|
.Chain(Tween.Custom(0f, 1f, 0.01f, val => {
|
|
if (val == 1f) {
|
|
// print("custom val == 1f");
|
|
expectRecursiveCallError();
|
|
s.progress = 1f;
|
|
}
|
|
}));
|
|
yield return s.ToYieldInstruction();
|
|
}
|
|
[UnityTest]
|
|
public IEnumerator SetSequenceProgressTo_0_AtCycleEnd() {
|
|
Sequence s = default;
|
|
s = Sequence.Create(2)
|
|
.Chain(Tween.Custom(0f, 1f, 0.01f, val => {
|
|
if (val == 1f) {
|
|
// print("custom val == 1f");
|
|
expectRecursiveCallError();
|
|
s.progress = 0f;
|
|
}
|
|
}));
|
|
yield return s.ToYieldInstruction();
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator SequenceStopOrCompleteFromCustomCallback() {
|
|
yield return test(s => {
|
|
// callback can be called twice when Time.delta time is less than TweenSetting.minDuration
|
|
s.Complete();
|
|
});
|
|
yield return test(s => s.Stop());
|
|
IEnumerator test(Action<Sequence> action) {
|
|
Sequence s = default;
|
|
s = Sequence.Create(2)
|
|
.ChainDelay(minDuration)
|
|
.Chain(Tween.Custom(0f, 1f, minDuration, _ => {
|
|
Assert.IsTrue(s.isAlive);
|
|
action(s);
|
|
Assert.IsFalse(s.isAlive);
|
|
}));
|
|
yield return s.ToYieldInstruction();
|
|
}
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator StopSequenceFromSequenceOnComplete() {
|
|
Sequence sequence = default;
|
|
sequence = Sequence.Create()
|
|
.OnComplete(() => {
|
|
Assert.IsFalse(sequence.isAlive);
|
|
sequence.Stop();
|
|
});
|
|
yield return sequence.ToYieldInstruction();
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator SettingSequenceRemainingCyclesInOnComplete() {
|
|
Sequence s = default;
|
|
s = Sequence.Create()
|
|
.OnComplete(() => {
|
|
Assert.IsFalse(s.isAlive);
|
|
expectIsDeadError();
|
|
s.SetRemainingCycles(2);
|
|
});
|
|
yield return s.ToYieldInstruction();
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator AddingStartedTweenToSequenceIsOk() {
|
|
var tween = Tween.PositionY(transform, getDt() * 3, 1f);
|
|
yield return null;
|
|
Assert.IsTrue(tween.isAlive);
|
|
Sequence.Create(tween).Stop();
|
|
Assert.IsFalse(tween.isAlive);
|
|
}
|
|
|
|
#if PRIME_TWEEN_DOTWEEN_ADAPTER
|
|
[Test]
|
|
public void SequenceDurationAfterChainLast() {
|
|
var seq = Tween.Delay(1f)
|
|
.Group(Tween.Delay(0.5f))
|
|
.ChainLast(Tween.Delay(0.1f));
|
|
Assert.AreEqual(1f, seq.duration);
|
|
|
|
seq.ChainLast(Tween.Delay(1f));
|
|
Assert.AreEqual(1.6f, seq.duration);
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator PrependInterval() {
|
|
{
|
|
var duration = getDt();
|
|
yield return Sequence.Create(Tween.Delay(duration)).PrependInterval(duration).ToYieldInstruction();
|
|
}
|
|
{
|
|
var s = Sequence.Create()
|
|
.ChainCallback(() => Assert.Fail())
|
|
.PrependInterval(100f);
|
|
yield return null;
|
|
s.Stop();
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void DontLogCantManipulateErrorInAdapter() {
|
|
var target = new GameObject().transform;
|
|
{
|
|
var t = Tween.Delay(target, 1f);
|
|
Sequence.Create(t);
|
|
Assert.AreEqual(0, target.DOKill());
|
|
Assert.AreEqual(0, target.DOKill(true));
|
|
LogAssert.NoUnexpectedReceived();
|
|
}
|
|
Object.DestroyImmediate(target.gameObject);
|
|
}
|
|
#endif
|
|
|
|
[UnityTest]
|
|
public IEnumerator Insert1() {
|
|
var seq = Sequence.Create();
|
|
int numCallbacks = 0;
|
|
seq.InsertCallback(0f, () => numCallbacks++);
|
|
Assert.AreEqual(0f, seq.duration);
|
|
yield return seq.ToYieldInstruction();
|
|
Assert.AreEqual(1, numCallbacks);
|
|
LogAssert.NoUnexpectedReceived();
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator Insert2() {
|
|
var seq = Sequence.Create();
|
|
int i = 0;
|
|
seq.InsertCallback(0f, transform, delegate {
|
|
Assert.AreEqual(0, i);
|
|
i++;
|
|
});
|
|
Assert.AreEqual(0f, seq.duration);
|
|
|
|
float dt = getDt();
|
|
float longestTime = dt * 10;
|
|
seq.InsertCallback(longestTime, () => {
|
|
Assert.AreEqual(2, i);
|
|
i++;
|
|
});
|
|
Assert.AreEqual(longestTime, seq.duration);
|
|
|
|
seq.InsertCallback(dt, () => {
|
|
Assert.AreEqual(1, i);
|
|
i++;
|
|
});
|
|
Assert.AreEqual(longestTime, seq.duration);
|
|
|
|
yield return seq.ToYieldInstruction();
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator Insert3() {
|
|
var seq = Sequence.Create();
|
|
|
|
seq.Insert(0f, Tween.Delay(1f));
|
|
Assert.AreEqual(1f, seq.duration);
|
|
|
|
seq.Insert(0.5f, Tween.Delay(1f));
|
|
Assert.AreEqual(1.5f, seq.duration);
|
|
|
|
seq.Insert(0.5f, Tween.Delay(1f));
|
|
Assert.AreEqual(1.5f, seq.duration);
|
|
|
|
seq.Insert(2f, Tween.Delay(1f));
|
|
Assert.AreEqual(3f, seq.duration);
|
|
|
|
seq.Chain(Tween.Delay(1f));
|
|
Assert.AreEqual(4f, seq.duration);
|
|
|
|
seq.Insert(5f, Tween.Delay(1f));
|
|
Assert.AreEqual(6f, seq.duration);
|
|
|
|
seq.Group(Tween.Delay(1f));
|
|
Assert.AreEqual(6f, seq.duration);
|
|
|
|
seq.Group(Tween.Delay(1.5f));
|
|
Assert.AreEqual(6.5f, seq.duration);
|
|
|
|
seq.Stop();
|
|
yield break;
|
|
}
|
|
|
|
[Test]
|
|
public void NestSequenceTwice() {
|
|
var main = Sequence.Create();
|
|
var nested = Sequence.Create();
|
|
main.Group(nested);
|
|
LogAssert.Expect(LogType.Error, Constants.nestSequenceTwiceError);
|
|
main.Group(nested);
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator SequenceCompleteRemainingCycles() {
|
|
var yoyoOrRewind = Random.value < 0.5f ? CycleMode.Yoyo : CycleMode.Rewind;
|
|
{
|
|
float val = -1f;
|
|
int numCompleted = 0;
|
|
Sequence.Create(9, yoyoOrRewind)
|
|
.Chain(Tween.Custom(0f, 1f, 1f, x => val = x))
|
|
.ChainCallback(() => numCompleted++)
|
|
.Complete();
|
|
Assert.AreEqual(1, numCompleted);
|
|
Assert.AreEqual(1f, val);
|
|
}
|
|
{
|
|
float val = -1f;
|
|
int numCompleted = 0;
|
|
Sequence.Create(10, yoyoOrRewind)
|
|
.Chain(Tween.Custom(0f, 1f, 1f, x => val = x))
|
|
.ChainCallback(() => numCompleted++)
|
|
.Complete();
|
|
Assert.AreEqual(1, numCompleted);
|
|
Assert.AreEqual(0f, val);
|
|
}
|
|
|
|
{
|
|
float val = -1f;
|
|
int numCompleted = 0;
|
|
var seq = Sequence.Create(9, yoyoOrRewind)
|
|
.Chain(Tween.Custom(0f, 1f, 100f, x => val = x))
|
|
.ChainCallback(() => numCompleted++);
|
|
seq.progress = 1f;
|
|
yield return null;
|
|
Assert.AreEqual(1, seq.cyclesDone);
|
|
Assert.AreEqual(1, numCompleted);
|
|
seq.Complete();
|
|
Assert.AreEqual(2, numCompleted);
|
|
Assert.AreEqual(1f, val);
|
|
}
|
|
{
|
|
float val = -1f;
|
|
int numCompleted = 0;
|
|
var seq = Sequence.Create(10, yoyoOrRewind)
|
|
.Chain(Tween.Custom(0f, 1f, 100f, x => val = x))
|
|
.ChainCallback(() => numCompleted++);
|
|
seq.progress = 1f;
|
|
yield return null;
|
|
Assert.AreEqual(1, seq.cyclesDone);
|
|
Assert.AreEqual(1, numCompleted);
|
|
seq.Complete();
|
|
Assert.AreEqual(1, numCompleted);
|
|
Assert.AreEqual(0f, val);
|
|
}
|
|
|
|
{
|
|
float val = -1f;
|
|
int numCompleted = 0;
|
|
Sequence.Create(Random.Range(1, 100), CycleMode.Restart)
|
|
.Chain(Tween.Custom(0f, 1f, 1f, x => val = x))
|
|
.ChainCallback(() => numCompleted++)
|
|
.Complete();
|
|
Assert.AreEqual(1, numCompleted);
|
|
Assert.AreEqual(1f, val);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void GetTweensCountOnSequence() {
|
|
Tween.StopAll();
|
|
Assert.AreEqual(0, Tween.GetTweensCount());
|
|
var seq = Tween.Position(transform, Vector3.one, 1f)
|
|
.Chain(Tween.Position(transform, Vector3.zero, 1f));
|
|
Assert.AreEqual(3, Tween.GetTweensCount()); // two tweens + sequence
|
|
Assert.AreEqual(2, Tween.GetTweensCount(transform)); // two tween on transform
|
|
seq.Stop();
|
|
}
|
|
|
|
/// report: https://forum.unity.com/threads/primetween-high-performance-animations-and-sequences.1479609/page-6#post-9802575
|
|
[UnityTest]
|
|
public IEnumerator SequenceUpdatesChildrenOnlyIfUpdatedSelf() {
|
|
var seq = Sequence.Create()
|
|
.ChainDelay(1)
|
|
.Chain(Sequence.Create()
|
|
.Chain(Tween.Custom(0f, 1f, 1f, _ => Assert.Fail())));
|
|
yield return null;
|
|
seq.Stop();
|
|
}
|
|
|
|
/// https://github.com/KyryloKuzyk/PrimeTween/discussions/112
|
|
[Test]
|
|
public void SequenceChainOrInsertCallbackBug1() {
|
|
var seq = Sequence.Create()
|
|
.ChainDelay(1f)
|
|
.ChainCallback(() => { })
|
|
.Group(Tween.Delay(1f));
|
|
Assert.AreEqual(2f, seq.duration);
|
|
}
|
|
[Test]
|
|
public void SequenceChainOrInsertCallbackBug2() {
|
|
var seq = Sequence.Create()
|
|
.ChainDelay(1f)
|
|
.ChainCallback(this, _ => { })
|
|
.Group(Tween.Delay(1f));
|
|
Assert.AreEqual(2f, seq.duration);
|
|
}
|
|
[Test]
|
|
public void SequenceChainOrInsertCallbackBug3() {
|
|
var seq = Sequence.Create()
|
|
.ChainDelay(1f)
|
|
.InsertCallback(0.5f, () => { })
|
|
.Group(Tween.Delay(1f));
|
|
Assert.AreEqual(1.5f, seq.duration);
|
|
}
|
|
[Test]
|
|
public void SequenceChainOrInsertCallbackBug4() {
|
|
var seq = Sequence.Create()
|
|
.ChainDelay(1f)
|
|
.InsertCallback(0.5f, this, _ => { })
|
|
.Group(Tween.Delay(1f));
|
|
Assert.AreEqual(1.5f, seq.duration);
|
|
}
|
|
}
|
|
#endif
|