2800 lines
102 KiB
C#

#if TEST_FRAMEWORK_INSTALLED
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using JetBrains.Annotations;
using NUnit.Framework;
using PrimeTween;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.TestTools;
using Assert = NUnit.Framework.Assert;
using AssertionException = UnityEngine.Assertions.AssertionException;
using Object = UnityEngine.Object;
using Random = UnityEngine.Random;
using SuppressMessage = System.Diagnostics.CodeAnalysis.SuppressMessageAttribute;
public partial class Tests {
[Test]
public void TweenTimeScaleWhileInSequence() {
var t = Tween.Delay(0.01f);
Sequence.Create(t);
expectCantManipulateTweenInsideSequence();
t.timeScale = 2f;
LogAssert.NoUnexpectedReceived();
Tween.StopAll();
}
[Test]
public async Task TweenTimeScaleOutlive() {
{
var tween = Tween.Delay(getDt() / 2);
var timeScaleTween = Tween.TweenTimeScale(tween, Random.value + 0.01f, float.MaxValue);
await tween;
Assert.IsFalse(timeScaleTween.isAlive);
}
{
var seq = Sequence.Create(Tween.Delay(getDt() / 2));
var timeScaleTween = Tween.TweenTimeScale(seq, Random.value + 0.01f, float.MaxValue);
await seq;
Assert.IsFalse(timeScaleTween.isAlive);
}
}
[Test]
public async Task TweenTimeScale() {
var t = Tween.PositionZ(transform, 10, 1);
const float iniTimeScale = 0.9f;
t.timeScale = iniTimeScale;
Assert.AreEqual(iniTimeScale, t.timeScale);
const float targetTimeScale = 0.5f;
await Tween.TweenTimeScale(t, targetTimeScale, 0.001f);
Assert.AreEqual(targetTimeScale, t.timeScale);
t.Complete();
}
[UnityTest]
public IEnumerator QuaternionDefaultValue() {
{
var q = Quaternion.Euler(0, 0, 45);
var def = new Quaternion();
Assert.AreEqual(Quaternion.identity.normalized, def.normalized);
Assert.AreNotEqual(Quaternion.Angle(Quaternion.identity, q), Quaternion.Angle(def, q));
Assert.AreEqual(Quaternion.Angle(Quaternion.identity, q), Quaternion.Angle(def.normalized, q));
}
{
Tween t = default;
var def = new Quaternion();
int numCallback = 0;
t = Tween.Custom(def, def, 0.01f, delegate {
numCallback++;
var startVal = t.tween.startValue.QuaternionVal;
var endVal = t.tween.endValue.QuaternionVal;
// Debug.Log($"{startVal}, {endVal}");
Assert.AreNotEqual(def, startVal);
Assert.AreNotEqual(def, endVal);
t.Stop();
});
yield return t.ToYieldInstruction();
Assert.AreEqual(1, numCallback);
}
}
/// This test can fail if Game window is set to 'Play Unfocused'
[UnityTest]
public IEnumerator StartValueIsAppliedOnFirstFrame() {
const int iniVal = -1;
float val = iniVal;
const int startValue = 0;
Tween.Custom(startValue, 1, 0.01f, newVal => val = newVal);
Assert.AreEqual(iniVal, val);
yield return new WaitForEndOfFrame();
Assert.AreEqual(startValue, val);
yield return new WaitForEndOfFrame();
Assert.AreNotEqual(startValue, val);
}
[Test]
public void SafetyChecksEnabled() {
#if !PRIME_TWEEN_SAFETY_CHECKS
Assert.Inconclusive();
#endif
}
[UnityTest]
public IEnumerator TweenIsDeadInOnComplete() {
Tween t = default;
t = Tween.Delay(0.01f, () => {
Assert.IsFalse(t.isAlive);
for (int i = 0; i < 6; i++) {
expectIsDeadError();
}
Assert.AreEqual(0, t.elapsedTime);
Assert.AreEqual(0, t.elapsedTimeTotal);
Assert.AreEqual(0, t.progress);
Assert.AreEqual(0, t.progressTotal);
Assert.AreEqual(0, t.duration);
Assert.AreEqual(0, t.durationTotal);
});
yield return t.ToYieldInstruction();
}
static void expectIsDeadError(bool isCreated = true) => LogAssert.Expect(LogType.Error, new Regex(isCreated ? Constants.isDeadMessage : "Tween or Sequence is not created properly."));
[Test]
public void ShakeDuplication1() {
var s1 = Tween.ShakeLocalPosition(transform, Vector3.one, 0.1f, startDelay: 0.1f);
var s2 = Tween.ShakeLocalPosition(transform, Vector3.one, 0.1f);
Assert.IsTrue(s1.isAlive);
Assert.IsTrue(s2.isAlive);
}
[UnityTest]
public IEnumerator ShakeDuplication2() {
var s1 = Tween.ShakeLocalPosition(transform, Vector3.one, 0.1f);
Assert.IsTrue(s1.isAlive);
var s2 = Tween.ShakeLocalPosition(transform, Vector3.one, 0.1f);
Assert.IsTrue(s1.isAlive);
yield return null;
// because two shakes are started the same frame, the first one completes the second one
Assert.IsTrue(s1.isAlive);
Assert.IsTrue(s2.isAlive);
}
[UnityTest]
public IEnumerator ShakeDuplication3() {
var s1 = Tween.ShakeLocalPosition(transform, Vector3.one, 0.1f);
yield return null;
var s2 = Tween.ShakeLocalPosition(transform, Vector3.one, 0.1f);
yield return null;
Assert.IsTrue(s1.isAlive);
Assert.IsTrue(s2.isAlive);
}
[UnityTest]
public IEnumerator ShakeDuplication4() {
const float startDelay = 0.05f;
var s1 = Tween.ShakeLocalPosition(transform, Vector3.one, 0.1f, startDelay: startDelay);
var s2 = Tween.ShakeLocalPosition(transform, Vector3.one, 0.1f, startDelay: 0.1f);
yield return Tween.Delay(startDelay + Time.deltaTime).ToYieldInstruction();
Assert.IsTrue(s1.isAlive);
Assert.IsTrue(s2.isAlive);
}
[UnityTest]
public IEnumerator ShakeDuplication5() {
var target = new GameObject(nameof(ShakeDuplication5)).transform;
target.localPosition = new Vector3(Random.value, Random.value, Random.value);
var iniPos = target.localPosition;
var s1 = Tween.ShakeLocalPosition(target, Vector3.one, 0.1f);
var seq = Sequence.Create(s1);
Assert.IsTrue(s1.isAlive);
var s2 = Tween.ShakeLocalPosition(target, Vector3.one, 0.1f);
Assert.IsTrue(s1.isAlive);
Assert.IsTrue(seq.isAlive);
Assert.IsTrue(s2.isAlive);
Assert.IsTrue(s1.tween.startFromCurrent);
Assert.IsTrue(s2.tween.startFromCurrent);
yield return null;
Assert.IsTrue(s1.isAlive);
Assert.IsTrue(seq.isAlive);
Assert.IsTrue(s2.isAlive);
Assert.IsFalse(s1.tween.startFromCurrent);
Assert.IsFalse(s2.tween.startFromCurrent);
Assert.AreEqual(iniPos, s1.tween.startValue.Vector3Val);
Assert.AreEqual(iniPos, s2.tween.startValue.Vector3Val);
}
[Test]
public void ShakeDuplicationDestroyedTarget() {
var target = new GameObject(nameof(ShakeDuplicationDestroyedTarget)).transform;
Tween.ShakeLocalPosition(target, Vector3.one, 0.1f);
Object.DestroyImmediate(target.gameObject);
Tween.ShakeLocalPosition(target, Vector3.one, 0.1f);
expectTargetIsNull();
}
static void expectTargetIsNull() => LogAssert.Expect(LogType.Error, new Regex("Tween's target is null"));
[UnityTest]
public IEnumerator FramePacing() {
Tween.StopAll();
const int fps = 120;
Application.targetFrameRate = fps;
QualitySettings.vSyncCount = 0;
Assert.AreEqual(fps, Application.targetFrameRate);
yield return null;
{
var go = new GameObject();
go.AddComponent<FramePacingTest>();
while (go != null) {
yield return null;
}
}
Application.targetFrameRate = targetFrameRate;
yield return null;
}
#if UNITY_EDITOR
[Test]
public void GenerateCode() {
const string path = "Packages/com.kyrylokuzyk.primetween/Editor/CodeGenerator.asset";
var cg = UnityEditor.AssetDatabase.LoadAssetAtPath<CodeGenerator>(path);
cg.generateAllMethods();
}
#endif
[Test]
public void TweenCompleteInvokeOnCompleteParameter() {
{
int numCompleted = 0;
var t = Tween.Scale(transform, 1.5f, 0.01f).OnComplete(() => numCompleted++);
t.Complete();
Assert.AreEqual(1, numCompleted);
t.Complete();
Assert.AreEqual(1, numCompleted);
}
/*{
int numCompleted = 0;
var t = Tween.Scale(transform, 1.5f, 0.01f).OnComplete(() => numCompleted++);
t.Complete(false);
Assert.AreEqual(0, numCompleted);
t.Complete(false);
Assert.AreEqual(0, numCompleted);
t.Complete();
Assert.AreEqual(0, numCompleted);
}*/
}
[Test]
public void IgnoreFromInScale() {
var t = Tween.Scale(transform, 1.5f, 0.01f);
Assert.IsTrue(t.tween.startFromCurrent);
}
[UnityTest]
public IEnumerator FromToValues() {
{
var duration = getDt() * Random.Range(0.5f, 1.5f);
var t = Tween.Custom(0, 0, duration, ease: Ease.Linear, onValueChange: delegate { });
while (t.isAlive) {
Assert.AreEqual(t.elapsedTime, t.progress * duration, 0.001f);
Assert.AreEqual(t.interpolationFactor, t.progress);
Assert.AreEqual(t.interpolationFactor, t.progressTotal);
yield return null;
}
}
var from = Random.value;
var to = Random.value;
var data = new TweenSettings<float>(from, to, 0.01f);
{
var t = Tween.LocalPositionX(transform, data);
Assert.AreEqual(from, t.tween.startValue.FloatVal);
Assert.AreEqual(to, t.tween.endValue.FloatVal);
}
{
var t = Tween.Custom(this, data, delegate { });
Assert.AreEqual(from, t.tween.startValue.FloatVal);
Assert.AreEqual(to, t.tween.endValue.FloatVal);
}
}
[UnityTest]
public IEnumerator TweenCompleteWhenInterpolationCompleted() {
float curVal = 0f;
var t = Tween.Custom(this, 0f, 1f, 0.05f, (_, val) => curVal = val, cycles: 2, endDelay: 1f, cycleMode: CycleMode.Yoyo);
while (t.interpolationFactor < 1f) {
yield return null;
}
Assert.AreEqual(0, t.cyclesDone);
Assert.AreEqual(1f, curVal);
t.Complete();
Assert.AreEqual(0f, curVal);
}
[Test]
public async Task CycleModeIncremental() {
{
float curVal = 0f;
await Tween.Custom(this, 0f, 1f, 0.01f, (_, val) => curVal = val, cycles: 2, cycleMode: CycleMode.Incremental);
Assert.AreEqual(2f, curVal);
}
{
float curVal = 0f;
await Tween.Custom(this, 0f, 1f, 0.01f, (_, val) => curVal = val, cycles: 4, cycleMode: CycleMode.Incremental);
Assert.AreEqual(4f, curVal);
}
{
float curVal = 0f;
Tween.Custom(this, 0f, 1f, 0.01f, (_, val) => curVal = val, cycles: 2, cycleMode: CycleMode.Incremental)
.Complete();
Assert.AreEqual(2f, curVal);
}
{
float curVal = 0f;
Tween.Custom(this, 0f, 1f, 0.01f, (_, val) => curVal = val, cycles: 4, cycleMode: CycleMode.Incremental)
.Complete();
Assert.AreEqual(4f, curVal);
}
}
[Test]
public void TweenCompleteWithEvenCycles() {
{
float curVal = 0f;
Tween.Custom(this, 0f, 1f, 0.05f, (_, val) => curVal = val, cycles: 2, cycleMode: CycleMode.Restart)
.Complete();
Assert.AreEqual(1f, curVal);
}
{
float curVal = 0f;
Tween.Custom(this, 0f, 1f, 0.05f, (_, val) => curVal = val, cycles: 4, cycleMode: CycleMode.Restart)
.Complete();
Assert.AreEqual(1f, curVal);
}
{
float curVal = 0f;
Tween.Custom(this, 0f, 1f, 0.05f, (_, val) => curVal = val, cycles: 2, cycleMode: CycleMode.Yoyo)
.Complete();
Assert.AreEqual(0f, curVal);
}
{
float curVal = 0f;
Tween.Custom(this, 0f, 1f, 0.05f, (_, val) => curVal = val, cycles: 4, cycleMode: CycleMode.Yoyo)
.Complete();
Assert.AreEqual(0f, curVal);
}
{
float curVal = 0f;
Tween.Custom(this, 0f, 1f, 0.05f, (_, val) => curVal = val, cycles: 2, cycleMode: CycleMode.Rewind)
.Complete();
Assert.AreEqual(0f, curVal);
}
{
float curVal = 0f;
Tween.Custom(this, 0f, 1f, 0.05f, (_, val) => curVal = val, cycles: 4, cycleMode: CycleMode.Rewind)
.Complete();
Assert.AreEqual(0f, curVal);
}
}
[Test]
public void TweenCompleteWithOddCycles() {
{
float curVal = 0f;
Tween.Custom(this, 0f, 1f, 0.05f, (_, val) => curVal = val, cycles: 1, cycleMode: CycleMode.Yoyo)
.Complete();
Assert.AreEqual(1f, curVal);
}
{
float curVal = 0f;
Tween.Custom(this, 0f, 1f, 0.05f, (_, val) => curVal = val, cycles: 3, cycleMode: CycleMode.Yoyo)
.Complete();
Assert.AreEqual(1f, curVal);
}
}
[UnityTest]
public IEnumerator TweenOnCompleteIsCalledOnceForTweenInSequence() {
for (int i = 0; i < 1; i++) {
loopBegin:
float curVal = 0f;
int numCompleted = 0;
float duration = Mathf.Max(minDuration, getDt()) * 10f;
var t = Tween.Custom(this, 0f, 1f, duration, (_, val) => curVal = val, cycles: 1, cycleMode: CycleMode.Yoyo)
.OnComplete(() => numCompleted++);
var s = t.Chain(Tween.Delay(duration));
while (true) {
if (!t.isAlive) {
goto loopBegin;
}
if (t.cyclesDone == 1) {
break;
}
yield return null;
}
Assert.IsTrue(t.isAlive);
Assert.AreEqual(1, t.tween.getCyclesDone());
Assert.IsTrue(t.tween.sequence.IsCreated);
Assert.AreEqual(1, numCompleted);
Assert.IsTrue(s.isAlive);
Assert.AreEqual(1f, curVal);
s.Complete();
Assert.AreEqual(1f, curVal);
Assert.AreEqual(1, numCompleted);
}
}
[Test]
public void TweenCompleteInSequence() {
float curVal = 0f;
var t = Tween.Custom(this, 0f, 1f, 0.05f, (_, val) => curVal = val, cycles: 1, cycleMode: CycleMode.Yoyo);
var s = t.Chain(Tween.Delay(0.05f));
Assert.IsTrue(t.isAlive);
Assert.AreEqual(0, t.tween.getCyclesDone());
Assert.IsTrue(t.tween.sequence.IsCreated);
Assert.IsTrue(s.isAlive);
Assert.AreNotEqual(1f, curVal);
s.Complete();
Assert.AreEqual(1f, curVal);
}
[Test]
public async Task AwaitExceptions() {
expectTweenWasStoppedBecauseException();
await Tween.Custom(this, 0f, 1f, 1f, delegate {
throw new Exception();
});
}
[UnityTest]
public IEnumerator CoroutineEnumeratorNotEnumeratedToTheEnd() {
Tween.StopAll();
Assert.AreEqual(0, tweensCount);
var t = Tween.Delay(TweenSettings.minDuration * 100);
var e = t.ToYieldInstruction();
Assert.IsTrue(e.MoveNext());
yield return e.Current;
Assert.IsTrue(t.isAlive);
while (t.isAlive) {
yield return null;
}
yield return null;
Assert.AreEqual(0, tweensCount);
testCompletedCorEnumerator(e);
}
[UnityTest]
public IEnumerator CoroutineEnumeratorInfiniteTween() {
{
var t = Tween.Position(transform, Vector3.one, getDt(), cycles: -1);
Tween.Delay(getDt() * 5f).OnComplete(() => t.Stop());
yield return t.ToYieldInstruction();
}
{
var t = Tween.Position(transform, Vector3.one, getDt(), cycles: -1);
Tween.Delay(getDt() * 5f).OnComplete(() => t.Complete());
yield return t.ToYieldInstruction();
}
}
[UnityTest]
public IEnumerator CoroutineEnumeratorMultipleToYieldInstruction() {
var t = Tween.Delay(0.01f);
var e = t.ToYieldInstruction();
Assert.Throws<AssertionException>(() => t.ToYieldInstruction());
t.Complete();
yield return e;
Assert.IsFalse(t.isAlive);
testCompletedCorEnumerator(e);
}
[UnityTest]
public IEnumerator CoroutineEnumeratorUsingDead() {
var t = Tween.Delay(0.01f);
var e = t.ToYieldInstruction();
yield return e;
Assert.IsFalse(t.isAlive);
testCompletedCorEnumerator(e);
}
static void testCompletedCorEnumerator(IEnumerator e) {
Assert.IsFalse(e.MoveNext());
Assert.Throws<AssertionException>(() => {
_ = e.Current;
});
Assert.Throws<NotSupportedException>(() => e.Reset());
}
[UnityTest]
public IEnumerator YieldInstructionsClash2() {
var test = new GameObject().AddComponent<YieldInstructionsClash>();
// ReSharper disable once LoopVariableIsNeverChangedInsideLoop
while (test != null) {
yield return null;
}
}
[UnityTest]
public IEnumerator YieldInstructionsClash() {
Application.targetFrameRate = 100;
yield return null;
Assert.AreEqual(0, tweensCount);
for (int i = 0; i < 1; i++) {
{
var t1 = Tween.Delay(minDuration);
int frameStart = Time.frameCount;
yield return t1.ToYieldInstruction();
Assert.AreEqual(1, Time.frameCount - frameStart);
Assert.IsFalse(t1.isAlive);
var t2 = Tween.Delay(minDuration);
t2.ToYieldInstruction();
t2.Complete();
}
{
var t1 = Tween.Delay(minDuration);
t1.ToYieldInstruction();
yield return null;
yield return null;
Assert.IsFalse(t1.isAlive);
var t2 = Tween.Delay(minDuration);
t2.ToYieldInstruction();
t2.Complete();
}
}
Application.targetFrameRate = targetFrameRate;
}
[Test]
public void TweenDuplicateInSequence() {
var t1 = Tween.Delay(0.1f);
var t2 = Tween.Delay(0.1f);
var s = t1.Chain(t2);
expectNestTweenTwiceError();
s.Chain(t1);
}
/*[UnityTest]
public IEnumerator WaitStopFromValueChange2() {
Tween t = default;
t = Tween.WaitWhile(this, _ => {
Assert.IsTrue(t.isAlive);
t.Stop();
return true;
});
yield return t.ToYieldInstruction();
}
[UnityTest]
public IEnumerator WaitCompleteFromValueChange2() {
Tween t = default;
int numValueChanged = 0;
t = Tween.WaitWhile(this, _ => {
numValueChanged++;
switch (numValueChanged) {
case 1:
Assert.IsTrue(t.isAlive);
t.Complete();
break;
case 2:
Assert.IsFalse(t.isAlive);
break;
default: throw new Exception();
}
return true;
});
yield return t.ToYieldInstruction();
}
[UnityTest]
public IEnumerator WaitCompleteFromValueChange() {
var target = new GameObject();
int numValueChanged = 0;
yield return Tween.WaitWhile(target, _ => {
numValueChanged++;
switch (numValueChanged) {
case 1:
Assert.AreEqual(1, Tween.CompleteAll(target, 1, 1));
break;
case 2:
Assert.AreEqual(0, Tween.CompleteAll(target, 0, 0));
break;
default: throw new Exception();
}
return true;
}).ToYieldInstruction();
}
[UnityTest]
public IEnumerator WaitStopFromValueChange() {
var target = new GameObject();
yield return Tween.WaitWhile(target, _ => {
Assert.AreEqual(1, Tween.StopAll(target, 1, 1));
return true;
}).ToYieldInstruction();
}
[UnityTest]
public IEnumerator TweenWait() {
var timeStart = Time.time;
int numOnCompleteDone = 0;
const float duration = 0.3f;
var t = Tween.WaitWhile(this, _ => Time.time - timeStart < duration)
.OnComplete(() => numOnCompleteDone++);
yield return null;
Assert.IsTrue(t.isAlive);
yield return new WaitForSeconds(duration + 0.01f);
Assert.IsFalse(t.isAlive);
Assert.AreEqual(1, numOnCompleteDone);
LogAssert.NoUnexpectedReceived();
}
[Test]
public void TweenWaitInstantComplete() {
int numOnCompleteDone = 0;
var t = Tween.WaitWhile(this, _ => true).OnComplete(() => numOnCompleteDone++);
Assert.IsTrue(t.isAlive);
t.Complete();
Assert.IsFalse(t.isAlive);
Assert.AreEqual(1, numOnCompleteDone);
}
[Test]
public void TweenWaitInstantStop() {
int numOnCompleteDone = 0;
var t = Tween.WaitWhile(this, _ => true).OnComplete(() => numOnCompleteDone++);
Assert.IsTrue(t.isAlive);
t.Stop();
Assert.IsFalse(t.isAlive);
Assert.AreEqual(0, numOnCompleteDone);
}
[Test]
public void TweenWaitException() {
var t = Tween.WaitWhile(this, _ => throw new Exception()).OnComplete(Assert.Fail);
Assert.IsTrue(t.isAlive);
LogAssert.Expect(LogType.Error, new Regex("Tween was stopped because of exception"));
LogAssert.Expect(LogType.Error, new Regex(Constants.onCompleteCallbackIgnored));
t.Complete();
Assert.IsFalse(t.isAlive);
}
[UnityTest]
public IEnumerator TweenWaitDuration() {
// Application.targetFrameRate = 60;
var t = Tween.WaitWhile(this, _ => true);
validate();
Assert.AreEqual(0, t.elapsedTime);
Assert.AreEqual(0, t.elapsedTimeTotal);
yield return null;
Assert.AreNotEqual(0, t.elapsedTime);
Assert.AreNotEqual(0, t.elapsedTimeTotal);
// for (int i = 0; i < 60; i++) {
// yield return null;
// Debug.Log($"{t.elapsedTime}, {t.elapsedTimeTotal}");
// }
validate();
t.Complete();
void validate() {
Assert.AreEqual(-1, t.cyclesTotal);
Assert.AreEqual(0, t.cyclesDone);
Assert.IsTrue(float.IsPositiveInfinity(t.duration));
Assert.IsTrue(float.IsPositiveInfinity(t.durationTotal));
Assert.AreEqual(0, t.progress);
Assert.AreEqual(0, t.progressTotal);
Assert.AreEqual(0, t.interpolationFactor);
}
}*/
[Test]
public void ZeroDurationWarning() {
var oldSetting = PrimeTweenConfig.warnZeroDuration;
try {
PrimeTweenConfig.warnZeroDuration = true;
LogAssert.Expect(LogType.Warning, new Regex(nameof(PrimeTweenManager.warnZeroDuration)));
Tween.Custom(this, 0, 1, 0, delegate{});
PrimeTweenConfig.warnZeroDuration = false;
Tween.Custom(this, 0, 1, 0, delegate{});
LogAssert.NoUnexpectedReceived();
} finally {
PrimeTweenConfig.warnZeroDuration = oldSetting;
}
}
[Test]
public void CompleteTweenTwice() {
int numCompleted = 0;
var t = createCustomTween(1)
.OnComplete(() => numCompleted++);
t.Complete();
Assert.AreEqual(1, numCompleted);
t.Complete();
Assert.AreEqual(1, numCompleted);
}
[UnityTest]
public IEnumerator FromValueShouldNotChangeBetweenCycles() {
var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
var origPos = new Vector3(10, 10, 10);
cube.transform.position = origPos;
var tween = Tween.Position(cube.transform, new Vector3(20, 10, 10), 0.01f, cycles: 5);
Assert.IsTrue(tween.isAlive);
Assert.IsNotNull(tween.tween.getter);
while (tween.isAlive) {
yield return null;
Assert.AreEqual(origPos, tween.tween.startValue.Vector3Val, "'From' should not change after a cycle. This can happen if tween resets startFromCurrent after a cycle.");
}
Object.Destroy(cube);
}
[Test]
public void SettingIsPausedOnTweenInSequenceDisplayError() {
var target = new object();
var t = Tween.Delay(target, 0.01f);
Sequence.Create(t);
expectError();
t.isPaused = true;
expectError();
Tween.SetPausedAll(true, target);
expectError();
Tween.SetPausedAll(false, target);
void expectError() {
expectCantManipulateTweenInsideSequence();
}
}
[Test]
public void SettingCyclesOnDeadTweenDisplaysError() {
var t = createTween();
Assert.IsTrue(t.isAlive);
t.Complete();
Assert.IsFalse(t.isAlive);
expectIsDeadError();
t.SetRemainingCycles(5);
}
[Test]
public void TestDeadTween() {
var t = createDeadTween();
expectError();
t.isPaused = true;
t.Stop();
t.Complete();
// t.Revert();
expectError();
t.SetRemainingCycles(10);
expectError();
t.OnComplete(delegate{});
expectError();
t.OnComplete(this, delegate { });
expectError();
t.timeScale = 0;
void expectError() {
expectIsDeadError();
}
}
static Tween createDeadTween() {
var t = createCustomTween(0.1f);
t.Complete();
Assert.IsFalse(t.isAlive);
return t;
}
[UnityTest]
public IEnumerator TweenIsPaused() {
var val = 0f;
var t = Tween.Custom(this, 0, 1, 1, (_, newVal) => {
val = newVal;
});
t.isPaused = true;
yield return null;
Assert.AreEqual(0, val);
yield return null;
Assert.AreEqual(0, val);
yield return null;
Assert.AreEqual(0, val);
t.isPaused = false;
yield return null;
Assert.AreNotEqual(0, val);
}
[UnityTest]
public IEnumerator SequenceIsPaused() {
var val = 0f;
var t = Tween.Custom(this, 0, 1, 1, (_, newVal) => {
val = newVal;
});
var s = Sequence.Create(t);
s.isPaused = true;
yield return null;
Assert.AreEqual(0, val);
yield return null;
Assert.AreEqual(0, val);
yield return null;
Assert.AreEqual(0, val);
s.isPaused = false;
yield return null;
Assert.AreNotEqual(0, val);
}
const int capacityForTest = 800;
[UnityTest]
public IEnumerator TweensCapacity() {
Tween.StopAll();
Assert.AreEqual(0, tweensCount);
PrimeTweenConfig.SetTweensCapacity(capacityForTest);
Assert.AreEqual(capacityForTest, tweensCapacity);
PrimeTweenConfig.SetTweensCapacity(0);
Assert.AreEqual(0, tweensCapacity);
LogAssert.Expect(LogType.Warning, new Regex("Please increase the capacity"));
Tween.Delay(0.0001f);
Tween.Delay(0.0001f); // created before set capacity
PrimeTweenConfig.SetTweensCapacity(capacityForTest);
Assert.AreEqual(capacityForTest, tweensCapacity);
var delay = Tween.Delay(0.0001f);
yield return delay.ToYieldInstruction(); // should not display warning
Assert.IsFalse(delay.isAlive);
yield return null; // the yielded tween is not yet released when the coroutine completes. The release will happen only in a frame
Assert.AreEqual(0, tweensCount);
LogAssert.NoUnexpectedReceived();
}
static int tweensCapacity => PrimeTweenManager.Instance.currentPoolCapacity;
[Test]
public void ListResize() {
Tween.StopAll();
Assert.AreEqual(0, tweensCount);
var list = new List<ReusableTween>();
test(2, 2);
Assert.AreNotEqual(list[0], list[1]);
test(0, 2);
test(10, 10);
test(2, 5);
test(10, 20);
test(5, 30);
test(6, 29);
test(4, 31);
test(5, 32);
test(5, 31);
test(4, 31);
test(3, 31);
test(0, 31);
test(31, 31);
Assert.Throws<AssertionException>(() => test(32, 31));
test(0, 0);
test(10, 10);
void test(int newCount, int newCapacity) {
PrimeTweenManager.resizeAndSetCapacity(list, newCount, newCapacity);
Assert.AreEqual(newCount, list.Count);
Assert.AreEqual(newCapacity, list.Capacity);
PrimeTweenConfig.SetTweensCapacity(newCapacity);
Assert.AreEqual(newCapacity, tweensCapacity);
}
PrimeTweenConfig.SetTweensCapacity(capacityForTest);
}
static ShakeSettings shakeSettings {
get {
if (Random.value < 0.5f) {
return new ShakeSettings(Vector3.one, 1f, 10f, false);
}
return new ShakeSettings(Vector3.one, 1f, 10f, false, Ease.Linear);
}
}
[UnityTest]
public IEnumerator ShakeCompleteWhenStartDelayIsNotElapsed() {
var target = new GameObject(nameof(ShakeCompleteWhenStartDelayIsNotElapsed)).transform;
var iniPos = Random.value * Vector3.one;
target.localPosition = iniPos;
var t = Tween.ShakeLocalPosition(target, Vector3.one, 0.1f, startDelay: 0.1f);
yield return null;
Assert.AreEqual(0f, t.interpolationFactor);
Assert.AreEqual(iniPos, target.localPosition);
t.Complete();
Assert.AreEqual(iniPos, target.localPosition);
}
[UnityTest]
public IEnumerator ShakeScale() {
var shakeTransform = new GameObject("shake target").transform;
shakeTransform.position = Vector3.one;
Assert.AreEqual(shakeTransform.localScale, Vector3.one);
var t = Tween.ShakeScale(shakeTransform, shakeSettings);
yield return null;
Assert.AreNotEqual(shakeTransform.localScale, Vector3.one);
t.Complete();
Assert.IsTrue(shakeTransform.localScale == Vector3.one);
Object.DestroyImmediate(shakeTransform.gameObject);
}
[UnityTest]
public IEnumerator ShakeLocalRotation() {
var shakeTransform = new GameObject("shake target").transform;
shakeTransform.position = Vector3.one;
Assert.AreEqual(shakeTransform.localRotation, Quaternion.identity);
var t = Tween.ShakeLocalRotation(shakeTransform, shakeSettings);
yield return null;
Assert.AreNotEqual(shakeTransform.localRotation, Quaternion.identity);
t.Complete();
Assert.IsTrue(shakeTransform.localRotation == Quaternion.identity);
Object.DestroyImmediate(shakeTransform.gameObject);
}
[UnityTest]
public IEnumerator ShakeLocalPosition() {
var shakeTransform = new GameObject("shake target").transform;
shakeTransform.position = Vector3.one;
Assert.AreEqual(shakeTransform.position, Vector3.one);
var t = Tween.ShakeLocalPosition(shakeTransform, shakeSettings);
yield return null;
Assert.AreNotEqual(shakeTransform.position, Vector3.one);
t.Complete();
Assert.IsTrue(shakeTransform.position == Vector3.one, shakeTransform.position.ToString());
Object.DestroyImmediate(shakeTransform.gameObject);
}
[UnityTest]
public IEnumerator ShakeCustom() {
var shakeTransform = new GameObject("shake target").transform;
var iniPos = Vector3.one;
shakeTransform.position = iniPos;
Assert.AreEqual(iniPos, shakeTransform.position);
var t = Tween.ShakeCustom(shakeTransform, iniPos, shakeSettings, (target, val) => target.localPosition = val);
yield return null;
Assert.AreNotEqual(iniPos, shakeTransform.position);
t.Complete();
Assert.IsTrue(iniPos == shakeTransform.position, iniPos.ToString());
}
[UnityTest]
public IEnumerator CreateShakeWhenTweenListHasNull() {
Tween.StopAll();
Assert.AreEqual(0, tweensCount);
Tween.Delay(0.0001f);
LogAssert.Expect(LogType.Error, "Shake's strength is (0, 0, 0).");
LogAssert.Expect(LogType.Error, new Regex("Shake's frequency should be > 0f"));
Tween.Delay(0.0001f)
.OnComplete(() => {
Assert.AreEqual(1, getNullTweensCount());
Tween.ShakeLocalPosition(transform, default).Complete();
});
yield return null;
yield return null;
yield return null;
Assert.AreEqual(0, tweensCount);
}
static int getNullTweensCount() => PrimeTweenManager.Instance.tweensCount - Tween.GetTweensCount();
[UnityTest]
public IEnumerator DelayNoTarget() {
int numCallbackCalled = 0;
var t = Tween.Delay(getDt() * 2f, () => numCallbackCalled++);
Assert.AreEqual(0, numCallbackCalled);
while (t.isAlive) {
yield return null;
}
Assert.AreEqual(1, numCallbackCalled);
}
[UnityTest]
public IEnumerator DelayFirstOverload() {
int numCallbackCalled = 0;
var t = Tween.Delay(this, getDt() * 3, () => numCallbackCalled++);
Assert.AreEqual(0, numCallbackCalled);
while (t.isAlive) {
yield return null;
}
Assert.AreEqual(1, numCallbackCalled);
}
[UnityTest]
public IEnumerator DelaySecondOverload() {
int numCallbackCalled = 0;
var t = Tween.Delay(this, getDt() * 3, _ => numCallbackCalled++);
Assert.AreEqual(0, numCallbackCalled);
while (t.isAlive) {
yield return null;
}
Assert.AreEqual(1, numCallbackCalled);
}
[UnityTest]
[SuppressMessage("ReSharper", "PossibleNullReferenceException")]
public IEnumerator NewTweenCreatedFromManualOnComplete() {
Tween.StopAll();
Assert.AreEqual(0, tweensCount);
var t1 = createTween().OnComplete(() => createTween());
createTween();
t1.Complete();
Assert.AreEqual(3, tweensCount);
checkTweensAreOrdered();
yield return null;
Assert.AreEqual(2, tweensCount);
checkTweensAreOrdered();
Tween.StopAll();
}
static void checkTweensAreOrdered() {
checkOrder(PrimeTweenManager.Instance.tweens);
checkOrder(PrimeTweenManager.Instance.lateUpdateTweens);
checkOrder(PrimeTweenManager.Instance.fixedUpdateTweens);
void checkOrder(List<ReusableTween> tweens) {
Assert.IsTrue(tweens.OrderBy(_ => _.id).SequenceEqual(tweens));
}
}
[UnityTest]
[SuppressMessage("ReSharper", "PossibleNullReferenceException")]
public IEnumerator NewTweenCreatedFromNormalOnComplete() {
Tween.StopAll();
Assert.AreEqual(0, tweensCount);
int numOnCompleteCalled = 0;
var t1 = createCustomTween(0.01f).OnComplete(() => {
numOnCompleteCalled++;
createCustomTween(0.01f);
createCustomTween(0.01f);
createCustomTween(0.01f);
});
Assert.AreEqual(1, tweensCount);
checkTweensAreOrdered();
while (t1.isAlive) {
yield return null;
}
Assert.AreEqual(1, numOnCompleteCalled);
Assert.AreEqual(3, tweensCount);
checkTweensAreOrdered();
}
[UnityTest]
public IEnumerator SetAllPaused() {
if (tweensCount != 0) {
var aliveCount = Tween.GetTweensCount();
Assert.AreEqual(Tween.StopAll(null), aliveCount);
}
Assert.AreEqual(0, tweensCount);
const int count = 10;
var tweens = new List<Tween>();
for (int i = 0; i < count; i++) {
tweens.Add(createCustomTween(1));
}
Assert.IsTrue(tweens.All(_ => !_.isPaused));
Assert.AreEqual(Tween.SetPausedAll(true, null), count);
Assert.IsTrue(tweens.All(_ => _.isPaused));
Assert.AreEqual(Tween.SetPausedAll(false, null), count);
Assert.IsTrue(tweens.All(_ => !_.isPaused));
Assert.IsTrue(tweens.All(_ => _.isAlive));
yield return null;
Assert.IsTrue(tweens.All(_ => _.isAlive));
foreach (var _ in tweens) {
_.Complete();
}
Assert.IsFalse(tweens.All(_ => _.isAlive));
}
[UnityTest]
public IEnumerator StopAllCalledFromOnValueChange() {
Tween.StopAll();
Assert.AreEqual(0, tweensCount);
int numOnValueChangeCalled = 0;
var t = Tween.Custom(this, 0, 1, 1f, delegate {
Assert.AreEqual(0, numOnValueChangeCalled);
numOnValueChangeCalled++;
var numStopped = Tween.StopAll(this);
Assert.AreEqual(1, numStopped);
});
Assert.IsTrue(t.isAlive);
yield return null;
yield return null;
Assert.IsFalse(t.isAlive);
LogAssert.NoUnexpectedReceived();
}
[UnityTest]
public IEnumerator RecursiveCompleteCallFromOnValueChange() {
int numOnValueChangeCalled = 0;
int numOnCompleteCalled = 0;
Tween t = default;
t = Tween.Custom(this, 0, 1, 1f, delegate {
// Debug.Log(val);
numOnValueChangeCalled++;
Assert.IsTrue(numOnValueChangeCalled <= 2);
t.Complete();
}).OnComplete(() => numOnCompleteCalled++);
Assert.IsTrue(t.isAlive);
while (t.isAlive) {
yield return null;
}
Assert.IsFalse(t.isAlive);
Assert.AreEqual(1, numOnCompleteCalled);
LogAssert.NoUnexpectedReceived();
}
[UnityTest]
public IEnumerator RecursiveCompleteAllCallFromOnValueChange() {
Tween.StopAll();
Assert.AreEqual(0, tweensCount);
int numOnValueChangeCalled = 0;
int numOnCompleteCalled = 0;
var t = Tween.Custom(this, 0, 1, 1f, delegate {
// Debug.Log(val);
numOnValueChangeCalled++;
switch (numOnValueChangeCalled) {
case 1: {
var numCompleted = Tween.CompleteAll(this);
Assert.AreEqual(1, numCompleted);
break;
}
case 2: {
var numCompleted = Tween.CompleteAll(this);
Assert.AreEqual(0, numCompleted);
break;
}
default:
throw new Exception();
}
}).OnComplete(() => numOnCompleteCalled++);
Assert.IsTrue(t.isAlive);
while (t.isAlive) {
yield return null;
}
Assert.IsFalse(t.isAlive);
Assert.AreEqual(1, numOnCompleteCalled);
yield return null;
Assert.AreEqual(0, tweensCount);
Assert.AreEqual(2, numOnValueChangeCalled);
LogAssert.NoUnexpectedReceived();
}
[UnityTest]
public IEnumerator RecursiveCompleteCallFromOnComplete() {
Tween.StopAll();
Assert.AreEqual(0, tweensCount);
int numOnCompleteCalled = 0;
Tween t = default;
t = Tween.Custom(this, 0, 1, minDuration, delegate {
}).OnComplete(() => {
numOnCompleteCalled++;
t.Complete();
});
Assert.IsTrue(t.isAlive);
while (t.isAlive) {
yield return null;
}
Assert.IsFalse(t.isAlive);
Assert.AreEqual(1, numOnCompleteCalled);
yield return null;
Assert.AreEqual(0, tweensCount);
}
[UnityTest]
public IEnumerator RecursiveCompleteAllCallFromOnComplete() {
Tween.StopAll();
Assert.AreEqual(0, tweensCount);
int numOnCompleteCalled = 0;
var t = Tween.Custom(this, 0, 1, minDuration, delegate {
}).OnComplete(() => {
numOnCompleteCalled++;
var numCompleted = Tween.CompleteAll(this);
Assert.AreEqual(0, numCompleted);
});
Assert.IsTrue(t.isAlive);
while (t.isAlive) {
yield return null;
}
Assert.IsFalse(t.isAlive);
Assert.AreEqual(1, numOnCompleteCalled);
yield return null;
Assert.AreEqual(0, tweensCount);
}
[UnityTest]
public IEnumerator StopAllCalledFromOnValueChange2() {
int numOnValChangedCalled = 0;
var t = Tween.Custom(this, 0, 1, 0.0001f, (_, val) => {
// Debug.Log(val);
Assert.AreEqual(0, val);
Assert.AreEqual(0, numOnValChangedCalled);
numOnValChangedCalled++;
var numStopped = Tween.StopAll(this);
Assert.AreEqual(1, numStopped);
});
Assert.IsTrue(t.isAlive);
yield return null;
Assert.IsFalse(t.isAlive);
Assert.AreEqual(1, numOnValChangedCalled);
}
[UnityTest]
public IEnumerator TweenCanBeNullInProcessAllMethod() {
Assert.AreEqual(0, tweensCount);
Tween.Custom(this, 0, 1, 0.0001f, delegate {
// Debug.Log($"t1 val {val}");
});
Tween.Custom(this, 0, 1, 0.0001f, delegate {
// Debug.Log($"t2 val {val}");
Assert.AreEqual(0, getNullTweensCount());
Assert.AreEqual(Tween.StopAll(this), 2);
});
yield return null;
LogAssert.NoUnexpectedReceived();
}
[UnityTest]
public IEnumerator TweenCanBeNullInOnComplete() {
Tween.StopAll();
Assert.AreEqual(0, tweensCount);
int numOnCompleteCalled = 0;
Tween.Custom(this, 0, 1, 0.0001f, delegate{});
Tween.Custom(this, 0, 1, 0.0001f, delegate {
}).OnComplete(() => {
numOnCompleteCalled++;
Assert.AreEqual(1, getNullTweensCount());
var numStopped = Tween.StopAll(this);
Assert.AreEqual(0, numStopped);
});
yield return null;
Assert.AreEqual(1, numOnCompleteCalled);
LogAssert.NoUnexpectedReceived();
}
[UnityTest]
public IEnumerator TweenShouldBeDeadInOnValueChangeAfterCallingComplete() {
// Debug.Log(nameof(TweenShouldBeDeadInOnValueChangeAfterCallingComplete));
var target = new GameObject(nameof(TweenShouldBeDeadInOnValueChangeAfterCallingComplete));
int numOnValueChangeCalled = 0;
Tween t = default;
t = Tween.Custom(target, 0, 1, minDuration, (_, val) => {
// Debug.Log(val);
Assert.IsTrue(val == 0 || val == 1);
numOnValueChangeCalled++;
switch (numOnValueChangeCalled) {
case 1:
Assert.IsTrue(t.isAlive);
if (Random.value < 0.5f) {
t.Complete();
} else {
Assert.AreEqual(Tween.CompleteAll(target), 1);
}
break;
case 2:
// when Complete() is called, it's expected that onValueChange will be reported once again
break;
default: throw new Exception();
}
});
Assert.AreEqual(1, Tween.SetPausedAll(true, target));
Assert.AreEqual(1, Tween.SetPausedAll(false, target));
yield return null;
Assert.IsFalse(t.isAlive);
Assert.AreEqual(2, numOnValueChangeCalled);
}
[Test]
public void NumProcessed() {
Tween.StopAll();
Assert.AreEqual(0, tweensCount);
var target1 = new object();
var target2 = new object();
createWithTarget1(); // 1
createWithTarget1(); // 2
createWithTarget1(); // 3
createWithTarget2(); // 1
createWithTarget2(); // 2
createWithTarget1(); // 4
createWithTarget2(); // 3
Assert.AreEqual(4, Tween.SetPausedAll(true, target1));
Assert.AreEqual(4, Tween.SetPausedAll(false, target1));
Assert.AreEqual(4, Tween.StopAll(target1));
Assert.AreEqual(0, Tween.StopAll(target1));
Assert.AreEqual(0, Tween.CompleteAll(target1));
Assert.AreEqual(0, Tween.SetPausedAll(true, target1));
Assert.AreEqual(3, Tween.SetPausedAll(true, target2));
Assert.AreEqual(3, Tween.SetPausedAll(false, target2));
Assert.AreEqual(3, Tween.CompleteAll(target2));
Assert.AreEqual(0, Tween.CompleteAll(target2));
Assert.AreEqual(0, Tween.StopAll(target2));
void createWithTarget1() => Tween.Custom(target1, 0, 1, 0.0001f, delegate { });
void createWithTarget2() => Tween.Custom(target2, 0, 1, 0.0001f, delegate { });
}
[UnityTest]
public IEnumerator TweenIsAliveForWholeDuration() {
int numOnValueChangedCalled = 0;
int numOnValueChangedCalledAfterComplete = 0;
Tween t = default;
var target = new object();
bool isCompleteCalled = false;
const float duration = 0.3f;
t = Tween.Custom(target, 0, 1, duration, (_, val) => {
// Debug.Log(val);
numOnValueChangedCalled++;
if (isCompleteCalled) {
numOnValueChangedCalledAfterComplete++;
}
Assert.AreEqual(!isCompleteCalled, t.isAlive);
if (val > duration / 2) {
isCompleteCalled = true;
t.Complete();
}
}).OnComplete(() => {
Assert.IsTrue(t.IsCreated);
Assert.IsFalse(t.isAlive);
Assert.AreEqual(0, Tween.StopAll(target));
});
while (t.isAlive) {
yield return null;
}
Assert.IsTrue(numOnValueChangedCalled > 1);
Assert.AreEqual(1, numOnValueChangedCalledAfterComplete);
}
[Test]
public void SetPauseAll() {
var target = new object();
var t = Tween.Custom(target, 0, 1, 1, delegate{});
Assert.AreEqual(0, Tween.SetPausedAll(false, target));
Assert.AreEqual(1, Tween.SetPausedAll(true, target));
Assert.AreEqual(0, Tween.SetPausedAll(true, target));
Assert.AreEqual(1, Tween.SetPausedAll(false, target));
Assert.AreEqual(0, Tween.SetPausedAll(false, target));
t.Stop();
Assert.AreEqual(0, Tween.SetPausedAll(true, target));
}
[UnityTest]
public IEnumerator StopByTargetFromOnValueChange() {
var target = new GameObject();
int numOnValueChangeCalled = 0;
var t = Tween.Custom(target, 0, 1, 1, delegate {
numOnValueChangeCalled++;
var numStopped = Tween.StopAll(target);
Assert.AreEqual(1, numStopped);
});
Assert.AreEqual(0, numOnValueChangeCalled);
Assert.IsTrue(t.isAlive);
yield return null;
Assert.IsFalse(t.isAlive);
Assert.AreEqual(1, numOnValueChangeCalled);
}
[UnityTest]
public IEnumerator TweenPropertiesDefault() {
if (tweensCount != 0) {
Tween.StopAll();
Assert.AreEqual(0, tweensCount);
}
{
yield return Tween.Delay(0.001f).ToYieldInstruction();
Assert.AreEqual(1, tweensCount);
yield return null;
Assert.AreEqual(0, tweensCount);
}
{
var t = Tween.Delay(0f);
Assert.IsTrue(t.isAlive);
validate(t, true);
}
{
var t = new Tween();
Assert.IsFalse(t.isAlive);
expectError(false);
Assert.AreEqual(0, t.cyclesTotal);
validate(t, false, false);
}
{
var t = Tween.Delay(1);
t.Complete();
Assert.IsFalse(t.isAlive);
expectError();
Assert.AreEqual(0, t.cyclesTotal);
validate(t, false);
}
{
var t = Tween.Delay(1);
t.Stop();
Assert.IsFalse(t.isAlive);
expectError();
Assert.AreEqual(0, t.cyclesTotal);
validate(t, false);
}
void validate(Tween t, bool isAlive, bool isCreated = true) {
if (!isAlive) {
for (int i = 0; i < 8; i++) {
expectError(isCreated);
}
}
Assert.AreEqual(0, t.elapsedTime);
Assert.AreEqual(0, t.elapsedTimeTotal);
Assert.AreEqual(0, t.cyclesDone);
Assert.AreEqual(0, t.duration);
Assert.AreEqual(0, t.durationTotal);
Assert.AreEqual(0, t.progress);
Assert.AreEqual(0, t.progressTotal);
Assert.AreEqual(0, t.interpolationFactor);
if (!isAlive) {
expectError(isCreated);
}
Assert.AreEqual(1, t.timeScale);
}
{
const float duration = 0.123f;
var t = Tween.PositionY(transform, 0, duration, Ease.Linear, -1);
Assert.AreEqual(duration, t.duration);
Assert.IsTrue(float.IsPositiveInfinity(t.durationTotal));
Assert.AreEqual(0, t.progress);
Assert.AreEqual(0, t.progressTotal);
t.Stop();
validate(t, false);
}
void expectError(bool isCreated = true) {
expectIsDeadError(isCreated);
}
}
[UnityTest]
public IEnumerator TweenProperties() {
float duration = Mathf.Max(minDuration, getDt() * Random.Range(0.5f, 5f));
int numCyclesExpected = Random.Range(1, 3);
Tween t = default;
float startDelay = getDt() * Random.Range(0.1f, 1.2f);
float endDelay = getDt() * Random.Range(0.1f, 1.2f);
float durationExpected = startDelay + duration + endDelay;
float totalDurationExpected = durationExpected * numCyclesExpected;
float timeStart = Time.time;
t = Tween.Custom(this, 1f, 2f, duration, ease: Ease.Linear, cycles: numCyclesExpected, startDelay: startDelay, endDelay: endDelay, onValueChange: (_, val) => {
val -= 1f;
var elapsedTimeTotalExpected = Time.time - timeStart;
var elapsedTimeExpected = elapsedTimeTotalExpected - durationExpected * t.cyclesDone;
// Debug.Log($"val: {val}, progress: {t.progress}, elapsedTimeExpected: {elapsedTimeExpected}, elapsedTimeTotalExpected: {elapsedTimeTotalExpected}");
const float tolerance = 0.001f;
if (val < 1) {
Assert.AreEqual(elapsedTimeExpected, t.elapsedTime, tolerance);
Assert.AreEqual(elapsedTimeTotalExpected, t.elapsedTimeTotal, tolerance, $"val: {val},duration: {duration}, numCyclesExpected: {numCyclesExpected}");
Assert.AreEqual(Mathf.Min(elapsedTimeTotalExpected / totalDurationExpected, 1f), t.progressTotal, tolerance);
Assert.AreEqual(elapsedTimeExpected / durationExpected, t.progress, tolerance);
}
Assert.AreEqual(numCyclesExpected, t.cyclesTotal);
Assert.AreEqual(durationExpected, t.duration);
Assert.AreEqual(totalDurationExpected, t.durationTotal);
Assert.AreEqual(t.interpolationFactor, val, tolerance);
});
yield return t.ToYieldInstruction();
Assert.IsFalse(t.isAlive);
for (int i = 0; i < 2; i++) {
expectIsDeadError();
}
Assert.AreEqual(0, t.progress);
Assert.AreEqual(0, t.progressTotal);
var infT = Tween.Position(transform, Vector3.one, minDuration, cycles: -1);
Assert.IsTrue(infT.isAlive);
Assert.AreEqual(-1, infT.cyclesTotal);
infT.Complete();
}
[UnityTest]
public IEnumerator ZeroDurationOnTweenShouldReportValueAtLeastOnce() {
Tween.StopAll();
Assert.AreEqual(0, tweensCount);
Assert.AreEqual(capacityForTest, tweensCapacity);
const float p1 = 0.345f;
Tween.PositionZ(transform, 0, p1, 0f).Complete();
UnityEngine.Assertions.Assert.AreApproximatelyEqual(p1, transform.position.z);
const float p2 = 0.123f;
Tween.PositionZ(transform, p2, 0).Complete();
UnityEngine.Assertions.Assert.AreApproximatelyEqual(p2, transform.position.z);
const float p3 = 0.456f;
Tween.PositionZ(transform, p3, 0);
yield return null;
UnityEngine.Assertions.Assert.AreApproximatelyEqual(p3, transform.position.z);
yield return Tween.PositionZ(transform, p1, 0).OnComplete(() => { }).ToYieldInstruction();
UnityEngine.Assertions.Assert.AreApproximatelyEqual(p1, transform.position.z);
}
[UnityTest]
public IEnumerator OneShouldBeReportedExactlyOnce() {
int numOneReported = 0;
const int cycles = 1;
for (int i = 0; i < 1; i++) {
numOneReported = 0;
yield return Tween.Custom(this, 0, 1, getDt() * Random.Range(0.5f, 1.5f), startDelay: getDt() * Random.Range(0.1f, 1.1f), endDelay: getDt() * Random.Range(0.5f, 3f), cycles: cycles, onValueChange: (_, val) => {
// print($"val: {val}");
if (val == 1f) {
numOneReported++;
}
}).ToYieldInstruction();
Assert.AreEqual(cycles, numOneReported);
}
numOneReported = 0;
yield return Tween.Custom(this, 0, 1, 0f, startDelay: getDt() * Random.Range(0.1f, 1.1f), endDelay: getDt() * Random.Range(0.1f, 1.1f), cycles: cycles, onValueChange: (_, val) => {
if (val == 1) {
numOneReported++;
}
}).ToYieldInstruction();
Assert.AreEqual(cycles, numOneReported);
numOneReported = 0;
yield return Tween.Custom(this, 0, 1, 0f, cycles: cycles, onValueChange: (_, val) => {
if (val == 1) {
numOneReported++;
}
}).ToYieldInstruction();
Assert.AreEqual(cycles, numOneReported);
numOneReported = 0;
yield return Tween.Custom(this, 0, 1, 0f, (_, val) => {
if (val == 1) {
numOneReported++;
}
}).ToYieldInstruction();
Assert.AreEqual(1, numOneReported);
yield return Tween.PositionY(transform, 3.14f, Mathf.Max(minDuration, getDt() * Random.Range(0.1f, 1.1f))).ToYieldInstruction();
yield return Tween.PositionY(transform, 3.14f, 0f).ToYieldInstruction();
yield return Tween.PositionY(transform, 0, 3.14f, 0f).ToYieldInstruction();
}
[UnityTest]
public IEnumerator SingleFrameTween() {
Application.targetFrameRate = 200;
for (int i = 0; i < 1; i++) {
int numOnValueChangeCalled = 0;
yield return Tween.Custom(this, 0, 1, 0.0001f, (_, val) => {
numOnValueChangeCalled++;
Assert.IsTrue(val == 0 || val == 1);
}).ToYieldInstruction();
Assert.AreEqual(2, numOnValueChangeCalled);
}
Application.targetFrameRate = targetFrameRate;
}
[UnityTest]
public IEnumerator TweensWithDurationOfDeltaTime() {
for (int i = 0; i < 1; i++) {
var go = new GameObject();
go.AddComponent<TweensWithDurationOfDeltaTime>();
// ReSharper disable once LoopVariableIsNeverChangedInsideLoop
while (go != null) {
yield return null;
}
}
}
[UnityTest]
public IEnumerator TweenWithExactDurationOfDeltaTime1() {
yield return Tween.Delay(this, Time.deltaTime).ToYieldInstruction();
}
[UnityTest]
public IEnumerator TweenWithExactDurationOfDeltaTime2() {
int numOnCompleteCalled = 0;
yield return Tween.Delay(this, Time.deltaTime, () => numOnCompleteCalled++).ToYieldInstruction();
Assert.AreEqual(1, numOnCompleteCalled);
}
[Test]
public void TotalDurationWithCycles() {
var duration = Random.value;
var startDelay = Random.value;
var endDelay = Random.value;
var cycles = Random.Range(1, 10);
var t = Tween.LocalPositionY(transform, new TweenSettings<float>(0, 1, duration, cycles: cycles, startDelay: startDelay, endDelay: endDelay));
var durationTotalExpected = duration + startDelay + endDelay;
const float tolerance = 0.0001f;
Assert.AreEqual(durationTotalExpected, t.duration, tolerance);
Assert.AreEqual(durationTotalExpected * cycles, t.durationTotal, tolerance);
Assert.AreEqual(durationTotalExpected * cycles, t.durationTotal, tolerance);
t.Complete();
}
[Test]
public void DurationWithWaitDependencies() {
var t1Dur = Random.value;
var t1Cycles = Random.Range(1, 20);
var t2Dur = Random.value;
var t2Cycles = Random.Range(1, 20);
// const int t1Dur = 1;
// const int t1Cycles = 2;
// const int t2Dur = 2;
// const int t2Cycles = 2;
var t1 = Tween.LocalPositionX(transform, 1, t1Dur, cycles: t1Cycles);
var t2 = Tween.LocalPositionX(transform, 1, t2Dur, cycles: t2Cycles);
var s = t1.Chain(t2);
Assert.IsTrue(t1.isAlive);
Assert.IsTrue(t2.isAlive);
Assert.AreEqual(t1Dur * t1Cycles, t1.durationTotal);
Assert.AreEqual(t2Dur * t2Cycles, t2.durationTotal);
Assert.AreEqual(t1Dur * t1Cycles, t1.durationWithWaitDelay);
Assert.AreEqual(t1Dur * t1Cycles + t2Dur * t2Cycles, t2.durationWithWaitDelay, 0.001f);
s.Complete();
}
[Test]
public void AwaitingDeadCompletesImmediately() {
bool isCompleted = false;
AwaitingDeadCompletesImmediatelyAsync(() => isCompleted = true);
Assert.IsTrue(isCompleted);
}
static async void AwaitingDeadCompletesImmediatelyAsync([NotNull] Action callback) {
var frame = Time.frameCount;
await new Tween();
await new Sequence();
Assert.AreEqual(frame, Time.frameCount);
callback();
}
[UnityTest]
public IEnumerator TestAwaitByCallback() {
bool isCompleted = false;
var t = Tween.Delay(getDt() * 5f);
waitForTweenAsync(t, () => isCompleted = true);
Assert.IsFalse(isCompleted);
yield return null;
Assert.IsFalse(isCompleted);
yield return t.ToYieldInstruction();
Assert.IsTrue(isCompleted);
}
static async void waitForTweenAsync(Tween tween, [NotNull] Action callback) {
await tween;
callback();
}
[Test]
public async Task AwaitTweenWithCallback() {
bool isCompleted = false;
var t = Tween.Delay(getDt() * 2f,() => isCompleted = true);
Assert.IsTrue(t.isAlive);
Assert.IsTrue(t.tween.HasOnComplete);
await t;
Assert.IsFalse(t.isAlive);
Assert.IsTrue(isCompleted);
}
const float minDuration = TweenSettings.minDuration;
[Test]
public async Task AwaitTweenWithCallbackDoesntPostpone() {
bool isCompleted = false;
var t = Tween.Delay(minDuration,() => isCompleted = true);
Assert.IsTrue(t.isAlive);
Assert.IsTrue(t.tween.HasOnComplete);
var frameStart = Time.frameCount;
await t;
Assert.AreEqual(1, Time.frameCount - frameStart);
Assert.IsFalse(t.isAlive);
Assert.IsTrue(isCompleted);
}
[Test]
public async Task AwaitSequence() {
bool isCompleted1 = false;
bool isCompleted2 = false;
await Sequence.Create(Tween.Delay(0.01f, () => isCompleted1 = true))
.Chain(Tween.Delay(0.02f, () => isCompleted2 = true));
Assert.IsTrue(isCompleted1);
Assert.IsTrue(isCompleted2);
}
[Test]
public async Task AwaitSequence2() {
var t1 = Tween.Delay(getDt());
var t2 = Tween.Delay(getDt());
await t1.Chain(t2);
Assert.IsFalse(t1.isAlive);
Assert.IsFalse(t2.isAlive);
}
[UnityTest]
public IEnumerator ToYieldInstruction() {
var t = Tween.Delay(0.1f);
var e = t.ToYieldInstruction();
var frameStart = Time.frameCount;
while (e.MoveNext()) {
yield return e.Current;
t.Complete();
}
Assert.AreEqual(1, Time.frameCount - frameStart);
Assert.IsFalse(t.isAlive);
yield return t.ToYieldInstruction();
Tween defaultTween = default;
defaultTween.ToYieldInstruction();
Sequence defaultSequence = default;
defaultSequence.ToYieldInstruction();
t.Complete();
}
[UnityTest]
public IEnumerator ImplicitConversionToIterator() {
PrimeTweenConfig.warnStructBoxingAllocationInCoroutine = true;
{
var t2 = Tween.Delay(0.0001f);
var frameStart = Time.frameCount;
expectCoroutineBoxingWarning();
yield return t2;
Assert.AreEqual(1, Time.frameCount - frameStart);
Assert.IsFalse(t2.isAlive);
}
{
var s = Sequence.Create(Tween.Delay(0.0001f));
var frameStart = Time.frameCount;
// iterator boxing warning is shown only once
yield return s;
Assert.AreEqual(1, Time.frameCount - frameStart);
Assert.IsFalse(s.isAlive);
}
LogAssert.NoUnexpectedReceived();
}
[Test]
public async Task AwaitInfiniteTweenComplete() {
Tween t = default;
int numCompleted = 0;
t = Tween.Custom(this, 0, 1, 1, cycles: -1, onValueChange: delegate { t.Complete(); })
.OnComplete(() => numCompleted++);
await t;
Assert.AreEqual(1, numCompleted);
}
[Test]
public async Task AwaitInfiniteTweenStop() {
Tween t = default;
int numOnValueChanged = 0;
t = Tween.Custom(this, 0, 1, 1f, cycles: -1, onValueChange: delegate {
// Debug.Log(numOnValueChanged);
numOnValueChanged++;
Assert.AreEqual(1, numOnValueChanged);
Assert.IsTrue(t.isAlive);
t.Stop();
});
Assert.IsTrue(t.isAlive);
await t;
Assert.IsFalse(t.isAlive);
Assert.AreEqual(1, numOnValueChanged);
}
[Test]
public async Task TweenStoppedTweenWhileAwaiting() {
var t = Tween.Delay(0.05f);
#pragma warning disable CS4014
Tween.Delay(0.01f).OnComplete(() => t.Stop());
#pragma warning restore CS4014
Assert.IsTrue(t.isAlive);
await t;
Assert.IsFalse(t.isAlive);
}
[Test]
public void InvalidDurations() {
Assert.Throws<AssertionException>(() => Tween.Delay(float.NaN), Constants.durationInvalidError);
Assert.Throws<AssertionException>(() => Tween.Delay(float.PositiveInfinity), Constants.durationInvalidError);
Assert.Throws<AssertionException>(() => Tween.Delay(float.NegativeInfinity), Constants.durationInvalidError);
Assert.Throws<AssertionException>(() => Tween.PositionZ(transform, new TweenSettings<float>(0, 1, new TweenSettings(1, startDelay: float.NaN))), Constants.durationInvalidError);
Assert.Throws<AssertionException>(() => Tween.PositionZ(transform, new TweenSettings<float>(0, 1, new TweenSettings(1, startDelay: float.PositiveInfinity))), Constants.durationInvalidError);
Assert.Throws<AssertionException>(() => Tween.PositionZ(transform, new TweenSettings<float>(0, 1, new TweenSettings(1, startDelay: float.NegativeInfinity))), Constants.durationInvalidError);
Assert.Throws<AssertionException>(() => Tween.PositionZ(transform, new TweenSettings<float>(0, 1, new TweenSettings(1, endDelay: float.NaN))), Constants.durationInvalidError);
Assert.Throws<AssertionException>(() => Tween.PositionZ(transform, new TweenSettings<float>(0, 1, new TweenSettings(1, endDelay: float.PositiveInfinity))), Constants.durationInvalidError);
Assert.Throws<AssertionException>(() => Tween.PositionZ(transform, new TweenSettings<float>(0, 1, new TweenSettings(1, endDelay: float.NegativeInfinity))), Constants.durationInvalidError);
}
[Test]
public void MaterialTweens() {
{
var s = Shader.Find("Standard");
if (s == null) {
Assert.Ignore();
return;
}
var m = new Material(s);
{
const string propName = "_EmissionColor";
#if UNITY_2021_1_OR_NEWER
Assert.IsTrue(m.HasColor(propName));
#endif
var to = Color.red;
Tween.MaterialColor(m, Shader.PropertyToID(propName), to, 1f).Complete();
Assert.AreEqual(to, m.GetColor(propName));
}
{
const string propName = "_EmissionColor";
#if UNITY_2021_1_OR_NEWER
Assert.IsTrue(m.HasColor(propName));
#endif
var iniColor = new Color(Random.value, Random.value, Random.value, Random.value);
m.SetColor(propName, iniColor);
var toAlpha = Random.value;
Tween.MaterialAlpha(m, Shader.PropertyToID(propName), toAlpha, 1f).Complete();
var col = m.GetColor(propName);
UnityEngine.Assertions.Assert.AreApproximatelyEqual(col.r, iniColor.r);
UnityEngine.Assertions.Assert.AreApproximatelyEqual(col.g, iniColor.g);
UnityEngine.Assertions.Assert.AreApproximatelyEqual(col.b, iniColor.b);
UnityEngine.Assertions.Assert.AreApproximatelyEqual(col.a, toAlpha);
}
{
const string propName = "_Cutoff";
#if UNITY_2021_1_OR_NEWER
Assert.IsTrue(m.HasFloat(propName));
#endif
var to = Random.value;
Tween.MaterialProperty(m, Shader.PropertyToID(propName), to, 1f).Complete();
UnityEngine.Assertions.Assert.AreApproximatelyEqual(to, m.GetFloat(propName));
}
{
const string propName = "_MainTex";
#if UNITY_2021_1_OR_NEWER
Assert.IsTrue(m.HasTexture(propName));
#endif
var to = Random.value * Vector2.one;
Tween.MaterialTextureOffset(m, Shader.PropertyToID(propName), to, 1f).Complete();
Assert.AreEqual(to, m.GetTextureOffset(propName));
}
{
const string propName = "_MainTex";
#if UNITY_2021_1_OR_NEWER
Assert.IsTrue(m.HasTexture(propName));
#endif
var to = Random.value * Vector2.one;
Tween.MaterialTextureScale(m, Shader.PropertyToID(propName), to, 1f).Complete();
Assert.IsTrue(to == m.GetTextureScale(propName));
}
}
{
var m = Resources.Load<Material>("Custom_TestShader");
Assert.IsNotNull(m);
const string propName = "_TestVectorProp";
var to = Random.value * Vector4.one;
Tween.MaterialProperty(m, Shader.PropertyToID(propName), to, 1f).Complete();
Assert.IsTrue(to == m.GetVector(propName));
}
}
/// passing the serialized UnityEngine.Object reference that is not populated behaves like passing destroyed object
[Test]
public void PassingDestroyedUnityTarget() {
LogAssert.NoUnexpectedReceived();
var target = new GameObject().transform;
Object.DestroyImmediate(target.gameObject);
var s = Sequence.Create();
expectError();
s.ChainCallback(target, delegate { });
expectError();
Assert.IsFalse(Tween.Delay(target, 0.1f, delegate { }).IsCreated);
expectError();
Assert.IsFalse(Tween.Delay(target, 0.1f).IsCreated);
expectError();
Assert.IsFalse(Tween.Delay(target, 0.1f, () => {}).IsCreated);
expectError();
Assert.IsFalse(Tween.Position(target, new TweenSettings<Vector3>(default, default, 0.1f)).IsCreated);
expectError();
var deadTween = Tween.Custom(target, 0f, 0, 0.1f, delegate { });
Assert.IsFalse(deadTween.isAlive);
expectAddDeadToSequenceError();
Sequence.Create(deadTween);
LogAssert.Expect(LogType.Error, "Shake's strength is (0, 0, 0).");
LogAssert.Expect(LogType.Error, new Regex("Shake's frequency should be > 0f"));
expectError();
Tween.ShakeLocalPosition(target, default);
void expectError() {
expectTargetIsNull();
}
}
[Test]
public void ShakeSettings() {
{
var s = new ShakeSettings(Vector3.one, 1f, 1);
Assert.IsTrue(s.enableFalloff);
}
{
var s = new ShakeSettings(Vector3.one, 1f, 1, true, Ease.InBack);
Assert.IsTrue(s.enableFalloff);
}
{
var s = new ShakeSettings(Vector3.one, 1f, 1, AnimationCurve.Linear(0,0,1,1));
Assert.IsTrue(s.enableFalloff);
}
}
[UnityTest]
public IEnumerator ForceCompleteWhenWaitingForEndDelay() {
var t = Tween.ShakeLocalPosition(transform, new ShakeSettings(Vector3.one, getDt() * 2f, endDelay: 100f));
while (t.interpolationFactor < 1f) {
yield return null;
}
Assert.IsTrue(t.isAlive);
t.Complete();
Assert.IsFalse(t.isAlive);
}
static void print(object o) => Debug.Log($"[{Time.frameCount}] {o}");
[UnityTest]
public IEnumerator StopAtEvenOrOddCycle() {
for (int i = 0; i < 5; i++) {
var t = Tween.Rotation(transform, Vector3.one, getDt() * 5f, cycles: 10, cycleMode: CycleMode.Yoyo);
while (t.cyclesDone < Random.Range(2, 4)) {
yield return null;
}
t.SetRemainingCycles(true);
Assert.AreEqual(t.cyclesDone % 2 + 1, t.cyclesTotal - t.cyclesDone);
t.SetRemainingCycles(false);
Assert.AreEqual(t.cyclesDone % 2, (t.cyclesTotal - t.cyclesDone) % 2);
}
}
[UnityTest]
public IEnumerator SetCycles() {
var t = Tween.Rotation(transform, Vector3.one, Mathf.Max(minDuration, getDt()) * 10, cycles: 10);
while (t.cyclesDone != 2) {
yield return null;
}
t.SetRemainingCycles(3);
Assert.AreEqual(2, t.cyclesDone);
Assert.AreEqual(5, t.cyclesTotal);
t.Complete();
}
[Test]
public void DOTweenAdapterEnabled() {
#if !PRIME_TWEEN_DOTWEEN_ADAPTER
Assert.Inconclusive();
#endif
}
[Test]
public void ExperimentalDefineSet() {
#if PRIME_TWEEN_EXPERIMENTAL
Assert.Ignore("Please remove the PRIME_TWEEN_EXPERIMENTAL define and run all tests again.");
#endif
}
[UnityTest]
public IEnumerator RecursiveKillAllCall() {
// Calling Tween.StopAll/Complete() from onValueChange previously threw the 'Please don't call Tween.StopAll/CompleteAll() from the OnComplete() callback' exception before.
// But this no longer the case - current impl checks if Update/FixedUpdate() is safe to call
yield return Tween.Custom(0, 1, 1f, val => {
if (val != 0) {
Tween.StopAll();
}
}).ToYieldInstruction();
yield return Tween.Custom(0, 1, 0.01f, _ => {
Tween.CompleteAll();
}).ToYieldInstruction();
LogAssert.NoUnexpectedReceived();
}
[UnityTest]
public IEnumerator KillAllIsImmediate() {
Tween.Delay(0.01f);
Tween.StopAll(null);
Assert.AreEqual(0, tweensCount);
Tween.Delay(0.01f);
Assert.AreEqual(1, tweensCount);
Assert.AreEqual(Tween.CompleteAll(null), 1);
Assert.AreEqual(0, tweensCount);
yield return null;
LogAssert.NoUnexpectedReceived();
}
[Test]
public void SetCapacityImmediatelyAfterStopAll() {
Tween.StopAll();
Assert.AreEqual(0, tweensCount);
PrimeTweenConfig.SetTweensCapacity(2);
Tween.Delay(0.01f);
Tween.Delay(0.01f);
Assert.AreEqual(2, tweensCount);
Tween.StopAll();
Assert.AreEqual(0, tweensCount);
PrimeTweenConfig.SetTweensCapacity(1);
PrimeTweenConfig.SetTweensCapacity(capacityForTest);
LogAssert.NoUnexpectedReceived();
}
[UnityTest]
public IEnumerator RotationShakeEndVal() {
var target = new GameObject(nameof(RotationShakeEndVal)).transform;
var iniRot = Random.rotation.normalized;
var strength = Random.insideUnitSphere;
var freq = Random.value * 10;
target.rotation = iniRot;
var handle = Tween.ShakeLocalRotation(target, strength, 1f, freq);
// skip frame so cacheDiff() is called
yield return null;
Assert.IsTrue(handle.isAlive);
var t = handle.tween;
Assert.IsTrue(iniRot == t.startValue.QuaternionVal);
Assert.IsTrue(Quaternion.identity == t.endValue.QuaternionVal);
Assert.AreEqual(strength, t.shakeData.strengthPerAxis);
Assert.AreEqual(freq, t.shakeData.frequency);
Object.Destroy(target.gameObject);
handle.Stop();
}
[UnityTest]
public IEnumerator AtSpeed() {
var target = new GameObject(nameof(AtSpeed)).transform;
var speed = (Random.value + 0.1f) * 10f;
const double tolerance = 0.001;
var endValue = new Vector3(1, 0,0);
{
Assert.AreEqual(Vector3.zero, target.position);
var t = Tween.PositionAtSpeed(target, endValue, speed);
Assert.AreEqual(speed, 1 / t.duration, tolerance);
yield return null;
Assert.AreEqual(speed, 1 / t.duration, tolerance);
t.Stop();
}
{
target.position = Vector3.zero;
Tween.PositionAtSpeed(target, endValue, speed).Complete();
Assert.AreEqual(endValue, target.position);
}
{
target.position = Vector3.zero;
float startDelay = getDt();
var t = Tween.PositionAtSpeed(target, endValue, speed, startDelay: startDelay);
var expectedDuration = 1 / speed + startDelay;
while (t.interpolationFactor == 0) {
Assert.AreEqual(expectedDuration, t.duration, tolerance);
yield return null;
}
Assert.AreEqual(expectedDuration, t.duration, tolerance);
yield return null;
Assert.AreEqual(expectedDuration, t.duration, tolerance);
t.Stop();
}
}
[UnityTest]
public IEnumerator DelayInterpolationFactor() {
for (int i = 0; i < 1; i++) {
float duration = Random.Range(0.001f, 0.1f);
var d = Tween.Delay(duration);
float timeStart = Time.time;
while (d.isAlive) {
Assert.AreEqual(Mathf.Min(1f, (Time.time - timeStart) / duration), d.interpolationFactor, 0.001f);
yield return null;
}
}
}
[Test]
public void TweensCount() {
Tween.StopAll();
int count = Random.Range(1, 10);
for (int i = 0; i < count; i++) {
Tween.PositionX(transform, 10, 0.01f);
}
Assert.AreEqual(count, Tween.GetTweensCount());
Assert.AreEqual(count, Tween.GetTweensCount(transform));
Tween.StopAll();
Assert.AreEqual(0, Tween.GetTweensCount());
}
[UnityTest]
public IEnumerator StopCalledOnLastTweenFrame() {
float dt = getDt();
Tween tween = default;
tween = Tween.Custom(0, 1, dt * 3, val => {
if (val == 1f) {
tween.Stop();
Assert.IsFalse(tween.isAlive);
}
}).OnComplete(() => Assert.Fail());
yield return tween.ToYieldInstruction();
}
[UnityTest]
public IEnumerator StopCalledOnLastTweenFrameFromOnUpdate() {
Tween tween = default;
float duration = getDt() * 3f;
tween = Tween.Custom(0, 1, duration, delegate { })
.OnUpdate(this, delegate {
if (tween.interpolationFactor == 1f) {
tween.Stop();
Assert.IsFalse(tween.isAlive);
}
})
.OnComplete(() => Assert.Fail());
yield return tween.ToYieldInstruction();
}
[UnityTest]
public IEnumerator OnUpdateDestroyedTarget() {
var onUpdateTarget = new GameObject(nameof(OnUpdateDestroyedTarget));
int numUpdated = 0;
expectOnUpdateRemoved();
yield return Tween.Delay(getDt() * 5)
.OnUpdate(onUpdateTarget, (target, _) => {
Assert.AreEqual(0, numUpdated);
numUpdated++;
Object.Destroy(target);
})
.ToYieldInstruction();
Assert.AreEqual(1, numUpdated);
LogAssert.NoUnexpectedReceived();
}
[UnityTest]
public IEnumerator OnUpdateException() {
var onUpdateTarget = new GameObject(nameof(OnUpdateDestroyedTarget));
expectOnUpdateRemoved();
int numCompleted = 0;
yield return Tween.PositionZ(transform, Random.value, 0.001f)
.OnUpdate(onUpdateTarget, delegate { throw new Exception(); })
.OnComplete(() => numCompleted++)
.ToYieldInstruction();
Assert.AreEqual(1, numCompleted);
LogAssert.NoUnexpectedReceived();
}
[Test]
public void OnUpdateInvalidUsage() {
var t = Tween.Delay(0.001f);
t.OnUpdate<object>(null, delegate { }); // ok
expectException<AssertionException>(() => {
t.OnUpdate<object>(null, delegate { }); // duplicate is not allowed
}, "Only one OnUpdate() is allowed for one tween.");
Assert.Throws<AssertionException>(() => {
t.OnUpdate(this, null); // null onUpdate is not allowed
});
}
[UnityTest]
public IEnumerator OnUpdate() {
{
// with delay
int numCalled = 0;
yield return Tween.Delay(minDuration, () => numCalled++).ToYieldInstruction();
Assert.AreEqual(1, numCalled);
}
{
var t = Tween.Position(transform, Vector3.one, getDt(), endDelay: getDt() * 5);
int numInterpolationCompleted = 0;
yield return t.OnUpdate<object>(null, delegate {
if (t.interpolationFactor == 1f) {
numInterpolationCompleted++;
}
}).ToYieldInstruction();
Assert.AreEqual(1, numInterpolationCompleted);
}
}
static void expectOnUpdateRemoved() => LogAssert.Expect(LogType.Error, new Regex("will not be called again because"));
[UnityTest]
public IEnumerator TimescaleTweenOutliveTheTarget() {
var shortTween = Tween.Delay(0.001f);
var timeScaleTween = Tween.TweenTimeScale(shortTween, 0.5f, 1)
.OnComplete(Assert.Fail);
expectOnCompleteIgnored();
yield return shortTween.ToYieldInstruction();
Assert.IsFalse(timeScaleTween.isAlive);
LogAssert.NoUnexpectedReceived();
}
[UnityTest]
public IEnumerator ConversionToEasing() {
var curve = AnimationCurve.Linear(0, 0, 1, 1);
new TweenSettings(1, curve);
new TweenSettings<float>(0, 1, curve);
new TweenSettings<float>(0, 1, 1, curve);
Tween.Position(transform, Vector3.one, 1, curve);
Tween.Position(transform, Vector3.one, 1, (Easing)Ease.InBack);
Tween.Position(transform, Vector3.zero, Vector3.one, 1, curve);
#if PRIME_TWEEN_EXPERIMENTAL
Tween.PositionAdditive(transform, Vector3.one, 1, curve);
#endif
Tween.PositionAtSpeed(transform, Vector3.one, 10, curve);
Tween.PositionAtSpeed(transform, Vector3.zero, Vector3.one, 10, curve);
yield return null;
Tween.StopAll();
}
[UnityTest]
public IEnumerator Elastic() {
for (int i = 0; i < 5; i++) {
Assert.AreEqual(0, Easing.Evaluate(0, parametricSettings(ParametricEase.Elastic, 1, 0.3f)));
Assert.AreEqual(1, Easing.Evaluate(1, parametricSettings(ParametricEase.Elastic, 1, 0.3f)));
var strength = 1 + Random.value;
var period = 0.1f + Random.value;
var t = Tween.Position(transform, Vector3.one, 1, Easing.Elastic(strength, period));
yield return null;
Assert.IsTrue(t.isAlive);
Assert.AreEqual(strength, t.tween.settings.parametricEaseStrength);
Assert.AreEqual(period, t.tween.settings.parametricEasePeriod);
Assert.AreEqual(Ease.Custom, t.tween.settings.ease);
Assert.AreEqual(ParametricEase.Elastic, t.tween.settings.parametricEase);
t.Stop();
}
}
[NotNull]
static ReusableTween parametricSettings(ParametricEase ease, float strength, float period) {
return new ReusableTween {
settings = new TweenSettings {
ease = Ease.Custom,
duration = 1,
parametricEase = ease,
parametricEaseStrength = strength,
parametricEasePeriod = period
}
};
}
[UnityTest]
public IEnumerator Overshoot() {
Assert.AreEqual(0, Easing.Evaluate(0, parametricSettings(ParametricEase.Overshoot, 1, float.NaN)));
Assert.AreEqual(1, Easing.Evaluate(1, parametricSettings(ParametricEase.Overshoot, 1, float.NaN)));
var strength = Random.value;
var t = Tween.Position(transform, Vector3.one, 1, Easing.Overshoot(strength));
yield return null;
Assert.IsTrue(t.isAlive);
Assert.AreEqual(strength * StandardEasing.backEaseConst, t.tween.settings.parametricEaseStrength);
Assert.AreEqual(ParametricEase.Overshoot, t.tween.settings.parametricEase);
Assert.AreEqual(Ease.Custom, t.tween.settings.ease);
t.Stop();
}
[UnityTest]
[SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")]
public IEnumerator NullTarget() {
const float duration = 0.05f;
Transform t = null;
expectTargetIsNull();
Tween.Position(t, Vector3.one, duration).ToYieldInstruction();
expectTargetIsNull();
Tween.Delay(null, duration);
expectTargetIsNull();
Tween.Delay(t, duration, delegate { });
expectTargetIsNull();
Sequence.Create().ChainCallback(t, delegate { });
Tween.Custom(0, 1, duration, delegate { });
Tween.Delay(duration);
Time.timeScale = 0.99f;
Tween.GlobalTimeScale(1, 0.05f);
Sequence.Create().ChainCallback(delegate { });
#if PRIME_TWEEN_DOTWEEN_ADAPTER
DOTween.Sequence().SetLoops(2).AppendCallback(delegate {});
DOTween.Sequence().PrependInterval(0.01f);
#endif
yield return null;
yield return null;
Tween.StopAll();
LogAssert.NoUnexpectedReceived();
}
[UnityTest]
public IEnumerator MoreThanOneCyclePerFrame() {
yield return null;
{
var zeroDurTween = Tween.ScaleY(transform, 2f, 0, cycles: int.MaxValue - 1);
yield return null;
Assert.IsFalse(zeroDurTween.isAlive, "0f duration completes all cycles immediately");
}
{
var infiniteZeroDurTween = Tween.ScaleY(transform, 2f, 0, cycles: -1);
yield return null;
Assert.AreEqual(1, infiniteZeroDurTween.cyclesDone);
Assert.IsTrue(infiniteZeroDurTween.isAlive);
}
{
float duration = 0.001f + getDt() / 10f;
Assert.IsTrue(duration >= 0.001f);
var t = Tween.ScaleY(transform, 2f, duration, cycles: int.MaxValue - 1);
yield return null;
Assert.AreEqual(Mathf.FloorToInt(Time.deltaTime / duration), t.cyclesDone);
t.Complete();
}
}
[UnityTest]
public IEnumerator ExecutionOrder() {
yield return null;
int i = 0;
void validate(int order) {
// Debug.Log($"-------------- validate {order}");
Assert.AreEqual(i, order);
i++;
}
{
for (int k = 0; k < 1; k++) {
yield return Sequence.Create(2)
.Chain(Tween.Custom(0, 1, getDur(), delegate { }, startDelay: getDur(), endDelay: getDur()).OnComplete(() => validate(0)))
.ChainCallback(() => validate(1))
.Chain(Tween.Delay(getDur(), () => validate(2)))
.Chain(Tween.Custom(0, 1, getDur(), delegate { }, startDelay: getDur(), endDelay: getDur()).OnComplete(() => validate(3)))
.ChainCallback(() => validate(4))
.ChainCallback(() => validate(5))
.ChainCallback(() => {
validate(6);
i = 0;
})
.ToYieldInstruction();
}
}
{
for (int k = 0; k < 1; k++) {
i = 0;
var seq = Sequence.Create();
const int iterations = 5;
for (int j = 0; j < iterations; j++) {
var expected = j;
if (Random.value > 0.5f) {
seq.Chain(Tween.Delay(getDur(), () => validate(expected)));
} else {
seq.ChainCallback(() => validate(expected));
}
}
seq.ChainCallback(() => {
validate(iterations);
i = 0;
});
seq.SetRemainingCycles(2);
yield return seq.ToYieldInstruction();
}
}
float getDur() => Mathf.Max(minDuration, getDt() * Mathf.Lerp(0.1f, 2f, Random.value));
}
static float getDt() => Application.targetFrameRate != -1 ? 1f / Application.targetFrameRate : Time.deltaTime;
[Test]
public void ShakeIsDeadOnNewReusableTween() {
var t = new ReusableTween();
Assert.IsFalse(t.shakeData.isAlive);
}
[UnityTest]
public IEnumerator SmallDurationWithInfiniteCycles() {
int numChanged = 0;
int numUpdated = 0;
const float duration = 0.001f;
var t = Tween.Custom(0f, 1f, duration, cycles: -1, onValueChange: delegate {
numChanged++;
// print("onValueChange");
})
.OnUpdate(this, delegate {
numUpdated++;
Assert.AreEqual(numChanged, numUpdated);
// print("OnUpdate()");
});
float timeStart = Time.time;
yield return null;
yield return null;
yield return null;
Assert.AreEqual(4, numChanged);
Assert.AreEqual(4, numUpdated);
var cyclesDoneExpected = Mathf.FloorToInt((Time.time - timeStart) / duration);
Assert.AreEqual(cyclesDoneExpected, t.cyclesDone);
t.Complete();
}
[UnityTest]
public IEnumerator InvalidOperationExceptionInsideCompleteAllBug() {
for (int i = 0; i < 1; i++) {
const float upper = 1.5f;
Tween.Delay(getDt() * Random.Range(0.5f, upper), () => Tween.Delay(getDt() * Random.Range(0.5f, 1.5f)));
Tween.Delay(getDt() * Random.Range(0.5f, upper), () => Tween.Delay(getDt() * Random.Range(0.5f, 1.5f)));
Tween.Delay(getDt() * Random.Range(0.5f, upper), () => Tween.Delay(getDt() * Random.Range(0.5f, 1.5f)));
Tween.Delay(getDt() * Random.Range(0.5f, upper), () => Tween.Delay(getDt() * Random.Range(0.5f, 1.5f)));
Tween.Delay(getDt() * Random.Range(0.5f, upper), () => Tween.Delay(getDt() * Random.Range(0.5f, 1.5f)));
int delayFramesBeforeCompleteAll = Random.Range(0, 0);
for (int j = 0; j < delayFramesBeforeCompleteAll; j++) {
yield return null;
}
if (Random.value >= 0.0f) {
Tween.CompleteAll();
}
}
yield return null;
}
[UnityTest]
public IEnumerator TweenElapsedTimeTotal() {
var duration = getDt() * 2f;
var t = Tween.Custom(0f, 1f, duration, delegate { });
var s = Sequence.Create(2)
.ChainDelay(duration)
.Chain(t)
.ChainDelay(duration);
while (s.isAlive) {
Assert.IsTrue(t.elapsedTimeTotal >= 0f);
Assert.IsTrue(t.elapsedTimeTotal <= t.durationTotal);
yield return null;
}
}
[Test]
public void SetCyclesWithDelay() {
LogAssert.Expect(LogType.Error, new Regex("Applying cycles to Delay will not repeat"));
var delay = Tween.Delay(this, duration: .5f, delegate {});
delay.SetRemainingCycles(10);
delay.Stop();
}
[Test]
public void ElapsedTimeTotalIsClamped() {
for (int i = 0; i < 1; i++) {
float duration = Random.value + 0.001f;
int cycles = Random.Range(3, 20);
var t = Tween.Delay(duration);
t.SetRemainingCycles(cycles);
t.isPaused = true;
t.elapsedTime = float.MaxValue;
Assert.AreEqual(1, t.cyclesDone);
Assert.AreEqual(duration, t.tween.elapsedTimeTotal);
Assert.AreEqual(0f, t.elapsedTime); // new cycles has started, so should be 0f
Assert.AreEqual(duration, t.elapsedTimeTotal);
t.elapsedTimeTotal = 0f;
Assert.AreEqual(0, t.cyclesDone);
Assert.AreEqual(0f, t.tween.elapsedTimeTotal);
Assert.AreEqual(0f, t.elapsedTime);
Assert.AreEqual(0f, t.elapsedTimeTotal);
t.elapsedTimeTotal = float.MaxValue;
Assert.AreEqual(cycles, t.cyclesDone);
Assert.AreEqual(t.durationTotal, t.tween.elapsedTimeTotal);
Assert.AreEqual(t.duration, t.elapsedTime);
Assert.AreEqual(t.durationTotal, t.elapsedTimeTotal);
Assert.IsTrue(t.isAlive);
t.Stop();
}
}
[UnityTest]
public IEnumerator WarnEndValueEqualsCurrent() {
Assert.AreEqual(0, tweensCount);
var iniPos = Vector3.one * Random.value;
{
transform.position = iniPos;
var t = Tween.Position(transform, iniPos, 1f);
yield return null;
LogAssert.Expect(LogType.Warning, new Regex("Tween's 'endValue' equals to the current animated value"));
t.Stop();
}
{
PrimeTweenConfig.warnEndValueEqualsCurrent = false;
transform.position = iniPos;
var t = Tween.Position(transform, iniPos, 1f);
yield return null;
t.Stop();
PrimeTweenConfig.warnEndValueEqualsCurrent = true;
}
LogAssert.NoUnexpectedReceived();
}
[Test]
public void SetInfiniteTweenElapsedTime() {
var t = Tween.Custom(0f, 1f, 0.01f, delegate { }, cycles: -1);
for (int i = 0; i < 8; i++) {
LogAssert.Expect(LogType.Error, new Regex("Invalid elapsedTime"));
}
t.elapsedTime = float.MaxValue; // ok
t.elapsedTime = float.PositiveInfinity; // ok
t.elapsedTime = -1f;
t.elapsedTime = float.NegativeInfinity;
t.elapsedTime = float.NaN;
t.elapsedTimeTotal = 0f; // ok
t.elapsedTimeTotal = 10f; // ok
t.elapsedTimeTotal = -1f;
t.elapsedTimeTotal = float.MaxValue;
t.elapsedTimeTotal = float.PositiveInfinity;
t.elapsedTimeTotal = float.NegativeInfinity;
t.elapsedTimeTotal = float.NaN;
t.Stop();
}
[Test]
public void SetInfiniteTweenProgress() {
var t = Tween.Custom(0f, 1f, 0.01f, delegate { }, cycles: -1);
Assert.IsTrue(float.IsPositiveInfinity(t.durationTotal));
// ok
t.progress = 0f;
t.progress = 0.5f;
t.progress = 1f;
for (int i = 0; i < 3; i++) {
LogAssert.Expect(LogType.Error, new Regex("It's not allowed to set progressTotal on infinite tween"));
}
t.progressTotal = 0f;
t.progressTotal = 0.5f;
t.progressTotal = 1f;
Assert.IsTrue(float.IsPositiveInfinity(t.durationTotal));
t.Stop();
}
[UnityTest]
public IEnumerator ZZ_SceneLoadSetsUnityObjectBug1() {
var t = Tween.Delay(1f);
LoadTestScene();
yield return null;
Assert.IsTrue(t.isAlive);
t.Stop();
}
[UnityTest]
public IEnumerator ZZ_SceneLoadSetsUnityObjectBug2() {
var seq = Sequence.Create().ChainDelay(1f);
LoadTestScene();
yield return null;
Assert.IsTrue(seq.isAlive);
seq.Stop();
}
static void LoadTestScene() {
const string testScenePath = "Packages/com.kyrylokuzyk.primetween/Tests/SceneLoadSetsUnityObjectBug.unity";
#if UNITY_EDITOR
if (Application.isEditor) {
UnityEditor.SceneManagement.EditorSceneManager.LoadSceneInPlayMode(testScenePath, new LoadSceneParameters(LoadSceneMode.Single));
return;
}
#endif
SceneManager.LoadScene(testScenePath, LoadSceneMode.Single);
}
[UnityTest]
public IEnumerator SetElapsedTimeRecursively() {
Tween t = default;
int i = 0;
t = Tween.Custom(0f, 1f, getDt() / 5f, delegate {
// print("custom");
onUpdate();
})
.OnUpdate(this, delegate {
// print("OnUpdate");
onUpdate();
});
yield return t.ToYieldInstruction();
void onUpdate() {
i++;
Assert.IsTrue(i < 100);
expectRecursiveCallError();
t.progress += 0.01f;
expectRecursiveCallError();
t.progressTotal += 0.01f;
expectRecursiveCallError();
t.elapsedTime += 0.01f;
expectRecursiveCallError();
t.elapsedTimeTotal += 0.01f;
}
}
[UnityTest]
public IEnumerator CompleteInfiniteTween() {
int numCallbacks = 0;
var duration = Mathf.Max(minDuration, Random.Range(0f, getDt()));
Assert.IsTrue(duration >= minDuration);
var t = Tween.Position(transform, Vector3.one, duration, cycles: -1)
.OnComplete(() => numCallbacks++);
float timeStart = Time.time;
yield return null;
yield return null;
var cyclesDoneExpected = Mathf.FloorToInt((Time.time - timeStart) / duration);
Assert.AreEqual(cyclesDoneExpected, t.cyclesDone);
t.Complete();
Assert.AreEqual(1, numCallbacks);
}
[Test]
public void CompleteInfiniteTween2() {
var target = new GameObject().transform;
var iniValue = Vector3.one * 0.5f;
target.localScale = iniValue;
var endValue = Vector3.one * 2f;
Tween.Scale(target, endValue, 0.5f, cycles: -1, cycleMode: CycleMode.Yoyo).Complete();
Assert.AreEqual(endValue, target.localScale);
{
var t = Tween.Scale(target, iniValue, 0.5f, cycles: -1, cycleMode: CycleMode.Yoyo);
t.SetRemainingCycles(true);
t.Complete();
Assert.AreEqual(iniValue, target.localScale);
}
{
var t = Tween.Scale(target, endValue, 0.5f, cycles: -1, cycleMode: CycleMode.Yoyo);
t.SetRemainingCycles(false);
t.Complete();
Assert.AreEqual(iniValue, target.localScale);
}
Object.DestroyImmediate(target.gameObject);
LogAssert.NoUnexpectedReceived();
}
[UnityTest]
public IEnumerator WarnEndValueEqualsCurrent2() {
Tween.StopAll();
yield return null;
{
transform.position = Vector3.one;
expectWarning();
var t = Tween.Position(transform, Vector3.one, 0.01f);
yield return null;
t.Stop();
}
{
transform.position = Vector3.one;
PrimeTweenConfig.warnEndValueEqualsCurrent = false;
var t = Tween.Position(transform, Vector3.one, 0.01f);
PrimeTweenConfig.warnEndValueEqualsCurrent = true;
yield return null;
t.Stop();
}
LogAssert.NoUnexpectedReceived();
static void expectWarning() => LogAssert.Expect(LogType.Warning, new Regex("Tween's 'endValue' equals to the current animated value"));
}
[UnityTest]
public IEnumerator SetPropertiesOfInfiniteTween() {
var t = Tween.Custom(0, 1, 1, _ => {
// print(_);
}, cycles: -1, cycleMode: CycleMode.Yoyo, ease: Ease.Linear);
t.elapsedTime = 0.5f;
yield return null;
t.progress = 0.75f;
yield return null;
t.elapsedTimeTotal = 2.1f;
yield return null;
t.elapsedTime = 0.5f;
yield return null;
t.Stop();
}
[Test]
public void NegativeIniCyclesBugReport() {
// https://github.com/KyryloKuzyk/PrimeTween/issues/63
Tween.StopAll();
var startValue = Vector3.one * 10;
var endValue = Vector3.one * 20;
transform.position = startValue;
var posTween = Tween.Position(transform, startValue, endValue, new TweenSettings(1f, cycles: 2, cycleMode: CycleMode.Rewind));
var seq = Sequence.Create()
.ChainDelay(1f)
.Chain(posTween);
seq.elapsedTime = 1.1f;
Assert.AreNotEqual(0f, posTween.interpolationFactor);
Assert.AreNotEqual(startValue, transform.position);
// Assert.AreEqual(-1, posTween.tween.cyclesDone);
seq.elapsedTime = 0.5f;
Assert.AreEqual(0f, posTween.interpolationFactor);
Assert.AreEqual(startValue, transform.position);
seq.Stop();
}
[Test]
public void UpdateTypes() {
var iniUpdateType = PrimeTweenConfig.defaultUpdateType;
{
Tween.StopAll();
var t = Tween.Position(transform, default, new TweenSettings(1f, updateType: default)).tween;
Assert.AreEqual(_UpdateType.Update, t.settings._updateType);
Assert.AreEqual(t, PrimeTweenManager.Instance.tweens.Single());
}
{
Tween.StopAll();
var t = Tween.Position(transform, default, new TweenSettings(1f, updateType: UpdateType.Update)).tween;
Assert.AreEqual(_UpdateType.Update, t.settings._updateType);
Assert.AreEqual(t, PrimeTweenManager.Instance.tweens.Single());
}
{
Tween.StopAll();
var t = Tween.Position(transform, default, new TweenSettings(1f, updateType: UpdateType.LateUpdate)).tween;
Assert.AreEqual(_UpdateType.LateUpdate, t.settings._updateType);
Assert.AreEqual(t, PrimeTweenManager.Instance.lateUpdateTweens.Single());
}
{
Tween.StopAll();
var t = Tween.Position(transform, default, new TweenSettings(1f, updateType: UpdateType.FixedUpdate)).tween;
Assert.AreEqual(_UpdateType.FixedUpdate, t.settings._updateType);
Assert.AreEqual(t, PrimeTweenManager.Instance.fixedUpdateTweens.Single());
}
{
Tween.StopAll();
UpdateType updateType = default;
updateType.enumValue = (_UpdateType)100;
Tween.Position(transform, default, new TweenSettings(1f, updateType: updateType));
LogAssert.Expect(LogType.Error, "Invalid update type: 100");
}
{
Tween.StopAll();
var t = Tween.ShakeLocalPosition(transform, new ShakeSettings(Vector3.one, updateType: default)).tween;
Assert.AreEqual(_UpdateType.Update, t.settings._updateType);
Assert.AreEqual(t, PrimeTweenManager.Instance.tweens.Single());
}
{
Tween.StopAll();
var t = Tween.ShakeLocalPosition(transform, new ShakeSettings(Vector3.one, updateType: UpdateType.Update)).tween;
Assert.AreEqual(_UpdateType.Update, t.settings._updateType);
Assert.AreEqual(t, PrimeTweenManager.Instance.tweens.Single());
}
{
Tween.StopAll();
var t = Tween.ShakeLocalPosition(transform, new ShakeSettings(Vector3.one, updateType: UpdateType.LateUpdate)).tween;
Assert.AreEqual(_UpdateType.LateUpdate, t.settings._updateType);
Assert.AreEqual(t, PrimeTweenManager.Instance.lateUpdateTweens.Single());
}
{
Tween.StopAll();
var t = Tween.ShakeLocalPosition(transform, new ShakeSettings(Vector3.one, updateType: UpdateType.FixedUpdate)).tween;
Assert.AreEqual(_UpdateType.FixedUpdate, t.settings._updateType);
Assert.AreEqual(t, PrimeTweenManager.Instance.fixedUpdateTweens.Single());
}
{
Tween.StopAll();
PrimeTweenConfig.defaultUpdateType = UpdateType.FixedUpdate;
var t = Tween.Position(transform, default, new TweenSettings(1f, updateType: default)).tween;
Assert.AreEqual(_UpdateType.FixedUpdate, t.settings._updateType);
Assert.AreEqual(t, PrimeTweenManager.Instance.fixedUpdateTweens.Single());
}
{
Tween.StopAll();
PrimeTweenConfig.defaultUpdateType = UpdateType.LateUpdate;
var t = Tween.Position(transform, default, new TweenSettings(1f, updateType: default)).tween;
Assert.AreEqual(_UpdateType.LateUpdate, t.settings._updateType);
Assert.AreEqual(t, PrimeTweenManager.Instance.lateUpdateTweens.Single());
}
Tween.StopAll();
#pragma warning disable CS0618 // Type or member is obsolete
Assert.AreEqual(false, new TweenSettings(1f, updateType: default).useFixedUpdate);
Assert.AreEqual(false, new TweenSettings(1f, updateType: UpdateType.Update).useFixedUpdate);
Assert.AreEqual(false, new TweenSettings(1f, updateType: UpdateType.LateUpdate).useFixedUpdate);
Assert.AreEqual(true, new TweenSettings(1f, updateType: UpdateType.FixedUpdate).useFixedUpdate);
#pragma warning restore CS0618 // Type or member is obsolete
Assert.AreEqual(UpdateType.Default, new TweenSettings(1f, updateType: default).updateType);
PrimeTweenConfig.defaultUpdateType = UpdateType.Update;
Assert.AreEqual(UpdateType.Default, new TweenSettings(1f, updateType: default).updateType);
PrimeTweenConfig.defaultUpdateType = UpdateType.LateUpdate;
Assert.AreEqual(UpdateType.Update, new TweenSettings(1f, updateType: UpdateType.Update).updateType);
Assert.AreEqual(UpdateType.FixedUpdate, new TweenSettings(1f, updateType: UpdateType.FixedUpdate).updateType);
PrimeTweenConfig.defaultUpdateType = iniUpdateType;
}
}
#endif