A game framework written with osu! in mind.

Add generic easing to transforms

+111 -32
+7 -5
osu.Framework/Graphics/MarginPadding.cs
··· 3 4 using osuTK; 5 using System; 6 using osu.Framework.Utils; 7 8 namespace osu.Framework.Graphics ··· 94 Bottom = -mp.Bottom, 95 }; 96 97 - public MarginPadding ValueAt(double time, MarginPadding startValue, MarginPadding endValue, double startTime, double endTime, Easing easingType) 98 => new MarginPadding 99 { 100 - Left = Interpolation.ValueAt(time, startValue.Left, endValue.Left, startTime, endTime, easingType), 101 - Top = Interpolation.ValueAt(time, startValue.Top, endValue.Top, startTime, endTime, easingType), 102 - Right = Interpolation.ValueAt(time, startValue.Right, endValue.Right, startTime, endTime, easingType), 103 - Bottom = Interpolation.ValueAt(time, startValue.Bottom, endValue.Bottom, startTime, endTime, easingType), 104 }; 105 } 106 }
··· 3 4 using osuTK; 5 using System; 6 + using osu.Framework.Graphics.Transforms; 7 using osu.Framework.Utils; 8 9 namespace osu.Framework.Graphics ··· 95 Bottom = -mp.Bottom, 96 }; 97 98 + public MarginPadding ValueAt<TEasing>(double time, MarginPadding startValue, MarginPadding endValue, double startTime, double endTime, in TEasing easing) 99 + where TEasing : IEasingFunction 100 => new MarginPadding 101 { 102 + Left = Interpolation.ValueAt(time, startValue.Left, endValue.Left, startTime, endTime, easing), 103 + Top = Interpolation.ValueAt(time, startValue.Top, endValue.Top, startTime, endTime, easing), 104 + Right = Interpolation.ValueAt(time, startValue.Right, endValue.Right, startTime, endTime, easing), 105 + Bottom = Interpolation.ValueAt(time, startValue.Bottom, endValue.Bottom, startTime, endTime, easing), 106 }; 107 } 108 }
+66 -9
osu.Framework/Graphics/TransformableExtensions.cs
··· 29 /// <param name="easing">The transform easing to be used for tweening.</param> 30 /// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns> 31 public static TransformSequence<TThis> TransformTo<TThis, TValue>(this TThis t, string propertyOrFieldName, TValue newValue, double duration = 0, Easing easing = Easing.None) 32 - where TThis : class, ITransformable => 33 - t.TransformTo(t.MakeTransform(propertyOrFieldName, newValue, duration, easing)); 34 35 /// <summary> 36 /// Applies a <see cref="Transform"/> to a given <see cref="ITransformable"/>. ··· 50 /// <summary> 51 /// Creates a <see cref="Transform{TValue, T}"/> for smoothly changing <paramref name="propertyOrFieldName"/> 52 /// over time using the given <paramref name="easing"/> for tweening. 53 - /// <see cref="PopulateTransform{TValue, TThis}(TThis, Transform{TValue, TThis}, TValue, double, Easing)"/> 54 - /// is invoked as part of this method. 55 /// </summary> 56 /// <typeparam name="TThis">The type of the <see cref="ITransformable"/> the <see cref="Transform{TValue, T}"/> can be applied to.</typeparam> 57 /// <typeparam name="TValue">The value type which is being transformed.</typeparam> 58 /// <param name="t">The <see cref="ITransformable"/> the <see cref="Transform{TValue, T}"/> will be applied to.</param> 59 /// <param name="propertyOrFieldName">The property or field name of the member ot <typeparamref name="TThis"/> to transform.</param> 60 /// <param name="newValue">The value to transform to.</param> 61 /// <param name="duration">The transform duration.</param> 62 /// <param name="easing">The transform easing to be used for tweening.</param> 63 /// <returns>The resulting <see cref="Transform{TValue, T}"/>.</returns> 64 - public static Transform<TValue, TThis> MakeTransform<TThis, TValue>(this TThis t, string propertyOrFieldName, TValue newValue, double duration = 0, Easing easing = Easing.None) 65 - where TThis : class, ITransformable => 66 - t.PopulateTransform(new TransformCustom<TValue, TThis>(propertyOrFieldName), newValue, duration, easing); 67 68 /// <summary> 69 /// Populates a newly created <see cref="Transform{TValue, T}"/> with necessary values. ··· 77 /// <param name="duration">The transform duration.</param> 78 /// <param name="easing">The transform easing to be used for tweening.</param> 79 /// <returns>The populated <paramref name="transform"/>.</returns> 80 - public static Transform<TValue, TThis> PopulateTransform<TValue, TThis>(this TThis t, Transform<TValue, TThis> transform, TValue newValue, double duration = 0, Easing easing = Easing.None) 81 where TThis : class, ITransformable 82 { 83 if (duration < 0) 84 throw new ArgumentOutOfRangeException(nameof(duration), $"{nameof(duration)} must be positive."); ··· 415 /// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns> 416 public static TransformSequence<T> TransformBindableTo<T, TValue>(this T drawable, [NotNull] Bindable<TValue> bindable, TValue newValue, double duration = 0, Easing easing = Easing.None) 417 where T : class, ITransformable => 418 - drawable.TransformTo(drawable.PopulateTransform(new TransformBindable<TValue, T>(bindable), newValue, duration, easing)); 419 } 420 }
··· 29 /// <param name="easing">The transform easing to be used for tweening.</param> 30 /// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns> 31 public static TransformSequence<TThis> TransformTo<TThis, TValue>(this TThis t, string propertyOrFieldName, TValue newValue, double duration = 0, Easing easing = Easing.None) 32 + where TThis : class, ITransformable 33 + => t.TransformTo(t.MakeTransform(propertyOrFieldName, newValue, duration, new DefaultEasingFunction(easing))); 34 + 35 + /// <summary> 36 + /// Transforms a given property or field member of a given <see cref="ITransformable"/> <typeparamref name="TThis"/> to <paramref name="newValue"/>. 37 + /// The value of the given member is smoothly changed over time using the given <paramref name="easing"/> for tweening. 38 + /// </summary> 39 + /// <typeparam name="TThis">The type of the <see cref="ITransformable"/> to apply the <see cref="Transform{TValue, T}"/> to.</typeparam> 40 + /// <typeparam name="TValue">The value type which is being transformed.</typeparam> 41 + /// <typeparam name="TEasing">The type of easing.</typeparam> 42 + /// <param name="t">The <see cref="ITransformable"/> to apply the <see cref="Transform{TValue, T}"/> to.</param> 43 + /// <param name="propertyOrFieldName">The property or field name of the member ot <typeparamref name="TThis"/> to transform.</param> 44 + /// <param name="newValue">The value to transform to.</param> 45 + /// <param name="duration">The transform duration.</param> 46 + /// <param name="easing">The transform easing to be used for tweening.</param> 47 + /// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns> 48 + public static TransformSequence<TThis> TransformTo<TThis, TValue, TEasing>(this TThis t, string propertyOrFieldName, TValue newValue, double duration, TEasing easing) 49 + where TThis : class, ITransformable 50 + where TEasing : IEasingFunction 51 + => t.TransformTo(t.MakeTransform(propertyOrFieldName, newValue, duration, easing)); 52 53 /// <summary> 54 /// Applies a <see cref="Transform"/> to a given <see cref="ITransformable"/>. ··· 68 /// <summary> 69 /// Creates a <see cref="Transform{TValue, T}"/> for smoothly changing <paramref name="propertyOrFieldName"/> 70 /// over time using the given <paramref name="easing"/> for tweening. 71 + /// <see cref="PopulateTransform{TValue, DefaultEasingFunction, TThis}"/> is invoked as part of this method. 72 + /// </summary> 73 + /// <typeparam name="TThis">The type of the <see cref="ITransformable"/> the <see cref="Transform{TValue, T}"/> can be applied to.</typeparam> 74 + /// <typeparam name="TValue">The value type which is being transformed.</typeparam> 75 + /// <param name="t">The <see cref="ITransformable"/> the <see cref="Transform{TValue, T}"/> will be applied to.</param> 76 + /// <param name="propertyOrFieldName">The property or field name of the member ot <typeparamref name="TThis"/> to transform.</param> 77 + /// <param name="newValue">The value to transform to.</param> 78 + /// <param name="duration">The transform duration.</param> 79 + /// <param name="easing">The transform easing to be used for tweening.</param> 80 + /// <returns>The resulting <see cref="Transform{TValue, T}"/>.</returns> 81 + public static Transform<TValue, DefaultEasingFunction, TThis> MakeTransform<TThis, TValue>(this TThis t, string propertyOrFieldName, TValue newValue, double duration = 0, 82 + Easing easing = Easing.None) 83 + where TThis : class, ITransformable 84 + => t.MakeTransform(propertyOrFieldName, newValue, duration, new DefaultEasingFunction(easing)); 85 + 86 + /// <summary> 87 + /// Creates a <see cref="Transform{TValue, T}"/> for smoothly changing <paramref name="propertyOrFieldName"/> 88 + /// over time using the given <paramref name="easing"/> for tweening. 89 + /// <see cref="PopulateTransform{TValue, TEasing, TThis}"/> is invoked as part of this method. 90 /// </summary> 91 /// <typeparam name="TThis">The type of the <see cref="ITransformable"/> the <see cref="Transform{TValue, T}"/> can be applied to.</typeparam> 92 /// <typeparam name="TValue">The value type which is being transformed.</typeparam> 93 + /// <typeparam name="TEasing">The type of easing.</typeparam> 94 /// <param name="t">The <see cref="ITransformable"/> the <see cref="Transform{TValue, T}"/> will be applied to.</param> 95 /// <param name="propertyOrFieldName">The property or field name of the member ot <typeparamref name="TThis"/> to transform.</param> 96 /// <param name="newValue">The value to transform to.</param> 97 /// <param name="duration">The transform duration.</param> 98 /// <param name="easing">The transform easing to be used for tweening.</param> 99 /// <returns>The resulting <see cref="Transform{TValue, T}"/>.</returns> 100 + public static Transform<TValue, TEasing, TThis> MakeTransform<TThis, TEasing, TValue>(this TThis t, string propertyOrFieldName, TValue newValue, double duration, TEasing easing) 101 + where TThis : class, ITransformable 102 + where TEasing : IEasingFunction 103 + => t.PopulateTransform(new TransformCustom<TValue, TEasing, TThis>(propertyOrFieldName), newValue, duration, easing); 104 105 /// <summary> 106 /// Populates a newly created <see cref="Transform{TValue, T}"/> with necessary values. ··· 114 /// <param name="duration">The transform duration.</param> 115 /// <param name="easing">The transform easing to be used for tweening.</param> 116 /// <returns>The populated <paramref name="transform"/>.</returns> 117 + public static Transform<TValue, DefaultEasingFunction, TThis> PopulateTransform<TValue, TThis>(this TThis t, Transform<TValue, DefaultEasingFunction, TThis> transform, TValue newValue, 118 + double duration = 0, Easing easing = Easing.None) 119 where TThis : class, ITransformable 120 + => t.PopulateTransform(transform, newValue, duration, new DefaultEasingFunction(easing)); 121 + 122 + /// <summary> 123 + /// Populates a newly created <see cref="Transform{TValue, T}"/> with necessary values. 124 + /// All <see cref="Transform{TValue, T}"/>s must be populated by this method prior to being used. 125 + /// </summary> 126 + /// <typeparam name="TThis">The type of the <see cref="ITransformable"/> the <see cref="Transform{TValue, T}"/> can be applied to.</typeparam> 127 + /// <typeparam name="TValue">The value type which is being transformed.</typeparam> 128 + /// <typeparam name="TEasing">The type of easing.</typeparam> 129 + /// <param name="t">The <see cref="ITransformable"/> the <see cref="Transform{TValue, T}"/> will be applied to.</param> 130 + /// <param name="transform">The transform to populate.</param> 131 + /// <param name="newValue">The value to transform to.</param> 132 + /// <param name="duration">The transform duration.</param> 133 + /// <param name="easing">The transform easing to be used for tweening.</param> 134 + /// <returns>The populated <paramref name="transform"/>.</returns> 135 + public static Transform<TValue, TEasing, TThis> PopulateTransform<TValue, TEasing, TThis>(this TThis t, Transform<TValue, TEasing, TThis> transform, TValue newValue, double duration, 136 + TEasing easing) 137 + where TThis : class, ITransformable 138 + where TEasing : IEasingFunction 139 { 140 if (duration < 0) 141 throw new ArgumentOutOfRangeException(nameof(duration), $"{nameof(duration)} must be positive."); ··· 472 /// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns> 473 public static TransformSequence<T> TransformBindableTo<T, TValue>(this T drawable, [NotNull] Bindable<TValue> bindable, TValue newValue, double duration = 0, Easing easing = Easing.None) 474 where T : class, ITransformable => 475 + drawable.TransformTo(drawable.PopulateTransform(new TransformBindable<TValue, DefaultEasingFunction, T>(bindable), newValue, duration, new DefaultEasingFunction(easing))); 476 } 477 }
+9 -3
osu.Framework/Graphics/Transforms/Transform.cs
··· 26 /// </summary> 27 public bool Rewindable = true; 28 29 - public Easing Easing; 30 - 31 public abstract ITransformable TargetTransformable { get; } 32 33 public double StartTime { get; internal set; } ··· 75 public TValue EndValue { get; protected internal set; } 76 } 77 78 - public abstract class Transform<TValue, T> : Transform<TValue> 79 where T : class, ITransformable 80 { 81 public override ITransformable TargetTransformable => Target; 82 83 public T Target { get; internal set; } 84 85 public sealed override void Apply(double time) 86 { ··· 95 protected abstract void ReadIntoStartValue(T d); 96 97 public override string ToString() => $"{Target.GetType().Name}.{TargetMember} {StartTime}-{EndTime}ms {StartValue} -> {EndValue}"; 98 } 99 }
··· 26 /// </summary> 27 public bool Rewindable = true; 28 29 public abstract ITransformable TargetTransformable { get; } 30 31 public double StartTime { get; internal set; } ··· 73 public TValue EndValue { get; protected internal set; } 74 } 75 76 + public abstract class Transform<TValue, TEasing, T> : Transform<TValue> 77 + where TEasing : IEasingFunction 78 where T : class, ITransformable 79 { 80 public override ITransformable TargetTransformable => Target; 81 82 public T Target { get; internal set; } 83 + 84 + public TEasing Easing { get; internal set; } 85 86 public sealed override void Apply(double time) 87 { ··· 96 protected abstract void ReadIntoStartValue(T d); 97 98 public override string ToString() => $"{Target.GetType().Name}.{TargetMember} {StartTime}-{EndTime}ms {StartValue} -> {EndValue}"; 99 + } 100 + 101 + public abstract class Transform<TValue, T> : Transform<TValue, DefaultEasingFunction, T> 102 + where T : class, ITransformable 103 + { 104 } 105 }
+3 -2
osu.Framework/Graphics/Transforms/TransformBindable.cs
··· 6 7 namespace osu.Framework.Graphics.Transforms 8 { 9 - internal class TransformBindable<TValue, T> : Transform<TValue, T> 10 where T : class, ITransformable 11 { 12 public override string TargetMember { get; } 13 14 private readonly Bindable<TValue> targetBindable; 15 - private readonly InterpolationFunc<TValue> interpolationFunc; 16 17 public TransformBindable(Bindable<TValue> targetBindable) 18 {
··· 6 7 namespace osu.Framework.Graphics.Transforms 8 { 9 + internal class TransformBindable<TValue, TEasing, T> : Transform<TValue, TEasing, T> 10 where T : class, ITransformable 11 + where TEasing : IEasingFunction 12 { 13 public override string TargetMember { get; } 14 15 private readonly Bindable<TValue> targetBindable; 16 + private readonly InterpolationFunc<TValue, TEasing> interpolationFunc; 17 18 public TransformBindable(Bindable<TValue> targetBindable) 19 {
+14 -2
osu.Framework/Graphics/Transforms/TransformCustom.cs
··· 15 /// A transform which operates on arbitrary fields or properties of a given target. 16 /// </summary> 17 /// <typeparam name="TValue">The type of the field or property to operate upon.</typeparam> 18 /// <typeparam name="T">The type of the target to operate upon.</typeparam> 19 - internal class TransformCustom<TValue, T> : Transform<TValue, T> where T : class, ITransformable 20 { 21 private delegate TValue ReadFunc(T transformable); 22 ··· 141 private static Accessor getAccessor(string propertyOrFieldName) => accessors.GetOrAdd(propertyOrFieldName, key => findAccessor(typeof(T), key)); 142 143 private readonly Accessor accessor; 144 - private readonly InterpolationFunc<TValue> interpolationFunc; 145 146 /// <summary> 147 /// Creates a new instance operating on a property or field of <typeparamref name="T"/>. The property or field is ··· 175 protected override void Apply(T d, double time) => accessor.Write(d, valueAt(time)); 176 177 protected override void ReadIntoStartValue(T d) => StartValue = accessor.Read(d); 178 } 179 }
··· 15 /// A transform which operates on arbitrary fields or properties of a given target. 16 /// </summary> 17 /// <typeparam name="TValue">The type of the field or property to operate upon.</typeparam> 18 + /// <typeparam name="TEasing">The type of easing.</typeparam> 19 /// <typeparam name="T">The type of the target to operate upon.</typeparam> 20 + internal class TransformCustom<TValue, TEasing, T> : Transform<TValue, TEasing, T> 21 + where T : class, ITransformable 22 + where TEasing : IEasingFunction 23 { 24 private delegate TValue ReadFunc(T transformable); 25 ··· 144 private static Accessor getAccessor(string propertyOrFieldName) => accessors.GetOrAdd(propertyOrFieldName, key => findAccessor(typeof(T), key)); 145 146 private readonly Accessor accessor; 147 + private readonly InterpolationFunc<TValue, TEasing> interpolationFunc; 148 149 /// <summary> 150 /// Creates a new instance operating on a property or field of <typeparamref name="T"/>. The property or field is ··· 178 protected override void Apply(T d, double time) => accessor.Write(d, valueAt(time)); 179 180 protected override void ReadIntoStartValue(T d) => StartValue = accessor.Read(d); 181 + } 182 + 183 + internal class TransformCustom<TValue, T> : TransformCustom<TValue, DefaultEasingFunction, T> 184 + where T : class, ITransformable 185 + { 186 + public TransformCustom(string propertyOrFieldName) 187 + : base(propertyOrFieldName) 188 + { 189 + } 190 } 191 }
+1 -1
osu.Framework/Graphics/Transforms/Transformable.cs
··· 412 413 /// <summary> 414 /// Adds to this object a <see cref="Transform"/> which was previously populated using this object via 415 - /// <see cref="TransformableExtensions.PopulateTransform{TValue, TThis}(TThis, Transform{TValue, TThis}, TValue, double, Easing)"/>. 416 /// Added <see cref="Transform"/>s are immediately applied, and therefore have an immediate effect on this object if the current time of this 417 /// object falls within <see cref="Transform.StartTime"/> and <see cref="Transform.EndTime"/>. 418 /// If <see cref="Clock"/> is null, e.g. because this object has just been constructed, then the given transform will be finished instantaneously.
··· 412 413 /// <summary> 414 /// Adds to this object a <see cref="Transform"/> which was previously populated using this object via 415 + /// <see cref="TransformableExtensions.PopulateTransform{TValue, TEasing, TThis}"/>. 416 /// Added <see cref="Transform"/>s are immediately applied, and therefore have an immediate effect on this object if the current time of this 417 /// object falls within <see cref="Transform.StartTime"/> and <see cref="Transform.EndTime"/>. 418 /// If <see cref="Clock"/> is null, e.g. because this object has just been constructed, then the given transform will be finished instantaneously.
+3 -3
osu.Framework/Utils/IInterpolable.cs
··· 1 // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. 2 // See the LICENCE file in the repository root for full licence text. 3 4 - using osu.Framework.Graphics; 5 6 namespace osu.Framework.Utils 7 { ··· 22 /// <param name="endValue">The <typeparamref name="TValue"/> at <paramref name="time"/> = <paramref name="endTime"/>.</param> 23 /// <param name="startTime">The start time.</param> 24 /// <param name="endTime">The end time.</param> 25 - /// <param name="easingType">The easing to use.</param> 26 /// <returns>The interpolated value.</returns> 27 - TValue ValueAt(double time, TValue startValue, TValue endValue, double startTime, double endTime, Easing easingType = Easing.None); 28 } 29 }
··· 1 // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. 2 // See the LICENCE file in the repository root for full licence text. 3 4 + using osu.Framework.Graphics.Transforms; 5 6 namespace osu.Framework.Utils 7 { ··· 22 /// <param name="endValue">The <typeparamref name="TValue"/> at <paramref name="time"/> = <paramref name="endTime"/>.</param> 23 /// <param name="startTime">The start time.</param> 24 /// <param name="endTime">The end time.</param> 25 + /// <param name="easing">The easing function to use.</param> 26 /// <returns>The interpolated value.</returns> 27 + TValue ValueAt<TEasing>(double time, TValue startValue, TValue endValue, double startTime, double endTime, in TEasing easing) where TEasing : IEasingFunction; 28 } 29 }
+8 -7
osu.Framework/Utils/Interpolation.cs
··· 330 331 public static TValue ValueAt<TValue, TEasing>(double time, TValue startValue, TValue endValue, double startTime, double endTime, in TEasing easing) 332 where TEasing : IEasingFunction 333 - => GenericInterpolation<TValue>.FUNCTION(time, startValue, endValue, startTime, endTime, easing); 334 335 #endregion 336 ··· 341 where TEasing : IEasingFunction 342 => easing.ApplyEasing(time); 343 344 - private static class GenericInterpolation<TValue> 345 { 346 - public static readonly InterpolationFunc<TValue> FUNCTION; 347 348 static GenericInterpolation() 349 { 350 const string interpolation_method = nameof(Interpolation.ValueAt); 351 352 - var parameters = typeof(InterpolationFunc<TValue>) 353 - .GetMethod(nameof(InterpolationFunc<TValue>.Invoke)) 354 ?.GetParameters().Select(p => p.ParameterType).ToArray(); 355 356 MethodInfo valueAtMethod = typeof(Interpolation).GetMethod(interpolation_method, parameters); 357 358 if (valueAtMethod != null) 359 - FUNCTION = (InterpolationFunc<TValue>)valueAtMethod.CreateDelegate(typeof(InterpolationFunc<TValue>)); 360 else 361 { 362 var typeRef = FormatterServices.GetSafeUninitializedObject(typeof(TValue)) as IInterpolable<TValue>; ··· 370 } 371 } 372 373 - public delegate TValue InterpolationFunc<TValue>(double time, TValue startValue, TValue endValue, double startTime, double endTime, Easing easingType); 374 }
··· 330 331 public static TValue ValueAt<TValue, TEasing>(double time, TValue startValue, TValue endValue, double startTime, double endTime, in TEasing easing) 332 where TEasing : IEasingFunction 333 + => GenericInterpolation<TValue, TEasing>.FUNCTION(time, startValue, endValue, startTime, endTime, easing); 334 335 #endregion 336 ··· 341 where TEasing : IEasingFunction 342 => easing.ApplyEasing(time); 343 344 + private static class GenericInterpolation<TValue, TEasing> 345 + where TEasing : IEasingFunction 346 { 347 + public static readonly InterpolationFunc<TValue, TEasing> FUNCTION; 348 349 static GenericInterpolation() 350 { 351 const string interpolation_method = nameof(Interpolation.ValueAt); 352 353 + var parameters = typeof(InterpolationFunc<TValue, TEasing>) 354 + .GetMethod(nameof(InterpolationFunc<TValue, TEasing>.Invoke)) 355 ?.GetParameters().Select(p => p.ParameterType).ToArray(); 356 357 MethodInfo valueAtMethod = typeof(Interpolation).GetMethod(interpolation_method, parameters); 358 359 if (valueAtMethod != null) 360 + FUNCTION = (InterpolationFunc<TValue, TEasing>)valueAtMethod.CreateDelegate(typeof(InterpolationFunc<TValue, TEasing>)); 361 else 362 { 363 var typeRef = FormatterServices.GetSafeUninitializedObject(typeof(TValue)) as IInterpolable<TValue>; ··· 371 } 372 } 373 374 + public delegate TValue InterpolationFunc<TValue, TEasing>(double time, TValue startValue, TValue endValue, double startTime, double endTime, in TEasing easingType) where TEasing : IEasingFunction; 375 }