477 lines
23 KiB
C#
477 lines
23 KiB
C#
// ReSharper disable UnusedMember.Global
|
|
// ReSharper disable UnusedMethodReturnValue.Global
|
|
#if PRIME_TWEEN_DOTWEEN_ADAPTER
|
|
using System;
|
|
using System.Collections;
|
|
using JetBrains.Annotations;
|
|
using UnityEngine;
|
|
|
|
namespace PrimeTween {
|
|
public static partial class DOTweenAdapter {
|
|
static int remapFrequency(float frequency) {
|
|
return (int) (frequency * 1.35f);
|
|
}
|
|
|
|
public static Tween DOShakePosition([NotNull] this Component target, float duration, float strength, int vibrato = 10, float randomness = 90, bool snapping = false, bool fadeOut = true)
|
|
=> DOShakePosition(target, duration, Vector3.one * strength, vibrato, randomness, snapping, fadeOut);
|
|
public static Tween DOShakePosition([NotNull] this Component target, float duration, Vector3 strength, int vibrato = 10, float randomness = 90, bool snapping = false, bool fadeOut = true) {
|
|
if (Math.Abs(randomness - 90f) > 0.001f) {
|
|
Debug.LogWarning("PrimeTween doesn't support " + nameof(randomness));
|
|
}
|
|
if (snapping) {
|
|
Debug.LogWarning("PrimeTween doesn't support " + nameof(snapping));
|
|
}
|
|
var settings = new ShakeSettings(strength, duration, vibrato);
|
|
if (fadeOut) {
|
|
settings.enableFalloff = true;
|
|
settings.frequency = remapFrequency(settings.frequency);
|
|
}
|
|
return Tween.ShakeLocalPosition(target.transform, settings);
|
|
}
|
|
public static Tween DOPunchPosition([NotNull] this Component target, Vector3 punch, float duration, int vibrato = 10, float elasticity = 1, bool snapping = false) {
|
|
if (snapping) {
|
|
Debug.LogWarning("PrimeTween doesn't support " + nameof(snapping));
|
|
}
|
|
var shakeSettings = new ShakeSettings(punch, duration, remapFrequency(vibrato), asymmetryFactor: 1 - elasticity);
|
|
return Tween.PunchLocalPosition(target.transform, shakeSettings);
|
|
}
|
|
|
|
public static Tween DOShakeRotation([NotNull] this Component target, float duration, float strength, int vibrato = 10, float randomness = 90, bool fadeOut = true)
|
|
=> DOShakeRotation(target, duration, Vector3.one * strength, vibrato, randomness, fadeOut);
|
|
public static Tween DOShakeRotation([NotNull] this Component target, float duration, Vector3 strength, int vibrato = 10, float randomness = 90, bool fadeOut = true) {
|
|
if (Math.Abs(randomness - 90f) > 0.001f) {
|
|
Debug.LogWarning("PrimeTween doesn't support " + nameof(randomness));
|
|
}
|
|
var settings = new ShakeSettings(strength, duration, vibrato);
|
|
if (fadeOut) {
|
|
settings.enableFalloff = true;
|
|
settings.frequency = remapFrequency(settings.frequency);
|
|
}
|
|
return Tween.ShakeLocalRotation(target.transform, settings);
|
|
}
|
|
public static Tween DOPunchRotation([NotNull] this Component target, Vector3 punch, float duration, int vibrato = 10, float elasticity = 1) {
|
|
var shakeSettings = new ShakeSettings(punch, duration, remapFrequency(vibrato), asymmetryFactor: 1 - elasticity);
|
|
return Tween.PunchLocalRotation(target.transform, shakeSettings);
|
|
}
|
|
|
|
public static Tween DOShakeScale([NotNull] this Component target, float duration, float strength, int vibrato = 10, float randomness = 90, bool fadeOut = true)
|
|
=> DOShakeScale(target, duration, Vector3.one * strength, vibrato, randomness, fadeOut);
|
|
public static Tween DOShakeScale([NotNull] this Component target, float duration, Vector3 strength, int vibrato = 10, float randomness = 90, bool fadeOut = true) {
|
|
if (Math.Abs(randomness - 90f) > 0.001f) {
|
|
Debug.LogWarning("PrimeTween doesn't support " + nameof(randomness));
|
|
}
|
|
var settings = new ShakeSettings(strength, duration, vibrato);
|
|
if (fadeOut) {
|
|
settings.enableFalloff = true;
|
|
settings.frequency = remapFrequency(settings.frequency);
|
|
}
|
|
return Tween.ShakeScale(target.transform, settings);
|
|
}
|
|
public static Tween DOPunchScale([NotNull] this Component target, Vector3 punch, float duration, int vibrato = 10, float elasticity = 1) {
|
|
var shakeSettings = new ShakeSettings(punch, duration, remapFrequency(vibrato), asymmetryFactor: 1 - elasticity);
|
|
return Tween.PunchScale(target.transform, shakeSettings);
|
|
}
|
|
|
|
public static Tween DORotate([NotNull] this Transform target, Vector3 endValue, float duration) {
|
|
return Tween.Rotation(target, Quaternion.Euler(endValue), duration);
|
|
}
|
|
|
|
public static Tween DOLocalRotate([NotNull] this Transform target, Vector3 endValue, float duration) {
|
|
return Tween.LocalRotation(target, Quaternion.Euler(endValue), duration);
|
|
}
|
|
|
|
public static Tween DOScale([NotNull] this Transform target, Single endValue, float duration) {
|
|
return Tween.Scale(target, endValue, duration);
|
|
}
|
|
|
|
public static int DOKill([NotNull] this Component target, bool complete = false) => doKill_internal(target, complete);
|
|
public static int DOKill([NotNull] this Material target, bool complete = false) => doKill_internal(target, complete);
|
|
|
|
internal static int doKill_internal([CanBeNull] object target, bool complete = false) {
|
|
bool prevLogCantManipulateError = PrimeTweenManager.logCantManipulateError;
|
|
PrimeTweenManager.logCantManipulateError = false;
|
|
var result = complete ? Tween.CompleteAll(target) : Tween.StopAll(target);
|
|
PrimeTweenManager.logCantManipulateError = prevLogCantManipulateError;
|
|
return result;
|
|
}
|
|
|
|
internal static Easing GetEasing(Ease ease, float? maybeStrength, float? maybePeriod) {
|
|
var strength = maybeStrength ?? 1;
|
|
switch (ease) {
|
|
case Ease.OutBack:
|
|
if (maybePeriod.HasValue) {
|
|
Debug.LogWarning("Ease.OutBack doesn't support custom period.");
|
|
}
|
|
return Easing.Overshoot(strength / StandardEasing.backEaseConst);
|
|
case Ease.OutBounce:
|
|
return Easing.Bounce(strength);
|
|
case Ease.OutElastic:
|
|
return Easing.Elastic(strength, maybePeriod ?? StandardEasing.defaultElasticEasePeriod);
|
|
}
|
|
return Easing.Standard(ease);
|
|
}
|
|
|
|
// public static Tween DOTWEEN_METHOD_NAME([NotNull] this UnityEngine.Camera target, Single endValue, float duration) => Tween.METHOD_NAME(target, endValue, duration);
|
|
}
|
|
|
|
public static class DOTween {
|
|
public static Ease defaultEaseType {
|
|
get => PrimeTweenConfig.defaultEase;
|
|
set => PrimeTweenConfig.defaultEase = value;
|
|
}
|
|
|
|
public static Sequence Sequence() => PrimeTween.Sequence.Create();
|
|
|
|
public static void Kill([NotNull] object target, bool complete = false) => DOTweenAdapter.doKill_internal(target, complete);
|
|
|
|
public static void KillAll(bool complete = false) => DOTweenAdapter.doKill_internal(null, complete);
|
|
|
|
public static Tween To([NotNull] Func<float> getter, [NotNull] Action<float> setter, float endValue, float duration) => Tween.Custom(getter(), endValue, duration, val => setter(val));
|
|
public static Tween To([NotNull] Func<Vector2> getter, [NotNull] Action<Vector2> setter, Vector2 endValue, float duration) => Tween.Custom(getter(), endValue, duration, val => setter(val));
|
|
public static Tween To([NotNull] Func<Vector3> getter, [NotNull] Action<Vector3> setter, Vector3 endValue, float duration) => Tween.Custom(getter(), endValue, duration, val => setter(val));
|
|
public static Tween To([NotNull] Func<Vector4> getter, [NotNull] Action<Vector4> setter, Vector4 endValue, float duration) => Tween.Custom(getter(), endValue, duration, val => setter(val));
|
|
public static Tween To([NotNull] Func<Quaternion> getter, [NotNull] Action<Quaternion> setter, Quaternion endValue, float duration) => Tween.Custom(getter(), endValue, duration, val => setter(val));
|
|
public static Tween To([NotNull] Func<Color> getter, [NotNull] Action<Color> setter, Color endValue, float duration) => Tween.Custom(getter(), endValue, duration, val => setter(val));
|
|
public static Tween To([NotNull] Func<Rect> getter, [NotNull] Action<Rect> setter, Rect endValue, float duration) => Tween.Custom(getter(), endValue, duration, val => setter(val));
|
|
}
|
|
|
|
public static class DOVirtual {
|
|
public static Tween DelayedCall(float delay, Action callback, bool ignoreTimeScale = true)
|
|
=> Tween.Delay(delay, callback, ignoreTimeScale);
|
|
|
|
public static Tween Float(float startValue, float endValue, float duration, Action<float> onValueChange) => Tween.Custom(startValue, endValue, duration, onValueChange);
|
|
public static Tween Vector3(Vector3 startValue, Vector3 endValue, float duration, Action<Vector3> onValueChange) => Tween.Custom(startValue, endValue, duration, onValueChange);
|
|
public static Tween Color(Color startValue, Color endValue, float duration, Action<Color> onValueChange) => Tween.Custom(startValue, endValue, duration, onValueChange);
|
|
|
|
public static float EasedValue(float from, float to, float lifetimePercentage, Ease easeType, float? amplitude = null, float? period = null)
|
|
=> Mathf.LerpUnclamped(from, to, DOTweenAdapter.GetEasing(easeType, amplitude, period).Evaluate(lifetimePercentage));
|
|
public static float EasedValue(float from, float to, float lifetimePercentage, [NotNull] AnimationCurve easeCurve)
|
|
=> Mathf.LerpUnclamped(from, to, Easing.Curve(easeCurve).Evaluate(lifetimePercentage));
|
|
public static Vector3 EasedValue(Vector3 from, Vector3 to, float lifetimePercentage, Ease easeType, float? amplitude = null, float? period = null)
|
|
=> UnityEngine.Vector3.LerpUnclamped(from, to, DOTweenAdapter.GetEasing(easeType, amplitude, period).Evaluate(lifetimePercentage));
|
|
public static Vector3 EasedValue(Vector3 from, Vector3 to, float lifetimePercentage, [NotNull] AnimationCurve easeCurve)
|
|
=> UnityEngine.Vector3.LerpUnclamped(from, to, Easing.Curve(easeCurve).Evaluate(lifetimePercentage));
|
|
}
|
|
|
|
public partial struct Sequence {
|
|
public Sequence AppendCallback([NotNull] Action callback) {
|
|
return ChainCallback(callback);
|
|
}
|
|
|
|
public Sequence SetLoops(int loops, LoopType? loopType = null) {
|
|
root.SetLoops(loops, loopType);
|
|
return this;
|
|
}
|
|
|
|
public Sequence Join(Sequence other) => Group(other);
|
|
|
|
public Sequence Join(Tween other) {
|
|
var tween = other.tween;
|
|
var startDelay = tween.settings.startDelay;
|
|
if (startDelay > 0) {
|
|
// For some weird reason, DG.Tweening.Sequence.DoInsert shifts the lastTweenInsertTime by a tween's delay.
|
|
tween.settings.startDelay = 0;
|
|
tween.recalculateTotalDuration();
|
|
Group(Tween.Delay(startDelay));
|
|
ChainLast(other);
|
|
return this;
|
|
}
|
|
return Group(other);
|
|
}
|
|
|
|
/// <summary>Schedules <see cref="other"/> after the last added tween.
|
|
/// Internal because this API is hard to understand, but needed for adapter.</summary>
|
|
internal Sequence ChainLast(Tween other) {
|
|
if (tryManipulate()) {
|
|
Insert(getLastInSelfOrRoot().durationWithWaitDelay, other);
|
|
}
|
|
return this;
|
|
}
|
|
|
|
public Sequence Append(Sequence other) => Chain(other);
|
|
|
|
public Sequence Append(Tween other) {
|
|
var tween = other.tween;
|
|
var startDelay = tween.settings.startDelay;
|
|
if (startDelay > 0) {
|
|
// For some weird reason, DG.Tweening.Sequence.DoInsert shifts the lastTweenInsertTime by a tween's delay.
|
|
tween.settings.startDelay = 0;
|
|
tween.recalculateTotalDuration();
|
|
Chain(Tween.Delay(startDelay));
|
|
}
|
|
return Chain(other);
|
|
}
|
|
|
|
public Sequence AppendInterval(float delay) {
|
|
return Chain(Tween.Delay(delay));
|
|
}
|
|
|
|
public void Kill(bool complete = false) {
|
|
if (complete) {
|
|
Complete();
|
|
} else {
|
|
Stop();
|
|
}
|
|
}
|
|
|
|
public void Complete(bool withCallbacks) {
|
|
if (withCallbacks) {
|
|
Debug.LogWarning("PrimeTween doesn't support " + nameof(Sequence) + "." + nameof(Complete) + "() " + nameof(withCallbacks) + " == true");
|
|
}
|
|
Complete();
|
|
}
|
|
|
|
public Sequence SetEase(Ease ease, float? amplitude = null, float? period = null) {
|
|
root.SetEase(ease, amplitude, period);
|
|
return this;
|
|
}
|
|
|
|
public Sequence SetEase([NotNull] AnimationCurve animCurve) {
|
|
root.SetEase(animCurve);
|
|
return this;
|
|
}
|
|
|
|
public Sequence SetDelay(float delay) {
|
|
return PrependInterval(delay);
|
|
}
|
|
|
|
public Sequence OnStepComplete([NotNull] Action action) {
|
|
Debug.LogWarning("Please use sequence.ChainCallback() as the last operation instead of sequence.OnStepComplete()");
|
|
return ChainCallback(action);
|
|
}
|
|
|
|
public Sequence PrependInterval(float interval) {
|
|
if (!ValidateCanManipulateSequence()) {
|
|
return this;
|
|
}
|
|
foreach (var t in getSelfChildren()) {
|
|
t.tween.waitDelay += interval;
|
|
}
|
|
duration += interval;
|
|
return this;
|
|
}
|
|
|
|
public Sequence SetUpdate(bool isIndependentUpdate) {
|
|
Assert.IsTrue(isAlive);
|
|
Assert.IsTrue(root.tween.isMainSequenceRoot());
|
|
root.tween.settings.useUnscaledTime = isIndependentUpdate;
|
|
return this;
|
|
}
|
|
|
|
public Sequence AsyncWaitForCompletion() => this;
|
|
|
|
public IEnumerator WaitForCompletion() => ToYieldInstruction();
|
|
|
|
/// <summary>It's safe to destroy objects with running animations in PrimeTween, so this adapter method does nothing. More info: https://github.com/KyryloKuzyk/PrimeTween/discussions/4</summary>
|
|
[PublicAPI]
|
|
public Sequence SetLink(GameObject gameObject) => this;
|
|
|
|
public Sequence Pause() {
|
|
isPaused = true;
|
|
return this;
|
|
}
|
|
|
|
public Sequence Play() {
|
|
isPaused = false;
|
|
return this;
|
|
}
|
|
}
|
|
|
|
public partial struct Tween {
|
|
public Tween SetEase(Ease ease, float? amplitude = null, float? period = null) {
|
|
Assert.IsTrue(isAlive);
|
|
var parametricEasing = DOTweenAdapter.GetEasing(ease, amplitude, period);
|
|
tween.settings.SetEasing(parametricEasing);
|
|
return this;
|
|
}
|
|
|
|
public Tween SetDelay(float delay) {
|
|
Assert.IsTrue(isAlive);
|
|
Assert.IsFalse(tween.IsInSequence());
|
|
tween.settings.startDelay = delay;
|
|
tween.recalculateTotalDuration();
|
|
return this;
|
|
}
|
|
|
|
public Tween SetRelative(bool isRelative = true) {
|
|
Assert.IsTrue(isAlive);
|
|
if (!isRelative) {
|
|
return this;
|
|
}
|
|
var getter = tween.getter;
|
|
if (getter == null) {
|
|
return this;
|
|
}
|
|
tween.endValue = CalculateRelative(tween, getter(tween), tween.endValue);
|
|
/*var getter = tween.getter;
|
|
// todo this doesn't account for double val
|
|
if (tween.propType == PropType.Quaternion) {
|
|
if (getter != null) {
|
|
tween.endValue.QuaternionVal *= getter(tween).QuaternionVal;
|
|
} else {
|
|
tween.endValue.QuaternionVal *= tween.startValue.QuaternionVal;
|
|
}
|
|
} else {
|
|
if (getter != null) {
|
|
tween.endValue.Vector4Val += getter(tween).Vector4Val;
|
|
} else {
|
|
tween.endValue.Vector4Val += tween.startValue.Vector4Val;
|
|
}
|
|
}*/
|
|
return this;
|
|
}
|
|
|
|
public Tween SetLoops(int loops, LoopType? loopType = null) {
|
|
SetRemainingCycles(loops);
|
|
if (isAlive && loopType.HasValue) {
|
|
tween.settings.cycleMode = toCycleMode(loopType.Value);
|
|
}
|
|
return this;
|
|
}
|
|
|
|
static CycleMode toCycleMode(LoopType t) {
|
|
switch (t) {
|
|
case LoopType.Restart:
|
|
return CycleMode.Restart;
|
|
case LoopType.Yoyo:
|
|
// yoyo in dotween behaves like rewind. But yoyo in other tween libraries (like tween.js) preserves the normal ease
|
|
return CycleMode.Rewind;
|
|
case LoopType.Incremental:
|
|
return CycleMode.Incremental;
|
|
default:
|
|
throw new Exception();
|
|
}
|
|
}
|
|
|
|
public void Kill(bool complete = false) {
|
|
if (complete) {
|
|
Complete();
|
|
} else {
|
|
Stop();
|
|
}
|
|
}
|
|
|
|
public bool IsActive() => isAlive;
|
|
public bool active => isAlive;
|
|
public bool IsPlaying() => isAlive && !isPaused;
|
|
|
|
public Tween Pause() {
|
|
isPaused = true;
|
|
return this;
|
|
}
|
|
|
|
public Tween Play() {
|
|
isPaused = false;
|
|
return this;
|
|
}
|
|
|
|
public float Elapsed(bool includeLoops = true) => includeLoops ? elapsedTimeTotal : elapsedTime;
|
|
public float Duration(bool includeLoops = true) => includeLoops ? durationTotal : duration;
|
|
public int Loops() => cyclesTotal;
|
|
public int CompletedLoops() => cyclesDone;
|
|
public float ElapsedDelay() => isAlive ? Mathf.Clamp(elapsedTime, 0f, tween.settings.startDelay) : 0;
|
|
public float ElapsedPercentage(bool includeLoops = true) => includeLoops ? progressTotal : progress;
|
|
public void TogglePause() => isPaused = !isPaused;
|
|
|
|
public Tween SetEase([NotNull] AnimationCurve animCurve) {
|
|
Assert.IsTrue(isAlive);
|
|
Assert.IsNotNull(animCurve);
|
|
tween.settings.SetEasing(Easing.Curve(animCurve));
|
|
return this;
|
|
}
|
|
|
|
public Tween SetTarget([NotNull] object target) {
|
|
Assert.IsNotNull(target);
|
|
Assert.IsTrue(isAlive);
|
|
tween.target = target;
|
|
tween.setUnityTarget(target);
|
|
return this;
|
|
}
|
|
|
|
public IEnumerator WaitForCompletion() => ToYieldInstruction();
|
|
|
|
public Tween AsyncWaitForCompletion() => this;
|
|
|
|
public Tween SetUpdate(bool isIndependentUpdate) {
|
|
Assert.IsTrue(isAlive);
|
|
tween.settings.useUnscaledTime = isIndependentUpdate;
|
|
return this;
|
|
}
|
|
|
|
public Tween From() => setFrom(true, false);
|
|
public Tween From(bool isRelative) => setFrom(true, isRelative);
|
|
public Tween From(bool setImmediately, bool isRelative) => setFrom(setImmediately, isRelative);
|
|
|
|
public Tween From(float fromValue, bool setImmediately = true, bool isRelative = false) => setFrom(setImmediately, isRelative, fromValue.ToContainer(), PropType.Float);
|
|
public Tween From(Color fromValue, bool setImmediately = true, bool isRelative = false) => setFrom(setImmediately, isRelative, fromValue.ToContainer(), PropType.Color);
|
|
public Tween From(Vector2 fromValue, bool setImmediately = true, bool isRelative = false) => setFrom(setImmediately, isRelative, fromValue.ToContainer(), PropType.Vector2);
|
|
public Tween From(Vector3 fromValue, bool setImmediately = true, bool isRelative = false) => setFrom(setImmediately, isRelative, fromValue.ToContainer(), PropType.Vector3);
|
|
public Tween From(Vector4 fromValue, bool setImmediately = true, bool isRelative = false) => setFrom(setImmediately, isRelative, fromValue.ToContainer(), PropType.Vector4);
|
|
public Tween From(Quaternion fromValue, bool setImmediately = true, bool isRelative = false) => setFrom(setImmediately, isRelative, fromValue.ToContainer(), PropType.Quaternion);
|
|
public Tween From(Rect fromValue, bool setImmediately = true, bool isRelative = false) => setFrom(setImmediately, isRelative, fromValue.ToContainer(), PropType.Rect);
|
|
|
|
static ValueContainer CalculateRelative(ReusableTween tween, ValueContainer current, ValueContainer diff) {
|
|
switch (tween.propType) {
|
|
case PropType.Quaternion:
|
|
return (current.QuaternionVal * diff.QuaternionVal).ToContainer();
|
|
case PropType.Double:
|
|
return (current.DoubleVal + diff.DoubleVal).ToContainer();
|
|
default:
|
|
return (current.Vector4Val + diff.Vector4Val).ToContainer();
|
|
}
|
|
}
|
|
|
|
Tween setFrom(bool setImmediately, bool isRelative, ValueContainer? fromValue = null, PropType propType = PropType.None) {
|
|
if (!tryManipulate()) {
|
|
return this;
|
|
}
|
|
if (elapsedTimeTotal != 0f) {
|
|
Debug.LogError(Constants.animationAlreadyStarted);
|
|
return this;
|
|
}
|
|
if (tween.isUnityTargetDestroyed()) {
|
|
Debug.LogError("Tween's target has been destroyed.");
|
|
return this;
|
|
}
|
|
var getter = tween.getter;
|
|
if (getter == null) {
|
|
Debug.LogError("Custom tweens don't support 'From()'.");
|
|
return this;
|
|
}
|
|
var current = getter(tween);
|
|
if (isRelative) {
|
|
tween.endValue = CalculateRelative(tween, current, tween.endValue);
|
|
}
|
|
if (fromValue.HasValue) {
|
|
if (tween.propType != propType) {
|
|
Debug.LogError($"Animated value is {tween.propType}, but '{nameof(From)}()' was called with {propType}. Please provide a correct type.");
|
|
return this;
|
|
}
|
|
tween.startFromCurrent = false;
|
|
tween.startValue = isRelative ? CalculateRelative(tween, current, fromValue.Value) : fromValue.Value;
|
|
} else {
|
|
tween.startFromCurrent = false;
|
|
tween.startValue = tween.endValue;
|
|
tween.endValue = current;
|
|
}
|
|
tween.cacheDiff();
|
|
if (setImmediately) {
|
|
tween.ReportOnValueChange(0f);
|
|
}
|
|
return this;
|
|
}
|
|
|
|
[PublicAPI]
|
|
public Tween SetLink(GameObject gameObject) {
|
|
return this;
|
|
}
|
|
}
|
|
|
|
public enum LoopType {
|
|
Restart,
|
|
Yoyo,
|
|
Incremental
|
|
}
|
|
}
|
|
#endif
|