Added GTWeen

This commit is contained in:
Marco 2025-02-24 11:52:50 +01:00
commit 2036e4e748
152 changed files with 5889 additions and 7 deletions

7
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,7 @@
# Contributing
- Feel free to fork this repository and raise a pull request.
- Feel free to open an [issue](https://github.com/Guillemsc/GTweensGodot/issues) if you find any bug or have some enhancement proposal.
- Feel free to open a [discussion](https://github.com/Guillemsc/GTweensGodot/discussions).
*Thank you* for contributing to GTweensGodot.

View file

@ -0,0 +1,7 @@
# Contributing
- Feel free to fork this repository and raise a pull request.
- Feel free to open an [issue](https://github.com/Guillemsc/GTweensGodot/issues) if you find any bug or have some enhancement proposal.
- Feel free to open a [discussion](https://github.com/Guillemsc/GTweensGodot/discussions).
*Thank you* for contributing to GTweensGodot.

View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 Guillem SC
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,138 @@
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
[![Contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/Guillemsc/GTweens/blob/main/CONTRIBUTING.md)
[![Release](https://img.shields.io/github/release/Guillemsc/GTweens.svg)](https://github.com/Guillemsc/GTweens/releases/latest)
[![NuGet](https://img.shields.io/nuget/v/GTweens.svg?label=nuget)](https://www.nuget.org/packages/GTweens)
[![Downloads](https://img.shields.io/nuget/dt/GTweens)](https://www.nuget.org/packages/GTweens)
[![Tests](https://github.com/Guillemsc/GTweens/actions/workflows/tests.yml/badge.svg)](https://github.com/Guillemsc/GTweens/actions/workflows/tests.yml)
[![Twitter Follow](https://img.shields.io/badge/twitter-%406uillem-blue.svg?style=flat&label=Follow)](https://twitter.com/6uillem)
![LogoWide-2](https://github.com/Guillemsc/GTweens/assets/17142208/ffeede41-5f4a-456f-8cd1-b74e2a26710a)
GTweens is a lightweight and versatile tweening library for C#.
This library simplifies the process of creating animations and transitions in your projects, allowing you to bring your game elements to life with ease.
## 🤜 Features
- **Sequencing**: Easily chain multiple tweens together to create complex sequences of animations.
- **Versatile Easing Functions**: Choose from a variety of easing functions to achieve different animation effects, including linear, ease-in, ease-out, etc.
- **Looping**: Create looping animations with a single line of code, and control loop count and behavior.
- **Delays**: Specify delays, allowing precise timing of your animations.
- **Callbacks**: Attach callbacks to tweens for event handling at various points in the animation timeline.
## 📦 Installation
1. [Download the latest release](https://github.com/Guillemsc/GTweens/releases/latest).
2. Unpack the `GTweens` folder into the project.
## 📚 Getting started
### Nomenclature
- Tween: a generic word that indicates some or multiple values being animated.
- Sequence: an combination of tweens that get animated as a group.
### Prefixes
Prefixes are important to use the most out of IntelliSense, so try to remember these:
- **Set**: prefix for all settings that can be chained to a tween.
```csharp
myTween.SetLoops(4).SetEasing(Easing.InOutCubic);
```
- **On**: prefix for all callbacks that can be chained to a tween.
```csharp
myTween.OnStart(myStartFunction).OnComplete(myCompleteFunction);
```
### Generic tweening
This is the most flexible way of tweening and allows you to tween almost any value.
```csharp
// For default C# values (int, float, etc)
GTweenExtensions.Tween(getter, setter, to, duration)
```
- **Getter**: a delegate that returns the value of the property to tween. Can be written as a lambda like this: `() => myValue`
where `myValue` is the name of the property to tween.
- **Setter**: a delegate that sets the value of the property to tween. Can be written as a lambda like this: `x => myValue = x`
where `myValue` is the name of the property to tween.
- **To**: the end value to reach.
- **Duration**: the duration of the tween in seconds.
- **Validation** (optional): a delegate that every time the tween updates, checks if it should be running. Can be written as a lambda like this: `() => shouldKeepRunning`
where `shouldKeepRunning` is a boolean.
```csharp
// For default C# values
GTween tween = GTweenExtensions.Tween(
() => Target.SomeFloat, // Getter
x => Target.SomeFloat = x, // Setter
100f, // To
1 // Duration
);
```
### Tweens context
Tweens require a system that updates them every frame. In GTweens, this system is referred to as a `GTweensContext`.
Essentially, `GTweensContext` is a class that maintains a list of active tweens and advances their progress collectively when the Tick method is called.
To set a GTween in motion, it needs to be initiated through the `Play` method provided by the `GTweensContext`.
Here's a practical example of how to implement this concept within an application:
```csharp
class MyApplication
{
// We need a single instance of a GTweensContext
readonly GTweensContext _gTweensContext = new();
void UpdateApplication(float frameDeltaTime)
{
// With out aplication update, we tick the context with the frame delta time
_gTweensContext.Tick(frameDeltaTime)
}
void PlaySomeTween()
{
// We create a tween
GTween tween = GTweenExtensions.Tween(
() => Target.SomeFloat, // Getter
x => Target.SomeFloat = x, // Setter
100f, // To
1 // Duration
);
// We play the tween with the context
_gTweensContext.Play(tween);
}
}
```
In this example:
- We establish a single instance of GTweensContext, _gTweensContext, within the MyApplication class.
- The UpdateApplication function is responsible for advancing the tweens within the context using the provided frameDeltaTime as the time increment.
- To initiate a new tween, we use the GTweenExtensions.Tween method, specifying the getter, setter, target value, and duration.
- Finally, we play the tween by adding it to the context using _gTweensContext.Play(tween).
This approach allows for the management and synchronization of tweens within the application using a GTweensContext.
### Sequences
Sequences are a combination of tweens that get animated as a group.
Sequences can be contained inside other sequences without any limit to the depth of the hierarchy.
To create sequences, you need to use the helper `GTweenSequenceBuilder`.
- First you call to start creating a new sequence `New()`.
- Next you `Append()` or `Join()` any tweens to the sequence.
- **Append**: Adds the given tween to the end of the Sequence. This tween will play after all the previous tweens have finished.
- **Join**: Inserts the given tween at the same time position of the last tween added to the Sequence. This tween will play at the same time as the previous tween.
- Finally you call `Build()` to get the generated sequence Tween.
```csharp
GTween tween = GTweenSequenceBuilder.New()
.Append(SomeTween)
.Join(SomeOtherTween)
.Append(SomeOtherOtherTween)
.AppendTime(0.5f)
.Append(AnotherTween)
.AppendCallback(() => Console.WriteLine("I'm finished!"))
.Build();
tween.SetEasing(Easing.InOutCubic);
tween.Play();
```
### Tween controls
- **Kill**: kills the tween. This means that the tween will stop playing.
- **Complete**: instantly reaches the final state of the tween, and stops playing.
- **Reset**: sets the tween to its initial state, and stops playing.
- **SetLoops**: sets the amount of times the tween should loop.
- **SetEasing**: sets the easing used by the tween. If the tween is a sequence, the easing will be applied to all child tweens. Set to linear by default.
- **SetTimeScale**: sets the time scale that will be used to tick the tween. Set to 1 by default.
### Tasks
- **AwaitCompleteOrKill**: returns a Task that waits until the tween is killed or completed.

View file

@ -0,0 +1,169 @@
using System;
using GTweens.TweenBehaviours;
using GTweens.Tweens;
namespace GTweens.Builders;
/// <summary>
/// Builder class for creating sequences of tweens.
/// </summary>
public sealed class GTweenSequenceBuilder
{
readonly SequenceTweenBehaviour _sequenceTweenBehaviour;
readonly GTween _gTween;
bool _creatingGroupTween;
GroupTweenBehaviour? _groupTweenBehaviour;
GTweenSequenceBuilder()
{
_sequenceTweenBehaviour = new SequenceTweenBehaviour();
_gTween = new GTween(_sequenceTweenBehaviour);
}
/// <summary>
/// Creates a new instance of the <see cref="GTweenSequenceBuilder"/>.
/// </summary>
/// <returns>A new instance of the builder.</returns>
public static GTweenSequenceBuilder New()
{
return new GTweenSequenceBuilder();
}
/// <summary>
/// Adds the given tween to the end of the Sequence. This tween will play after all the previous tweens have finished.
/// </summary>
/// <param name="gTween">The GTween to append to the sequence.</param>
/// <returns>The current instance of the builder.</returns>
public GTweenSequenceBuilder Append(GTween gTween)
{
_creatingGroupTween = false;
_sequenceTweenBehaviour.Add(gTween);
return this;
}
/// <summary>
/// Inserts the given tween at the same time position of the last tween added to the Sequence.
/// This tween will play at the same time as the previous tween.
/// </summary>
/// <param name="gTween">The GTween to join with the sequence.</param>
/// <returns>The current instance of the builder.</returns>
public GTweenSequenceBuilder Join(GTween gTween)
{
if (_creatingGroupTween)
{
_groupTweenBehaviour!.Add(gTween);
return this;
}
_creatingGroupTween = true;
_groupTweenBehaviour = new GroupTweenBehaviour();
if (_sequenceTweenBehaviour.Tweens.Count > 0)
{
GTween previousTween = _sequenceTweenBehaviour.Tweens[^1];
_sequenceTweenBehaviour.Remove(previousTween);
_groupTweenBehaviour.Add(previousTween);
}
_groupTweenBehaviour.Add(gTween);
_sequenceTweenBehaviour.Add(new GTween(_groupTweenBehaviour));
return this;
}
/// <summary>
/// Appends a callback action to the end of the sequence.
/// </summary>
/// <param name="callback">The callback action to append.</param>
/// <param name="callIfCompletingInstantly">Whether to call the callback if the tween is asked to complete instantly.</param>
/// <returns>The current instance of the builder.</returns>
public GTweenSequenceBuilder AppendCallback(Action callback, bool callIfCompletingInstantly = true)
{
CallbackTweenBehaviour callbackTweenBehaviour = new(callback, callIfCompletingInstantly);
Append(new GTween(callbackTweenBehaviour));
return this;
}
/// <summary>
/// Inserts the given callback at the same time position of the last tween added to the Sequence.
/// This tween will play at the same time as the previous tween.
/// </summary>
/// <param name="callback">The callback action to append.</param>
/// <param name="callIfCompletingInstantly">Whether to call the callback if the tween is asked to complete instantly.</param>
/// <returns>The current instance of the builder.</returns>
public GTweenSequenceBuilder JoinCallback(Action callback, bool callIfCompletingInstantly = true)
{
CallbackTweenBehaviour callbackTweenBehaviour = new(callback, callIfCompletingInstantly);
Join(new GTween(callbackTweenBehaviour));
return this;
}
/// <summary>
/// Appends a time delay to the end of the sequence.
/// </summary>
/// <param name="timeSeconds">The duration of the time delay in seconds.</param>
/// <returns>The current instance of the builder.</returns>
public GTweenSequenceBuilder AppendTime(float timeSeconds)
{
WaitTimeTweenBehaviour timeTweenBehaviour = new(timeSeconds);
Append(new GTween(timeTweenBehaviour));
return this;
}
/// <summary>
/// Inserts the given time delay at the same time position of the last tween added to the Sequence.
/// This tween will play at the same time as the previous tween.
/// </summary>
/// <param name="timeSeconds">The duration of the time delay in seconds.</param>
/// <returns>The current instance of the builder.</returns>
public GTweenSequenceBuilder JoinTime(float timeSeconds)
{
WaitTimeTweenBehaviour timeTweenBehaviour = new(timeSeconds);
Join(new GTween(timeTweenBehaviour));
return this;
}
/// <summary>
/// Provides a new GTweenSequenceBuilder for building a sequence, and then adds it to the end of the sequence.
/// </summary>
/// <param name="createSequence">An action that defines the nested sequence using a new GTweenSequenceBuilder.</param>
/// <returns>The current instance of the builder.</returns>
public GTweenSequenceBuilder AppendSequence(Action<GTweenSequenceBuilder> createSequence)
{
GTweenSequenceBuilder sequenceBuilder = New();
createSequence.Invoke(sequenceBuilder);
Append(sequenceBuilder.Build());
return this;
}
/// <summary>
/// Provides a new GTweenSequenceBuilder for building a sequence, and then inserts it
/// at the same time position of the last tween added to the Sequence.
/// </summary>
/// <param name="createSequence">An action that defines the nested sequence using a new GTweenSequenceBuilder.</param>
/// <returns>The current instance of the builder.</returns>
public GTweenSequenceBuilder JoinSequence(Action<GTweenSequenceBuilder> createSequence)
{
GTweenSequenceBuilder sequenceBuilder = New();
createSequence.Invoke(sequenceBuilder);
Join(sequenceBuilder.Build());
return this;
}
/// <summary>
/// Builds and returns the final GTween representing the sequence.
/// </summary>
/// <returns>The GTween representing the built sequence.</returns>
public GTween Build() => _gTween;
}

View file

@ -0,0 +1 @@
uid://bt2o7k0sblp2r

View file

@ -0,0 +1,114 @@
using System.Collections.Generic;
using System.Diagnostics;
using GTweens.Tweens;
namespace GTweens.Contexts
{
/// <summary>
/// Manages and updates a collection of GTweens.
/// </summary>
public sealed class GTweensContext
{
/// <summary>
/// Gets or sets the time scale at which the tweens should play.
/// </summary>
public float TimeScale { get; set; } = 1f;
/// <summary>
/// Gets the duration of the last tweens tick in milliseconds.
/// </summary>
public float TickDurationMs { get; private set; }
readonly List<GTween> _aliveTweens = new();
readonly List<GTween> _tweensToAdd = new();
readonly List<GTween> _tweensToRemove = new();
readonly Stopwatch _updateStopwatch = new();
/// <summary>
/// Plays a GTween within the context.
/// </summary>
/// <param name="gTween">The GTween to play.</param>
public void Play(GTween gTween)
{
if(gTween.IsNested)
{
return;
}
if(gTween.IsAlive)
{
TryStartTween(gTween);
return;
}
gTween.IsAlive = true;
_tweensToAdd.Add(gTween);
TryStartTween(gTween);
}
/// <summary>
/// Updates the context and all managed tweens.
/// </summary>
/// <param name="deltaTime">The elapsed time since the last update in seconds.</param>
public void Tick(float deltaTime)
{
float scaledDeltaTime = deltaTime * TimeScale;
_updateStopwatch.Restart();
foreach(GTween tween in _tweensToAdd)
{
_aliveTweens.Add(tween);
}
_tweensToAdd.Clear();
foreach (GTween tween in _aliveTweens)
{
if(tween.IsPlaying)
{
tween.Tick(scaledDeltaTime);
}
else
{
_tweensToRemove.Add(tween);
}
}
foreach(GTween tween in _tweensToRemove)
{
tween.IsAlive = false;
_aliveTweens.Remove(tween);
_tweensToAdd.Remove(tween);
}
_tweensToRemove.Clear();
_updateStopwatch.Stop();
TickDurationMs = _updateStopwatch.ElapsedMilliseconds;
}
/// <summary>
/// Clears all tweens from the context.
/// </summary>
public void Clear()
{
_aliveTweens.Clear();
_tweensToAdd.Clear();
_tweensToRemove.Clear();
}
void TryStartTween(GTween gTween)
{
if (!gTween.IsPlaying)
{
gTween.Start();
}
}
}
}

View file

@ -0,0 +1 @@
uid://cc0xhrqaeyj2a

View file

@ -0,0 +1,6 @@
namespace GTweens.Delegates;
public static class ValidationDelegates
{
public delegate bool Validation();
}

View file

@ -0,0 +1 @@
uid://dgm5i26rfdj1t

View file

@ -0,0 +1,37 @@
namespace GTweens.Easings
{
public enum Easing
{
Linear,
InSine,
OutSine,
InOutSine,
InQuad,
OutQuad,
InOutQuad,
InCubic,
OutCubic,
InOutCubic,
InQuart,
OutQuart,
InOutQuart,
InQuint,
OutQuint,
InOutQuint,
InExpo,
OutExpo,
InOutExpo,
InCirc,
OutCirc,
InOutCirc,
InBack,
OutBack,
InOutBack,
InElastic,
OutElastic,
InOutElastic,
InBounce,
OutBounce,
InOutBounce
}
}

View file

@ -0,0 +1 @@
uid://h86tmt5twtn8

View file

@ -0,0 +1,4 @@
namespace GTweens.Easings
{
public delegate float EasingDelegate(float a, float b, float t);
}

View file

@ -0,0 +1 @@
uid://d3yvf3ck512ig

View file

@ -0,0 +1,239 @@
using System;
namespace GTweens.Easings
{
public static class PresetEasingDelegateFactory
{
const float C1 = 1.70158f;
const float C2 = C1 * 1.525f;
const float C3 = C1 + 1;
const float C4 = (2 * (float)Math.PI) / 3;
const float C5 = (2 * (float)Math.PI) / 4.5f;
const float N1 = 7.5625f;
const float D1 = 2.75f;
public static EasingDelegate GetEaseDelegate(Easing easing)
{
EasingDelegate result;
switch (easing)
{
default:
case Easing.Linear: result = Linear; break;
case Easing.InSine: result = InSine; break;
case Easing.OutSine: result = OutSine; break;
case Easing.InOutSine: result = InOutSine; break;
case Easing.InQuad: result = InQuad; break;
case Easing.OutQuad: result = OutQuad; break;
case Easing.InOutQuad: result = InOutQuad; break;
case Easing.InCubic: result = InCubic; break;
case Easing.OutCubic: result = OutCubic; break;
case Easing.InOutCubic: result = InOutCubic; break;
case Easing.InQuart: result = InQuart; break;
case Easing.OutQuart: result = OutQuart; break;
case Easing.InOutQuart: result = InOutQuart; break;
case Easing.InQuint: result = InQuint; break;
case Easing.OutQuint: result = OutQuint; break;
case Easing.InOutQuint: result = InOutQuint; break;
case Easing.InExpo: result = InExpo; break;
case Easing.OutExpo: result = OutExpo; break;
case Easing.InOutExpo: result = InOutExpo; break;
case Easing.InCirc: result = InCirc; break;
case Easing.OutCirc: result = OutCirc; break;
case Easing.InOutCirc: result = InOutCirc; break;
case Easing.InBack: result = InBack; break;
case Easing.OutBack: result = OutBack; break;
case Easing.InOutBack: result = InOutBack; break;
case Easing.InElastic: result = InElastic; break;
case Easing.OutElastic: result = OutElastic; break;
case Easing.InOutElastic: result = InOutElastic; break;
case Easing.InBounce: result = InBounce; break;
case Easing.OutBounce: result = OutBounce; break;
case Easing.InOutBounce: result = InOutBounce; break;
}
return result;
}
static float Linear(float a, float b, float t)
{
return Lerp(a, b, t);
}
static float InSine(float a, float b, float t)
{
return Lerp(a, b, 1 - (float)Math.Cos((t * (float)Math.PI) / 2f));
}
static float OutSine(float a, float b, float t)
{
return Lerp(a, b, (float)Math.Sin((t * (float)Math.PI) / 2f));
}
static float InOutSine(float a, float b, float t)
{
return Lerp(a, b, -((float)Math.Cos(t * (float)Math.PI) - 1) / 2f);
}
static float InQuad(float a, float b, float t)
{
return Lerp(a, b, t * t);
}
static float OutQuad(float a, float b, float t)
{
return Lerp(a, b, 1 - (1 - t) * (1 - t));
}
static float InOutQuad(float a, float b, float t)
{
return Lerp(a, b, t < 0.5f ? 2 * t * t : 1 - (float)Math.Pow(-2 * t + 2, 2) / 2);
}
static float InCubic(float a, float b, float t)
{
return Lerp(a, b, t * t * t);
}
static float OutCubic(float a, float b, float t)
{
return Lerp(a, b, 1 - (float)Math.Pow(1 - t, 3));
}
static float InOutCubic(float a, float b, float t)
{
return Lerp(a, b, t < 0.5f ? 4 * t * t * t : 1 -(float) Math.Pow(-2 * t + 2, 3) / 2);
}
static float InQuart(float a, float b, float t)
{
return Lerp(a, b, t * t * t * t);
}
static float OutQuart(float a, float b, float t)
{
return Lerp(a, b, 1 - (float)Math.Pow(1 - t, 4));
}
static float InOutQuart(float a, float b, float t)
{
return Lerp(a, b, t < 0.5f ? 8 * t * t * t * t : 1 - (float)Math.Pow(-2 * t + 2, 4) / 2);
}
static float InQuint(float a, float b, float t)
{
return Lerp(a, b, t * t * t * t * t);
}
static float OutQuint(float a, float b, float t)
{
return Lerp(a, b, 1 - (float)Math.Pow(1 - t, 5));
}
static float InOutQuint(float a, float b, float t)
{
return Lerp(a, b, t < 0.5f ? 16 * t * t * t * t * t : 1 - (float)Math.Pow(-2 * t + 2, 5) / 2);
}
static float InExpo(float a, float b, float t)
{
return Lerp(a, b, t == 0 ? 0 : (float)Math.Pow(2, 10 * t - 10));
}
static float OutExpo(float a, float b, float t)
{
return Lerp(a, b, t == 1 ? 1 : 1 - (float)Math.Pow(2, -10 * t));
}
static float InOutExpo(float a, float b, float t)
{
return Lerp(a, b, t == 0 ? 0 : t == 1 ? 1 : t < 0.5f ? (float)Math.Pow(2, 20 * t - 10) / 2 : (2 - (float)Math.Pow(2, -20 * t + 10)) / 2);
}
static float InCirc(float a, float b, float t)
{
return Lerp(a, b, 1 - (float)Math.Sqrt(1 - (float)Math.Pow(t, 2)));
}
static float OutCirc(float a, float b, float t)
{
return Lerp(a, b, (float)Math.Sqrt(1 - (float)Math.Pow(t - 1, 2)));
}
static float InOutCirc(float a, float b, float t)
{
return Lerp(a, b, t < 0.5f ? (1 - (float)Math.Sqrt(1 - (float)Math.Pow(2 * t, 2))) / 2 : (float)(Math.Sqrt(1 - Math.Pow(-2 * t + 2, 2)) + 1) / 2);
}
static float InBack(float a, float b, float t)
{
return Lerp(a, b, C3 * t * t * t - C1 * t * t);
}
static float OutBack(float a, float b, float t)
{
return Lerp(a, b, 1 + C3 * (float)Math.Pow(t - 1, 3) + C1 * (float)Math.Pow(t - 1, 2));
}
static float InOutBack(float a, float b, float t)
{
return Lerp(a, b, t < 0.5f ? ((float)Math.Pow(2 * t, 2) * ((C2 + 1) * 2 * t - C2)) / 2 : ((float)Math.Pow(2 * t - 2, 2) * ((C2 + 1) * (t * 2 - 2) + C2) + 2) / 2);
}
static float InElastic(float a, float b, float t)
{
return Lerp(a, b, t == 0 ? 0 : t == 1 ? 1 : -(float)Math.Pow(2, 10 * t - 10) * (float)Math.Sin((t * 10 - 10.75f) * C4));
}
static float OutElastic(float a, float b, float t)
{
return Lerp(a, b, t == 0 ? 0 : t == 1 ? 1 : (float)Math.Pow(2, -10 * t) * (float)Math.Sin((t * 10 - 0.75f) * C4) + 1);
}
static float InOutElastic(float a, float b, float t)
{
return Lerp(a, b, t == 0 ? 0 : t == 1 ? 1 : t < 0.5f ? -((float)Math.Pow(2, 20 * t - 10) * (float)Math.Sin((20 * t - 11.125f) * C5)) / 2 : ((float)Math.Pow(2, -20 * t + 10) * (float)Math.Sin((20 * t - 11.125f) * C5)) / +1);
}
static float InBounce(float a, float b, float t)
{
return Lerp(a, b, 1 - RawOutBounce(1 - t));
}
static float OutBounce(float a, float b, float t)
{
return Lerp(a, b, RawOutBounce(t));
}
static float InOutBounce(float a, float b, float t)
{
return Lerp(a, b, t < 0.5f ? (1 - RawOutBounce(1 - 2 * t)) / 2 : (1 + RawOutBounce(2 * t - 1)) / 2);
}
static float RawOutBounce(float t)
{
if (t < 1 / D1)
{
return N1 * t * t;
}
if (t < 2 / D1)
{
return N1 * (t -= 1.5f / D1) * t + 0.75f;
}
if (t < 2.5f / D1)
{
return N1 * (t -= 2.25f / D1) * t + 0.9375f;
}
return N1 * (t -= 2.625f / D1) * t + 0.984375f;
}
static float Lerp(float a, float b, float t)
{
return a + (b - a) * t;
}
}
}

View file

@ -0,0 +1 @@
uid://b70204re20wwk

View file

@ -0,0 +1,28 @@
namespace GTweens.Enums
{
/// <summary>
/// Specifies different modes for resetting the values of a tween animation.
/// </summary>
public enum ResetMode
{
/// <summary>
/// Resets the values to their initial state, as they were when the tween animation started.
/// </summary>
InitialValues,
/// <summary>
/// Resets the values by using the difference between initial and final values, effectively incrementing the new initial and final values.
/// </summary>
IncrementalValues,
/// <summary>
/// Each time reverses the animation initial and final values, in a ping-pong fashion.
/// </summary>
PingPong,
/// <summary>
/// Leaves the values unchanged, maintaining their current state.
/// </summary>
CurrentValues,
}
}

View file

@ -0,0 +1 @@
uid://rg4640a2ekfw

View file

@ -0,0 +1,18 @@
namespace GTweens.Enums
{
/// <summary>
/// Specifies different rotation modes for tweening operations.
/// </summary>
public enum RotationMode
{
/// <summary>
/// Rotates objects using the shortest distance between the initial and final angles.
/// </summary>
ShortestDistance,
/// <summary>
/// Rotates objects based on the total angular distance, which may involve multiple rotations.
/// </summary>
TotalDistance,
}
}

View file

@ -0,0 +1 @@
uid://rnjfaov7hxcd

View file

@ -0,0 +1,87 @@
using System;
using System.Numerics;
using GTweens.Enums;
namespace GTweens.Extensions
{
internal static class AngleExtensions
{
public static float Clamp360(float eulerAngles)
{
float result = eulerAngles - (float)Math.Ceiling(eulerAngles / 360f) * 360f;
if (result < 0)
{
result += 360f;
}
return result;
}
public static Vector3 Clamp360(Vector3 eulerAngles)
{
return new Vector3(
Clamp360(eulerAngles.X),
Clamp360(eulerAngles.Y),
Clamp360(eulerAngles.Z)
);
}
/// <summary>
/// Calculates the shortest difference between two given angles.
/// </summary>
public static float DeltaAngle(float current, float target)
{
float difference = target - current;
float delta = MathExtensions.Repeat(difference, 360f);
if (delta > 180.0F)
{
delta -= 360.0F;
}
return delta;
}
public static Vector3 DeltaAngle(Vector3 current, Vector3 target)
{
return new Vector3(
DeltaAngle(current.X, target.X),
DeltaAngle(current.Y, target.Y),
DeltaAngle(current.Z, target.Z)
);
}
public static float GetDestinationAngleDegrees(float origin, float destination, RotationMode mode)
{
switch(mode)
{
case RotationMode.ShortestDistance:
{
float clampedOrigin = Clamp360(origin);
float clampedDestination = Clamp360(destination);
float deltaAngle = DeltaAngle(clampedOrigin, clampedDestination);
return origin + deltaAngle;
}
default:
case RotationMode.TotalDistance:
{
return destination;
}
}
}
public static float GetDestinationAngleRadiants(float origin, float destination, RotationMode mode)
{
return GetDestinationAngleDegrees(
origin * MathExtensions.Rad2Deg,
destination * MathExtensions.Rad2Deg,
mode
) * MathExtensions.Deg2Rad;
}
}
}

View file

@ -0,0 +1 @@
uid://boj44m1nwtj83

View file

@ -0,0 +1,298 @@
using System.Drawing;
using System.Numerics;
using System.Threading;
using System.Threading.Tasks;
using GTweens.Delegates;
using GTweens.TweenBehaviours;
using GTweens.Tweeners;
using GTweens.Tweens;
namespace GTweens.Extensions
{
public static class GTweenExtensions
{
public static GTween Tween(
Tweener<int>.Getter getter,
Tweener<int>.Setter setter,
Tweener<int>.Getter to,
float duration,
ValidationDelegates.Validation validation
)
{
InterpolationTweenBehaviour tweenBehaviour = new InterpolationTweenBehaviour();
tweenBehaviour.Add(new IntTweener(getter, setter, to, duration, validation));
return new GTween(tweenBehaviour);
}
public static GTween Tween(
Tweener<int>.Getter getter,
Tweener<int>.Setter setter,
int to,
float duration,
ValidationDelegates.Validation validation
) => Tween(getter, setter, () => to, duration, validation);
public static GTween Tween(
Tweener<int>.Getter getter,
Tweener<int>.Setter setter,
int to,
float duration
) => Tween(getter, setter, () => to, duration, ValidationExtensions.AlwaysValid);
public static GTween Tween(
Tweener<float>.Getter getter,
Tweener<float>.Setter setter,
Tweener<float>.Getter to,
float duration,
ValidationDelegates.Validation validation
)
{
InterpolationTweenBehaviour tweenBehaviour = new InterpolationTweenBehaviour();
tweenBehaviour.Add(new FloatTweener(getter, setter, to, duration, validation));
return new GTween(tweenBehaviour);
}
public static GTween Tween(
Tweener<float>.Getter getter,
Tweener<float>.Setter setter,
float to,
float duration,
ValidationDelegates.Validation validation
) => Tween(getter, setter, () => to, duration, validation);
public static GTween Tween(
Tweener<float>.Getter getter,
Tweener<float>.Setter setter,
float to,
float duration
) => Tween(getter, setter, to, duration, ValidationExtensions.AlwaysValid);
public static GTween Tween(
Tweener<Vector2>.Getter getter,
Tweener<Vector2>.Setter setter,
Tweener<Vector2>.Getter to,
float duration,
ValidationDelegates.Validation validation
)
{
InterpolationTweenBehaviour tweenBehaviour = new InterpolationTweenBehaviour();
tweenBehaviour.Add(new SystemVector2Tweener(getter, setter, to, duration, validation));
return new GTween(tweenBehaviour);
}
public static GTween Tween(
Tweener<Vector2>.Getter getter,
Tweener<Vector2>.Setter setter,
Vector2 to,
float duration,
ValidationDelegates.Validation validation
) => Tween(getter, setter, () => to, duration, validation);
public static GTween Tween(
Tweener<Vector2>.Getter getter,
Tweener<Vector2>.Setter setter,
Vector2 to,
float duration
) => Tween(getter, setter, to, duration, ValidationExtensions.AlwaysValid);
public static GTween Tween(
Tweener<Vector3>.Getter getter,
Tweener<Vector3>.Setter setter,
Tweener<Vector3>.Getter to,
float duration,
ValidationDelegates.Validation validation
)
{
InterpolationTweenBehaviour tweenBehaviour = new InterpolationTweenBehaviour();
tweenBehaviour.Add(new SystemVector3Tweener(getter, setter, to, duration, validation));
return new GTween(tweenBehaviour);
}
public static GTween Tween(
Tweener<Vector3>.Getter getter,
Tweener<Vector3>.Setter setter,
Vector3 to,
float duration,
ValidationDelegates.Validation validation
) => Tween(getter, setter, () => to, duration, validation);
public static GTween Tween(
Tweener<Vector3>.Getter getter,
Tweener<Vector3>.Setter setter,
Vector3 to,
float duration
) => Tween(getter, setter, to, duration, ValidationExtensions.AlwaysValid);
public static GTween Tween(
Tweener<Vector4>.Getter getter,
Tweener<Vector4>.Setter setter,
Tweener<Vector4>.Getter to,
float duration,
ValidationDelegates.Validation validation
)
{
InterpolationTweenBehaviour tweenBehaviour = new InterpolationTweenBehaviour();
tweenBehaviour.Add(new SystemVector4Tweener(getter, setter, to, duration, validation));
return new GTween(tweenBehaviour);
}
public static GTween Tween(
Tweener<Vector4>.Getter getter,
Tweener<Vector4>.Setter setter,
Vector4 to,
float duration,
ValidationDelegates.Validation validation
) => Tween(getter, setter, () => to, duration, validation);
public static GTween Tween(
Tweener<Vector4>.Getter getter,
Tweener<Vector4>.Setter setter,
Vector4 to,
float duration
) => Tween(getter, setter, to, duration, ValidationExtensions.AlwaysValid);
public static GTween Tween(
Tweener<Color>.Getter getter,
Tweener<Color>.Setter setter,
Tweener<Color>.Getter to,
float duration,
ValidationDelegates.Validation validation
)
{
InterpolationTweenBehaviour tweenBehaviour = new InterpolationTweenBehaviour();
tweenBehaviour.Add(new SystemColorTweener(getter, setter, to, duration, validation));
return new GTween(tweenBehaviour);
}
public static GTween Tween(
Tweener<Color>.Getter getter,
Tweener<Color>.Setter setter,
Color to,
float duration,
ValidationDelegates.Validation validation
) => Tween(getter, setter, () => to, duration, validation);
public static GTween Tween(
Tweener<Color>.Getter getter,
Tweener<Color>.Setter setter,
Color to,
float duration
) => Tween(getter, setter, to, duration, ValidationExtensions.AlwaysValid);
public static GTween Tween(
Tweener<Quaternion>.Getter getter,
Tweener<Quaternion>.Setter setter,
Tweener<Quaternion>.Getter to,
float duration,
ValidationDelegates.Validation validation
)
{
InterpolationTweenBehaviour tweenBehaviour = new InterpolationTweenBehaviour();
tweenBehaviour.Add(new SystemQuaternionTweener(getter, setter, to, duration, validation));
return new GTween(tweenBehaviour);
}
public static GTween Tween(
Tweener<Quaternion>.Getter getter,
Tweener<Quaternion>.Setter setter,
Quaternion to,
float duration,
ValidationDelegates.Validation validation
) => Tween(getter, setter, () => to, duration, validation);
public static GTween Tween(
Tweener<Quaternion>.Getter getter,
Tweener<Quaternion>.Setter setter,
Quaternion to,
float duration
) => Tween(getter, setter, to, duration, ValidationExtensions.AlwaysValid);
public static GTween Tween(
int from,
int to,
Tweener<int>.Setter setter,
float duration
)
{
return Tween(
() => from,
setter,
to,
duration,
ValidationExtensions.AlwaysValid
);
}
public static GTween Tween(
float from,
float to,
Tweener<float>.Setter setter,
float duration
)
{
return Tween(
() => from,
setter,
to,
duration,
ValidationExtensions.AlwaysValid
);
}
public static GTween TweenTimeScale(this GTween target, float to, float duration)
{
return Tween(
() => target.TimeScale,
current => target.SetTimeScale(current),
to,
duration
);
}
public static bool IsPlayingOrCompleted(this GTween gTween)
{
return gTween.IsPlaying || gTween.IsCompleted;
}
public static bool IsPlayingOrCompletedOrNested(this GTween gTween)
{
return gTween.IsPlaying || gTween.IsCompleted || gTween.IsNested;
}
/// <summary>
/// Asynchronously waits for the completion of a GTween animation or cancellation through a CancellationToken.
/// </summary>
/// <param name="gTween">The GTween instance to monitor for completion.</param>
/// <param name="cancellationToken">The CancellationToken that can be used to cancel the operation.</param>
/// <returns>
/// A Task that represents the asynchronous operation. The Task completes when the GTween animation is complete,
/// or when the CancellationToken is signaled for cancellation.
/// </returns>
public static Task AwaitCompleteOrKill(this GTween gTween, CancellationToken cancellationToken)
{
TaskCompletionSource taskCompletionSource = new();
if (!gTween.IsPlaying)
{
return Task.CompletedTask;
}
if (cancellationToken.IsCancellationRequested)
{
return Task.CompletedTask;
}
void OnCompleteOrKill()
{
gTween.OnCompleteOrKillAction -= OnCompleteOrKill;
taskCompletionSource.TrySetResult();
}
cancellationToken.Register(OnCompleteOrKill);
gTween.OnCompleteOrKill(OnCompleteOrKill);
return taskCompletionSource.Task;
}
}
}

View file

@ -0,0 +1 @@
uid://dei0hda724u2a

View file

@ -0,0 +1,27 @@
using System;
namespace GTweens.Extensions;
public static class MathExtensions
{
public const float Deg2Rad = 0.01745329f;
public const float Rad2Deg = 57.29578f;
public static float SafeDivide(float v1, float v2)
{
if (v2 == 0f)
{
return 0f;
}
return v1 / v2;
}
/// <summary>
/// Loops the value t, so that it is never larger than length and never smaller than 0.
/// </summary>
public static float Repeat(float t, float length)
{
return Math.Clamp(t - (float)Math.Floor(t / length) * length, 0.0f, length);
}
}

View file

@ -0,0 +1 @@
uid://bouwnkbl68u6a

View file

@ -0,0 +1,17 @@
using System.Drawing;
namespace GTweens.Extensions
{
public static class SystemColorExtensions
{
public static Color FromRgba(float r, float g, float b, float a)
{
return Color.FromArgb(
(int)(a * 255f),
(int)(r * 255f),
(int)(g * 255f),
(int)(b * 255f)
);
}
}
}

View file

@ -0,0 +1 @@
uid://cftquavd2ss24

View file

@ -0,0 +1,8 @@
using GTweens.Delegates;
namespace GTweens.Extensions;
public static class ValidationExtensions
{
public static readonly ValidationDelegates.Validation AlwaysValid = () => true;
}

View file

@ -0,0 +1 @@
uid://yer2h7qavcpt

View file

@ -0,0 +1,34 @@
using GTweens.Easings;
namespace GTweens.Interpolators
{
public sealed class FloatInterpolator : IInterpolator<float>
{
public static readonly FloatInterpolator Instance = new();
FloatInterpolator()
{
}
public float Evaluate(
float initialValue,
float finalValue,
float time,
EasingDelegate easingDelegate
)
{
return easingDelegate(initialValue, finalValue, time);
}
public float Subtract(float initialValue, float finalValue)
{
return finalValue - initialValue;
}
public float Add(float initialValue, float finalValue)
{
return finalValue + initialValue;
}
}
}

View file

@ -0,0 +1 @@
uid://b3m1wga6bh0qn

View file

@ -0,0 +1,37 @@
using GTweens.Easings;
namespace GTweens.Interpolators
{
/// <summary>
/// Represents an interpolator for working with transitions between two values of type <typeparamref name="T"/>.
/// </summary>
/// <typeparam name="T">The type of values to interpolate.</typeparam>
public interface IInterpolator<T>
{
/// <summary>
/// Evaluates the intermediate value between the initial and final values based on the specified time and easing function.
/// </summary>
/// <param name="initialValue">The initial value.</param>
/// <param name="finalValue">The final value.</param>
/// <param name="time">The interpolation time (usually between 0 and 1).</param>
/// <param name="easingFunction">The easing function to apply during interpolation.</param>
/// <returns>The interpolated value between <paramref name="initialValue"/> and <paramref name="finalValue"/>.</returns>
T Evaluate(T initialValue, T finalValue, float time, EasingDelegate easingFunction);
/// <summary>
/// Subtracts two values of type <typeparamref name="T"/>.
/// </summary>
/// <param name="initialValue">The initial value.</param>
/// <param name="finalValue">The final value.</param>
/// <returns>The result of subtracting <paramref name="finalValue"/> from <paramref name="initialValue"/>.</returns>
T Subtract(T initialValue, T finalValue);
/// <summary>
/// Adds two values of type <typeparamref name="T"/>.
/// </summary>
/// <param name="initialValue">The initial value.</param>
/// <param name="finalValue">The final value.</param>
/// <returns>The result of adding <paramref name="finalValue"/> to <paramref name="initialValue"/>.</returns>
T Add(T initialValue, T finalValue);
}
}

View file

@ -0,0 +1 @@
uid://83qvtsiku48u

View file

@ -0,0 +1,34 @@
using GTweens.Easings;
namespace GTweens.Interpolators
{
public sealed class IntInterpolator : IInterpolator<int>
{
public static readonly IntInterpolator Instance = new();
IntInterpolator()
{
}
public int Evaluate(
int initialValue,
int finalValue,
float time,
EasingDelegate easingDelegate
)
{
return (int)easingDelegate(initialValue, finalValue, time);
}
public int Subtract(int initialValue, int finalValue)
{
return finalValue - initialValue;
}
public int Add(int initialValue, int finalValue)
{
return finalValue + initialValue;
}
}
}

View file

@ -0,0 +1 @@
uid://e1vtsq83j4g6

View file

@ -0,0 +1,51 @@
using System.Drawing;
using GTweens.Easings;
using GTweens.Extensions;
namespace GTweens.Interpolators
{
public sealed class SystemColorInterpolator : IInterpolator<Color>
{
public static readonly SystemColorInterpolator Instance = new();
SystemColorInterpolator()
{
}
public Color Evaluate(
Color initialValue,
Color finalValue,
float time,
EasingDelegate easingDelegate
)
{
return SystemColorExtensions.FromRgba(
easingDelegate!(initialValue.A, finalValue.A, time),
easingDelegate(initialValue.R, finalValue.R, time),
easingDelegate(initialValue.G, finalValue.G, time),
easingDelegate(initialValue.B, finalValue.B, time)
);
}
public Color Subtract(Color initialValue, Color finalValue)
{
return Color.FromArgb(
finalValue.A - initialValue.A,
finalValue.R - initialValue.R,
finalValue.G - initialValue.G,
finalValue.B - initialValue.B
);
}
public Color Add(Color initialValue, Color finalValue)
{
return Color.FromArgb(
finalValue.A + initialValue.A,
finalValue.R + initialValue.R,
finalValue.G + initialValue.G,
finalValue.B + initialValue.B
);
}
}
}

View file

@ -0,0 +1 @@
uid://bthivyns1lr7a

View file

@ -0,0 +1,37 @@
using System.Numerics;
using GTweens.Easings;
namespace GTweens.Interpolators
{
public sealed class SystemQuaternionInterpolator : IInterpolator<Quaternion>
{
public static readonly SystemQuaternionInterpolator Instance = new();
SystemQuaternionInterpolator()
{
}
public Quaternion Evaluate(
Quaternion initialValue,
Quaternion finalValue,
float time,
EasingDelegate easingDelegate
)
{
float curveTime = easingDelegate(0f, 1f, time);
return Quaternion.Slerp(initialValue, finalValue, curveTime);
}
public Quaternion Subtract(Quaternion initialValue, Quaternion finalValue)
{
return Quaternion.Inverse(initialValue) * finalValue;
}
public Quaternion Add(Quaternion initialValue, Quaternion finalValue)
{
return initialValue * finalValue;
}
}
}

View file

@ -0,0 +1 @@
uid://d2onw3tx1lfu7

View file

@ -0,0 +1,38 @@
using System.Numerics;
using GTweens.Easings;
namespace GTweens.Interpolators
{
public sealed class SystemVector2Interpolator : IInterpolator<Vector2>
{
public static readonly SystemVector2Interpolator Instance = new();
SystemVector2Interpolator()
{
}
public Vector2 Evaluate(
Vector2 initialValue,
Vector2 finalValue,
float time,
EasingDelegate easingDelegate
)
{
return new Vector2(
easingDelegate(initialValue.X, finalValue.X, time),
easingDelegate(initialValue.Y, finalValue.Y, time)
);
}
public Vector2 Subtract(Vector2 initialValue, Vector2 finalValue)
{
return finalValue - initialValue;
}
public Vector2 Add(Vector2 initialValue, Vector2 finalValue)
{
return finalValue + initialValue;
}
}
}

View file

@ -0,0 +1 @@
uid://dvtde4b3gjv32

View file

@ -0,0 +1,39 @@
using System.Numerics;
using GTweens.Easings;
namespace GTweens.Interpolators
{
public sealed class SystemVector3Interpolator : IInterpolator<Vector3>
{
public static readonly SystemVector3Interpolator Instance = new();
SystemVector3Interpolator()
{
}
public Vector3 Evaluate(
Vector3 initialValue,
Vector3 finalValue,
float time,
EasingDelegate easingDelegate
)
{
return new Vector3(
easingDelegate(initialValue.X, finalValue.X, time),
easingDelegate(initialValue.Y, finalValue.Y, time),
easingDelegate(initialValue.Z, finalValue.Z, time)
);
}
public Vector3 Subtract(Vector3 initialValue, Vector3 finalValue)
{
return finalValue - initialValue;
}
public Vector3 Add(Vector3 initialValue, Vector3 finalValue)
{
return finalValue + initialValue;
}
}
}

View file

@ -0,0 +1 @@
uid://cdm8j104f7hgo

View file

@ -0,0 +1,54 @@
// using Juce.Tweening.Easing;
// using Juce.Tweening.Utils;
// using System;
// using System.Numerics;
//
// namespace Juce.Tweening.Interpolators
// {
// public class SystemVector3RotationInterpolator : IInterpolator<Vector3>
// {
// readonly RotationMode rotationMode;
//
// public SystemVector3RotationInterpolator(RotationMode rotationMode)
// {
// this.rotationMode = rotationMode;
// }
//
// public Vector3 Evaluate(
// Vector3 initialValue,
// Vector3 finalValue,
// float time,
// EaseDelegate easeFunction
// )
// {
// if (easeFunction == null)
// {
// throw new ArgumentNullException($"Tried to Evaluate with a " +
// $"null {nameof(EaseDelegate)} on {nameof(SystemVector3Interpolator)}");
// }
//
// if (rotationMode == RotationMode.Fast)
// {
// Vector3 deltaAngle = AngleUtils.DeltaAngle(initialValue, finalValue);
//
// finalValue = initialValue + deltaAngle;
// }
//
// return new Vector3(
// easeFunction(initialValue.X, finalValue.X, time),
// easeFunction(initialValue.Y, finalValue.Y, time),
// easeFunction(initialValue.Z, finalValue.Z, time)
// );
// }
//
// public Vector3 Subtract(Vector3 initialValue, Vector3 finalValue)
// {
// return finalValue - initialValue;
// }
//
// public Vector3 Add(Vector3 firstValue, Vector3 secondValue)
// {
// return secondValue + firstValue;
// }
// }
// }

View file

@ -0,0 +1 @@
uid://c8hpkxetb6uyg

View file

@ -0,0 +1,40 @@
using System.Numerics;
using GTweens.Easings;
namespace GTweens.Interpolators
{
public sealed class SystemVector4Interpolator : IInterpolator<Vector4>
{
public static readonly SystemVector4Interpolator Instance = new();
SystemVector4Interpolator()
{
}
public Vector4 Evaluate(
Vector4 initialValue,
Vector4 finalValue,
float time,
EasingDelegate easingDelegate
)
{
return new Vector4(
easingDelegate(initialValue.X, finalValue.X, time),
easingDelegate(initialValue.Y, finalValue.Y, time),
easingDelegate(initialValue.Z, finalValue.Z, time),
easingDelegate(initialValue.W, finalValue.W, time)
);
}
public Vector4 Subtract(Vector4 initialValue, Vector4 finalValue)
{
return finalValue - initialValue;
}
public Vector4 Add(Vector4 initialValue, Vector4 finalValue)
{
return finalValue + initialValue;
}
}
}

View file

@ -0,0 +1 @@
uid://cmwi4emxwsy8c

View file

@ -0,0 +1,38 @@
using System;
using GTweens.Enums;
namespace GTweens.TweenBehaviours
{
public sealed class CallbackTweenBehaviour : TweenBehaviour
{
readonly Action _action;
readonly bool _callIfCompletingInstantly;
public CallbackTweenBehaviour(Action action, bool callIfCompletingInstantly)
{
_action = action;
_callIfCompletingInstantly = callIfCompletingInstantly;
}
public override void Start(bool isCompletingInstantly)
{
bool canCall = !isCompletingInstantly || _callIfCompletingInstantly;
if (canCall)
{
_action?.Invoke();
}
MarkFinished();
}
public override void Reset(bool kill, ResetMode loopResetMode)
{
MarkUnfinished();
}
public override float GetDuration() => 0f;
public override float GetElapsed() => 0f;
public override bool GetLoopable() => false;
}
}

View file

@ -0,0 +1 @@
uid://b4nvwfr8t2hvu

View file

@ -0,0 +1,166 @@
using System.Collections.Generic;
using GTweens.Easings;
using GTweens.Enums;
using GTweens.Extensions;
using GTweens.Tweens;
namespace GTweens.TweenBehaviours
{
public sealed class GroupTweenBehaviour : TweenBehaviour
{
public IReadOnlyList<GTween> Tweens => _tweens;
readonly List<GTween> _tweens = new();
readonly List<GTween> _playingTweens = new();
bool _durationCalculated;
float _cachedCalculatedDuration;
public override void Start(bool isCompletingInstantly)
{
StartTweens(isCompletingInstantly);
}
public override void Tick(float deltaTime)
{
for (int i = _playingTweens.Count - 1; i >= 0; --i)
{
GTween gTween = _playingTweens[i];
gTween.Tick(deltaTime);
if (!gTween.IsPlaying)
{
_playingTweens.RemoveAt(i);
}
}
if (_playingTweens.Count == 0)
{
MarkFinished();
}
}
public override void Kill()
{
foreach (GTween tween in _playingTweens)
{
tween.Kill();
}
_playingTweens.Clear();
MarkFinished();
}
public override void Complete()
{
foreach (GTween tween in _playingTweens)
{
if (tween.IsCompleted)
{
continue;
}
if (!tween.IsPlaying)
{
tween.Start(isCompletingInstantly: true);
}
tween.Complete();
}
_playingTweens.Clear();
MarkFinished();
}
public override void Reset(bool kill, ResetMode resetMode)
{
for (int i = _tweens.Count - 1; i >= 0; --i)
{
GTween gTween = _tweens[i];
gTween.Reset(kill, resetMode);
}
MarkUnfinished();
}
public override void SetEasing(EasingDelegate easingFunction)
{
foreach (GTween tween in _tweens)
{
tween.SetEasing(easingFunction);
}
}
public override float GetDuration()
{
if(_durationCalculated)
{
return _cachedCalculatedDuration;
}
_durationCalculated = true;
_cachedCalculatedDuration = 0.0f;
foreach (GTween tween in _tweens)
{
_cachedCalculatedDuration += tween.GetDuration();
}
return _cachedCalculatedDuration;
}
public override float GetElapsed()
{
float totalDuration = 0.0f;
foreach (GTween tween in _tweens)
{
totalDuration += tween.GetElapsed();
}
return totalDuration;
}
public void Add(GTween gTween)
{
if(gTween.IsPlayingOrCompletedOrNested())
{
return;
}
gTween.IsNested = true;
_tweens.Add(gTween);
_durationCalculated = false;
}
void StartTweens(bool isCompletingInstantly)
{
_playingTweens.Clear();
_playingTweens.AddRange(_tweens);
for (int i = _playingTweens.Count - 1; i >= 0; --i)
{
GTween gTween = _playingTweens[i];
gTween.Start(isCompletingInstantly);
if (!gTween.IsPlaying)
{
_playingTweens.RemoveAt(i);
}
}
if (_playingTweens.Count == 0)
{
MarkFinished();
}
}
}
}

View file

@ -0,0 +1 @@
uid://b0sfk7ps1fav6

View file

@ -0,0 +1,22 @@
using GTweens.Easings;
using GTweens.Enums;
namespace GTweens.TweenBehaviours;
public interface ITweenBehaviour
{
float GetDuration();
float GetElapsed();
float GetRemaining();
bool GetLoopable();
void Start(bool isCompletingInstantly);
void Tick(float deltaTime);
void Kill();
void Complete();
void Reset(bool kill, ResetMode loopResetMode);
void SetEasing(EasingDelegate easingFunction);
bool GetFinished();
}

View file

@ -0,0 +1 @@
uid://ceieq47mwyq5q

View file

@ -0,0 +1,173 @@
using System;
using System.Collections.Generic;
using GTweens.Easings;
using GTweens.Enums;
using GTweens.Tweeners;
namespace GTweens.TweenBehaviours
{
public sealed class InterpolationTweenBehaviour : TweenBehaviour
{
readonly List<ITweener> _tweeners = new();
readonly List<ITweener> _playingTweeners = new();
bool _durationCalculated;
float _cachedCalculatedDuration;
public override void Start(bool isCompletingInstantly)
{
StartTweeners();
}
public override void Tick(float deltaTime)
{
for (int i = _playingTweeners.Count - 1; i >= 0; --i)
{
ITweener tweener = _playingTweeners[i];
tweener.Tick(deltaTime);
if (!tweener.IsPlaying)
{
_playingTweeners.RemoveAt(i);
}
}
if (_playingTweeners.Count == 0)
{
MarkFinished();
}
}
public override void Kill()
{
foreach (ITweener tweener in _playingTweeners)
{
tweener.Kill();
}
_playingTweeners.Clear();
MarkFinished();
}
public override void Complete()
{
foreach (ITweener tweener in _playingTweeners)
{
if (!tweener.IsPlaying)
{
continue;
}
tweener.Complete();
}
_playingTweeners.Clear();
MarkFinished();
}
public override void Reset(bool kill, ResetMode resetMode)
{
for (int i = _tweeners.Count - 1; i >= 0; --i)
{
ITweener tweener = _tweeners[i];
tweener.Reset(resetMode);
}
MarkUnfinished();
}
public override void SetEasing(EasingDelegate easingFunction)
{
foreach (ITweener tweener in _tweeners)
{
tweener.SetEasing(easingFunction);
}
}
public override float GetDuration()
{
if(_durationCalculated)
{
return _cachedCalculatedDuration;
}
_durationCalculated = true;
_cachedCalculatedDuration = 0.0f;
foreach (ITweener tweener in _tweeners)
{
_cachedCalculatedDuration += tweener.Duration;
}
return _cachedCalculatedDuration;
}
public override float GetElapsed()
{
float totalElapsed = 0.0f;
foreach (ITweener tweener in _tweeners)
{
totalElapsed += tweener.Elapsed;
}
return totalElapsed;
}
public void Add(ITweener tweener)
{
if (tweener == null)
{
throw new ArgumentNullException(
$"Tried to {nameof(Add)} a null {nameof(ITweener)} on {nameof(InterpolationTweenBehaviour)}"
);
}
if (tweener.IsPlaying)
{
throw new ArgumentNullException(
$"Tried to {nameof(Add)} a {nameof(ITweener)} on {nameof(InterpolationTweenBehaviour)} but it was already playing"
);
}
if (_tweeners.Contains(tweener))
{
throw new ArgumentNullException(
$"Tried to {nameof(Add)} a {nameof(ITweener)} on {nameof(InterpolationTweenBehaviour)} but it was already added"
);
}
_tweeners.Add(tweener);
_durationCalculated = false;
}
void StartTweeners()
{
_playingTweeners.Clear();
_playingTweeners.AddRange(_tweeners);
for (int i = _playingTweeners.Count - 1; i >= 0; --i)
{
ITweener tweener = _playingTweeners[i];
tweener.Start();
if (!tweener.IsPlaying)
{
_playingTweeners.RemoveAt(i);
}
}
if (_playingTweeners.Count == 0)
{
MarkFinished();
}
}
}
}

View file

@ -0,0 +1 @@
uid://cx1regaakoijq

View file

@ -0,0 +1,189 @@
using System.Collections.Generic;
using GTweens.Easings;
using GTweens.Enums;
using GTweens.Extensions;
using GTweens.Tweens;
namespace GTweens.TweenBehaviours
{
public sealed class SequenceTweenBehaviour : TweenBehaviour
{
public IReadOnlyList<GTween> Tweens => _tweens;
readonly List<GTween> _tweens = new();
readonly List<GTween> _playingTweens = new();
bool _durationCalculated;
float _cachedCalculatedDuration;
public override void Start(bool isCompletingInstantly)
{
StartTweens(isCompletingInstantly);
}
public override void Tick(float deltaTime)
{
if (_playingTweens.Count == 0)
{
MarkFinished();
return;
}
GTween gTween = _playingTweens[0];
gTween.Tick(deltaTime);
if (gTween.IsPlaying)
{
return;
}
_playingTweens.RemoveAt(0);
if (_playingTweens.Count > 0)
{
GTween nextGTween = _playingTweens[0];
nextGTween.Start();
}
else
{
Tick(deltaTime);
}
}
public override void Kill()
{
foreach (GTween tween in _playingTweens)
{
tween.Kill();
}
_playingTweens.Clear();
MarkFinished();
}
public override void Complete()
{
foreach (GTween tween in _tweens)
{
if(tween.IsCompleted)
{
continue;
}
if (!tween.IsPlaying)
{
tween.Start(isCompletingInstantly: true);
}
tween.Complete();
}
_playingTweens.Clear();
MarkFinished();
}
public override void Reset(bool kill, ResetMode resetMode)
{
for (int i = _tweens.Count - 1; i >= 0; --i)
{
GTween gTween = _tweens[i];
gTween.Reset(kill, resetMode);
}
MarkUnfinished();
}
public override void SetEasing(EasingDelegate easingFunction)
{
foreach (GTween tween in _tweens)
{
tween.SetEasing(easingFunction);
}
}
public override float GetDuration()
{
if(_durationCalculated)
{
return _cachedCalculatedDuration;
}
_durationCalculated = true;
_cachedCalculatedDuration = 0.0f;
foreach (GTween tween in _tweens)
{
_cachedCalculatedDuration += tween.GetDuration();
}
return _cachedCalculatedDuration;
}
public override float GetElapsed()
{
float totalDuration = 0.0f;
foreach (GTween tween in _tweens)
{
totalDuration += tween.GetElapsed();
}
return totalDuration;
}
public void Add(GTween gTween)
{
if (gTween.IsPlayingOrCompletedOrNested())
{
return;
}
gTween.IsNested = true;
_tweens.Add(gTween);
_durationCalculated = false;
}
public void Remove(GTween gTween)
{
if (gTween.IsPlayingOrCompleted())
{
return;
}
bool found = _tweens.Remove(gTween);
if (!found)
{
return;
}
gTween.IsNested = false;
_durationCalculated = false;
}
void StartTweens(bool isCompletingInstantly)
{
_playingTweens.Clear();
_playingTweens.AddRange(_tweens);
if (_playingTweens.Count > 0)
{
GTween gTween = _playingTweens[0];
gTween.Start(isCompletingInstantly);
}
else
{
MarkFinished();
}
}
}
}

View file

@ -0,0 +1 @@
uid://dm1lb1r6xblco

View file

@ -0,0 +1,34 @@
using System;
using GTweens.Easings;
using GTweens.Enums;
namespace GTweens.TweenBehaviours;
public abstract class TweenBehaviour : ITweenBehaviour
{
bool _finished;
public bool GetFinished() => _finished;
protected void MarkFinished() => _finished = true;
protected void MarkUnfinished() => _finished = false;
public float GetRemaining()
{
float duration = GetDuration();
float elapsed = GetElapsed();
return Math.Max(duration - elapsed, 0f);
}
public abstract float GetDuration();
public abstract float GetElapsed();
public virtual bool GetLoopable() => true;
public virtual void Start(bool isCompletingInstantly) { }
public virtual void Tick(float deltaTime) { }
public virtual void Kill() { }
public virtual void Complete() { }
public virtual void Reset(bool kill, ResetMode loopResetMode) { }
public virtual void SetEasing(EasingDelegate easingFunction) { }
}

View file

@ -0,0 +1 @@
uid://rx0cbwgbajym

View file

@ -0,0 +1,53 @@
using GTweens.Enums;
namespace GTweens.TweenBehaviours
{
public sealed class WaitTimeTweenBehaviour : TweenBehaviour
{
readonly float _durationSeconds;
float _elapsedSeconds;
public WaitTimeTweenBehaviour(float durationSeconds)
{
_durationSeconds = durationSeconds;
}
public override void Start(bool isCompletingInstantly)
{
_elapsedSeconds = 0f;
}
public override void Tick(float deltaTime)
{
_elapsedSeconds += deltaTime;
if (_elapsedSeconds >= _durationSeconds)
{
MarkFinished();
}
}
public override void Complete()
{
_elapsedSeconds = _durationSeconds;
MarkFinished();
}
public override void Reset(bool kill, ResetMode loopResetMode)
{
_elapsedSeconds = 0f;
MarkUnfinished();
}
public override float GetDuration()
{
return _durationSeconds;
}
public override float GetElapsed()
{
return _elapsedSeconds;
}
}
}

View file

@ -0,0 +1 @@
uid://m7stdrq84q6r

View file

@ -0,0 +1,25 @@
using GTweens.Delegates;
using GTweens.Interpolators;
namespace GTweens.Tweeners;
public sealed class FloatTweener : Tweener<float>
{
public FloatTweener(
Getter currentValueGetter,
Setter setter,
Getter to,
float duration,
ValidationDelegates.Validation validation
)
: base(
currentValueGetter,
setter,
to,
duration,
FloatInterpolator.Instance,
validation
)
{
}
}

View file

@ -0,0 +1 @@
uid://bywdapy07yjny

View file

@ -0,0 +1,25 @@
using GTweens.Easings;
using GTweens.Enums;
namespace GTweens.Tweeners
{
public interface ITweener
{
float Duration { get; }
float Elapsed { get; }
float Remaining { get; }
bool IsPlaying { get; }
bool IsCompleted { get; }
bool IsKilled { get; }
bool IsCompletedOrKilled { get; }
void SetEasing(EasingDelegate easingFunction);
void Reset(ResetMode mode);
void Start();
void Tick(float deltaTime);
void Complete();
void Kill();
}
}

View file

@ -0,0 +1 @@
uid://k17rtk6wh5xf

View file

@ -0,0 +1,26 @@
using GTweens.Delegates;
using GTweens.Interpolators;
namespace GTweens.Tweeners
{
public sealed class IntTweener : Tweener<int>
{
internal IntTweener(
Getter currValueGetter,
Setter setter,
Getter to,
float duration,
ValidationDelegates.Validation validation
)
: base(
currValueGetter,
setter,
to,
duration,
IntInterpolator.Instance,
validation
)
{
}
}
}

View file

@ -0,0 +1 @@
uid://ntjjh7jiu8vt

View file

@ -0,0 +1,26 @@
using System.Drawing;
using GTweens.Delegates;
using GTweens.Interpolators;
namespace GTweens.Tweeners
{
public sealed class SystemColorTweener : Tweener<Color>
{
public SystemColorTweener(
Getter currValueGetter,
Setter setter,
Getter to,
float duration,
ValidationDelegates.Validation validation
)
: base(currValueGetter,
setter,
to,
duration,
SystemColorInterpolator.Instance,
validation
)
{
}
}
}

View file

@ -0,0 +1 @@
uid://bugpyjerorwcw

View file

@ -0,0 +1,27 @@
using System.Numerics;
using GTweens.Delegates;
using GTweens.Interpolators;
namespace GTweens.Tweeners
{
public sealed class SystemQuaternionTweener : Tweener<Quaternion>
{
public SystemQuaternionTweener(
Getter currValueGetter,
Setter setter,
Getter to,
float duration,
ValidationDelegates.Validation validation
)
: base(
currValueGetter,
setter,
to,
duration,
SystemQuaternionInterpolator.Instance,
validation
)
{
}
}
}

View file

@ -0,0 +1 @@
uid://cvhxhs2yx2njy

View file

@ -0,0 +1,27 @@
using System.Numerics;
using GTweens.Delegates;
using GTweens.Interpolators;
namespace GTweens.Tweeners
{
public sealed class SystemVector2Tweener : Tweener<Vector2>
{
public SystemVector2Tweener(
Getter currValueGetter,
Setter setter,
Getter to,
float duration,
ValidationDelegates.Validation validation
)
: base(
currValueGetter,
setter,
to,
duration,
SystemVector2Interpolator.Instance,
validation
)
{
}
}
}

View file

@ -0,0 +1 @@
uid://ckm388yjwcuu6

View file

@ -0,0 +1,27 @@
using System.Numerics;
using GTweens.Delegates;
using GTweens.Interpolators;
namespace GTweens.Tweeners
{
public sealed class SystemVector3Tweener : Tweener<Vector3>
{
public SystemVector3Tweener(
Getter currValueGetter,
Setter setter,
Getter to,
float duration,
ValidationDelegates.Validation validation
)
: base(
currValueGetter,
setter,
to,
duration,
SystemVector3Interpolator.Instance,
validation
)
{
}
}
}

View file

@ -0,0 +1 @@
uid://bpptxf58855kt

View file

@ -0,0 +1,27 @@
using System.Numerics;
using GTweens.Delegates;
using GTweens.Interpolators;
namespace GTweens.Tweeners
{
public sealed class SystemVector4Tweener : Tweener<Vector4>
{
public SystemVector4Tweener(
Getter currValueGetter,
Setter setter,
Getter to,
float duration,
ValidationDelegates.Validation validation
)
: base(
currValueGetter,
setter,
to,
duration,
SystemVector4Interpolator.Instance,
validation
)
{
}
}
}

View file

@ -0,0 +1 @@
uid://b4534l80h30dx

View file

@ -0,0 +1,234 @@
using System;
using GTweens.Delegates;
using GTweens.Easings;
using GTweens.Enums;
using GTweens.Extensions;
using GTweens.Interpolators;
namespace GTweens.Tweeners
{
public abstract class Tweener<T> : ITweener
{
public delegate void Setter(T currentValue);
public delegate T Getter();
public bool IsPlaying { get; private set; }
public bool IsCompleted { get; private set; }
public bool IsKilled { get; private set; }
public bool IsCompletedOrKilled => IsCompleted || IsKilled;
public float Duration { get; }
public float Elapsed { get; private set; }
public float Remaining => Math.Max(Duration - Elapsed, 0f);
readonly Getter _getter;
readonly Setter _setter;
readonly Getter _to;
readonly ValidationDelegates.Validation _validation;
readonly IInterpolator<T> _interpolator;
bool _hasFirstTimeValues;
T _firstTimeInitialValue = default!;
T _firstTimeFinalValue = default!;
T _initialValue = default!;
T _finalValue = default!;
T _currentValue = default!;
EasingDelegate _easingFunction = PresetEasingDelegateFactory.GetEaseDelegate(Easing.Linear);
public Tweener(
Getter getter,
Setter setter,
Getter to,
float duration,
IInterpolator<T> interpolator,
ValidationDelegates.Validation validation
)
{
_getter = getter;
_setter = setter;
_to = to;
_interpolator = interpolator;
_validation = validation;
Duration = Math.Max(duration, 0.0f);
}
public void Start()
{
if (IsPlaying)
{
return;
}
IsPlaying = true;
IsCompleted = false;
IsKilled = false;
Elapsed = 0.0f;
bool valid = Validate();
if(!valid)
{
Kill();
return;
}
_initialValue = _getter.Invoke();
GetFirstTimeValues();
CompleteIfInstant();
}
public void Reset(ResetMode mode)
{
bool valid = Validate();
if (!valid)
{
Kill();
return;
}
GetFirstTimeValues();
IsCompleted = false;
IsKilled = false;
Elapsed = 0.0f;
switch (mode)
{
default:
case ResetMode.InitialValues:
{
_setter(_firstTimeInitialValue);
_finalValue = _firstTimeFinalValue;
}
break;
case ResetMode.IncrementalValues:
{
T difference = _interpolator.Subtract(_firstTimeInitialValue, _firstTimeFinalValue);
_finalValue = _interpolator.Add(_currentValue, difference);
}
break;
case ResetMode.PingPong:
{
_finalValue = _initialValue;
}
break;
}
}
public void Tick(float deltaTime)
{
if (!IsPlaying)
{
return;
}
bool valid = Validate();
if (!valid)
{
Kill();
return;
}
Elapsed = Math.Min(Duration, Elapsed + deltaTime);
if (Elapsed < Duration)
{
float timeNormalized = MathExtensions.SafeDivide(Elapsed, Duration);
_currentValue = _interpolator.Evaluate(
_initialValue,
_finalValue,
timeNormalized,
_easingFunction
);
_setter(_currentValue);
}
else
{
Complete();
}
}
public void Complete()
{
bool valid = Validate();
if (!valid)
{
return;
}
GetFirstTimeValues();
T newValue = _interpolator.Evaluate(
_initialValue,
_finalValue,
1.0f,
_easingFunction
);
_setter(newValue);
IsPlaying = false;
IsCompleted = true;
}
public void Kill()
{
IsKilled = true;
IsPlaying = false;
}
public void SetEasing(EasingDelegate easingFunction)
{
_easingFunction = easingFunction;
}
void CompleteIfInstant()
{
if (!IsPlaying)
{
return;
}
bool isInstant = Duration == 0.0f;
if (isInstant)
{
Complete();
}
}
bool Validate()
{
return _validation.Invoke();
}
void GetFirstTimeValues()
{
if (_hasFirstTimeValues)
{
return;
}
_hasFirstTimeValues = true;
_finalValue = _to.Invoke();
_firstTimeInitialValue = _initialValue;
_firstTimeFinalValue = _finalValue;
}
}
}

View file

@ -0,0 +1 @@
uid://cy5dli5pvpgrj

View file

@ -0,0 +1,27 @@
// using Juce.Tweening.Interpolators;
// using UnityEngine;
//
// namespace Juce.Tweening.Tweeners
// {
// public class Vector3RotationTweener : Tweener<Vector3>
// {
// public Vector3RotationTweener(
// Getter currValueGetter,
// Setter setter,
// Getter finalValueGetter,
// RotationMode rotationMode,
// float duration,
// Validation validation
// )
// : base(
// currValueGetter,
// setter,
// finalValueGetter,
// duration,
// new SystemVector3RotationInterpolator(rotationMode),
// validation
// )
// {
// }
// }
// }

View file

@ -0,0 +1 @@
uid://by4baldnaurb8

View file

@ -0,0 +1,423 @@
using System;
using GTweens.Easings;
using GTweens.Enums;
using GTweens.TweenBehaviours;
namespace GTweens.Tweens
{
/// <summary>
/// Represents the core item for building tweening animations.
/// </summary>
public sealed class GTween
{
public event Action? OnStartAction;
public event Action? OnTickAction;
public event Action? OnLoopAction;
public event Action? OnResetAction;
public event Action? OnCompleteAction;
public event Action? OnKillAction;
public event Action? OnCompleteOrKillAction;
public event Action<float>? OnTimeScaleChangedAction;
public ITweenBehaviour Behaviour { get; }
public float TimeScale { get; private set; } = 1;
public float Delay { get; private set; }
public int Loops { get; private set; }
public ResetMode LoopResetMode { get; private set; }
public bool IsNested { get; set; }
public bool IsPlaying { get; private set; }
public bool IsPaused { get; private set; }
public bool IsCompleted { get; private set; }
public bool IsKilled { get; private set; }
public bool IsCompletedOrKilled => IsCompleted || IsKilled;
public bool IsAlive { get; set; }
float _delayRemaining;
int _loopsRemaining;
public GTween(ITweenBehaviour behaviour)
{
Behaviour = behaviour;
}
/// <summary>
/// Starts the tween.
/// </summary>
/// <param name="isCompletingInstantly">Determines if the tween should complete instantly.</param>
public void Start(bool isCompletingInstantly = false)
{
if (IsPlaying)
{
Kill();
}
IsPlaying = true;
IsCompleted = false;
IsKilled = false;
_delayRemaining = Delay;
_loopsRemaining = Loops;
Behaviour.Start(isCompletingInstantly);
OnStartAction?.Invoke();
}
/// <summary>
/// Advances the tween by a given delta time.
/// </summary>
/// <param name="deltaTime">The elapsed time since the last update.</param>
public void Tick(float deltaTime)
{
if (!IsPlaying)
{
return;
}
if (IsPaused)
{
return;
}
float deltaTimeWithTimeScale = TimeScale * deltaTime;
if (_delayRemaining > 0f)
{
_delayRemaining -= deltaTime;
return;
}
Behaviour.Tick(deltaTimeWithTimeScale);
OnTickAction?.Invoke();
bool isFinished = Behaviour.GetFinished();
if (!isFinished)
{
return;
}
bool needsToLoop = _loopsRemaining > 0 && Behaviour.GetLoopable();
if(needsToLoop)
{
Loop(LoopResetMode);
}
else
{
MarkFinished();
}
}
/// <summary>
/// Sets if the tween can continue updating or not. Has effect even if the tween has not startet playing.
/// If you start a paused tween, it will not update until it's unpaused.
/// </summary>
public GTween SetPaused(bool paused)
{
IsPaused = paused;
return this;
}
/// <summary>
/// Instantly reaches the final state of the tween, and stops playing.
/// </summary>
public void Complete()
{
if (!IsPlaying && !IsCompleted)
{
Start(true);
}
Behaviour.Complete();
_loopsRemaining = 0;
MarkFinished();
}
/// <summary>
/// Kills the tween. This means that the tween will stop playing, leaving it at its current state.
/// </summary>
public void Kill()
{
if (!IsPlaying)
{
return;
}
IsPlaying = false;
IsCompleted = false;
IsKilled = true;
Behaviour.Kill();
OnKillAction?.Invoke();
OnCompleteOrKillAction?.Invoke();
}
/// <summary>
/// Resets the tween, optionally killing it and specifying the reset mode.
/// </summary>
/// <param name="kill">Whether to kill the tween.</param>
/// <param name="resetMode">The reset mode to use.</param>
/// <returns>The current GTween instance for method chaining.</returns>
public GTween Reset(bool kill, ResetMode resetMode = ResetMode.InitialValues)
{
if (kill)
{
Kill();
IsPlaying = false;
}
IsCompleted = false;
IsKilled = false;
_delayRemaining = Delay;
Behaviour.Reset(kill, resetMode);
OnResetAction?.Invoke();
return this;
}
/// <summary>
/// Simulates the progress of a GTween animation for a specified duration.
/// </summary>
/// <param name="time">The simulated time in seconds.</param>
/// <returns>The current GTween instance for method chaining.</returns>
public GTween Simulate(float time)
{
if (!IsPlaying)
{
Start();
}
bool loops = Loops > 0;
float simulationTime = loops ?
time % Behaviour.GetDuration() :
Math.Min(time, Behaviour.GetDuration());
float progress = Behaviour.GetElapsed();
while (simulationTime > 0)
{
Tick(simulationTime);
float newProgress = Behaviour.GetElapsed();
float tickElapsed = newProgress - progress;
progress = newProgress;
simulationTime -= tickElapsed;
}
return this;
}
/// <summary>
/// Adds some delay (in seconds) at the begining of the tween.
/// </summary>
public GTween SetDelay(float delaySeconds)
{
Delay = delaySeconds;
return this;
}
/// <summary>
/// Sets the time scale for the tween, affecting its speed.
/// By default time scale is 1.0f. If you decrease this number, the tween
/// will update slower. If you increase it, the tween will update faster.
/// </summary>
/// <param name="timeScale">The time scale to set.</param>
/// <returns>The current GTween instance for method chaining.</returns>
public GTween SetTimeScale(float timeScale)
{
TimeScale = timeScale;
OnTimeScaleChangedAction?.Invoke(timeScale);
return this;
}
/// <summary>
/// Sets the easing function for the tween.
/// </summary>
/// <param name="easingFunction">The custom easing function to use.</param>
/// <returns>The current GTween instance for method chaining.</returns>
public GTween SetEasing(EasingDelegate easingFunction)
{
Behaviour.SetEasing(easingFunction);
return this;
}
/// <summary>
/// Sets the predefined easing function for the tween.
/// </summary>
/// <param name="easing">The predefined easing to use.</param>
/// <returns>The current GTween instance for method chaining.</returns>
public GTween SetEasing(Easing easing)
{
return SetEasing(PresetEasingDelegateFactory.GetEaseDelegate(easing));
}
/// <summary>
/// Sets the number of loops and the reset mode for the tween.
/// </summary>
/// <param name="loops">The number of loops.</param>
/// <param name="resetMode">The reset mode to use when looping.</param>
/// <returns>The current GTween instance for method chaining.</returns>
public GTween SetLoops(int loops, ResetMode resetMode = ResetMode.InitialValues)
{
Loops = Math.Max(loops, 0);
LoopResetMode = resetMode;
return this;
}
/// <summary>
/// Sets the tween to have and almost infinite amount of loops with the specified reset mode.
/// </summary>
/// <param name="resetMode">The reset mode to use when looping.</param>
/// <returns>The current GTween instance for method chaining.</returns>
public GTween SetMaxLoops(ResetMode resetMode = ResetMode.InitialValues)
{
return SetLoops(int.MaxValue, resetMode);
}
/// <summary>
/// Calculates the total duration of the tween.
/// </summary>
public float GetDuration()
{
return Behaviour.GetDuration();
}
/// <summary>
/// Calculates the time elapsed since the tween started playing.
/// </summary>
public float GetElapsed()
{
if(!IsPlaying && !IsCompleted)
{
return 0f;
}
if(!IsPlaying && IsCompleted)
{
return GetDuration();
}
return Behaviour.GetElapsed();
}
/// <summary>
/// Gets the time left remaining on the tween (duration - elapsed).
/// </summary>
public float GetRemaining()
{
if(!IsPlaying && !IsCompleted)
{
return GetDuration();
}
if(!IsPlaying && IsCompleted)
{
return 0f;
}
return Behaviour.GetRemaining();
}
public GTween OnStart(Action action)
{
OnStartAction += action;
return this;
}
public GTween OnTick(Action action)
{
OnTickAction += action;
return this;
}
public GTween OnLoop(Action action)
{
OnLoopAction += action;
return this;
}
public GTween OnReset(Action action)
{
OnResetAction += action;
return this;
}
public GTween OnComplete(Action action)
{
OnCompleteAction += action;
return this;
}
public GTween OnKill(Action action)
{
OnKillAction += action;
return this;
}
public GTween OnCompleteOrKill(Action action)
{
OnCompleteOrKillAction += action;
return this;
}
public GTween OnTimeScaleChanged(Action<float> action)
{
OnTimeScaleChangedAction += action;
return this;
}
void Loop(ResetMode loopResetMode)
{
bool needsToLoop = _loopsRemaining > 0;
if(!needsToLoop || !Behaviour.GetLoopable())
{
return;
}
--_loopsRemaining;
Reset(kill: false, loopResetMode);
IsPlaying = true;
IsCompleted = false;
IsKilled = false;
Behaviour.Start(false);
OnLoopAction?.Invoke();
}
void MarkFinished()
{
if (!IsPlaying)
{
return;
}
IsPlaying = false;
IsCompleted = true;
IsKilled = false;
Behaviour.Complete();
OnCompleteAction?.Invoke();
OnCompleteOrKillAction?.Invoke();
}
}
}

View file

@ -0,0 +1 @@
uid://d2cnyj34v2qq4

View file

@ -0,0 +1,25 @@
using GTweens.Contexts;
namespace GTweensGodot.Contexts;
/// <summary>
/// Represents a context for managing tweens in the Godot environment.
/// </summary>
public class GodotGTweensContext
{
public static readonly GodotGTweensContext Instance = new();
/// <summary>
/// Gets the unpausable context for managing tweens. This context is always running, even when GetTree().Paused
/// is set to true.
/// </summary>
public GTweensContext UnpausableContext { get; } = new();
/// <summary>
/// Gets the pausable context for managing tweens. This context is stops running when GetTree().Paused
/// is set to true.
/// </summary>
public GTweensContext PausableContext { get; } = new();
GodotGTweensContext() { }
}

View file

@ -0,0 +1 @@
uid://di15j01ica1hi

View file

@ -0,0 +1,23 @@
using Godot;
namespace GTweensGodot.Contexts;
public partial class GodotGTweensContextNode : Node
{
public sealed override void _Ready()
{
ProcessMode = ProcessModeEnum.Always;
}
public sealed override void _Process(double delta)
{
float floatDelta = (float)delta;
if (!GetTree().Paused)
{
GodotGTweensContext.Instance.PausableContext.Tick(floatDelta);
}
GodotGTweensContext.Instance.UnpausableContext.Tick(floatDelta);
}
}

View file

@ -0,0 +1 @@
uid://b51ltpwp3fkt0

View file

@ -0,0 +1,56 @@
using Godot;
using GTweens.Enums;
namespace GTweensGodot.Extensions;
public static class AngleExtensions
{
public static Vector3 Clamp360(Vector3 eulerAngles)
{
return new Vector3(
GTweens.Extensions.AngleExtensions.Clamp360(eulerAngles.X),
GTweens.Extensions.AngleExtensions.Clamp360(eulerAngles.Y),
GTweens.Extensions.AngleExtensions.Clamp360(eulerAngles.Z)
);
}
public static Vector3 DeltaAngle(Vector3 current, Vector3 target)
{
return new Vector3(
GTweens.Extensions.AngleExtensions.DeltaAngle(current.X, target.X),
GTweens.Extensions.AngleExtensions.DeltaAngle(current.Y, target.Y),
GTweens.Extensions.AngleExtensions.DeltaAngle(current.Z, target.Z)
);
}
public static Vector3 GetDestinationAngleDegrees(Vector3 origin, Vector3 destination, RotationMode mode)
{
switch (mode)
{
case RotationMode.ShortestDistance:
{
Vector3 clampedOrigin = Clamp360(origin);
Vector3 clampedDestination = Clamp360(destination);
Vector3 deltaAngle = DeltaAngle(clampedOrigin, clampedDestination);
return origin + deltaAngle;
}
default:
case RotationMode.TotalDistance:
{
return destination;
}
}
}
public static Vector3 GetDestinationAngleRadiants(Vector3 origin, Vector3 destination, RotationMode mode)
{
return GetDestinationAngleDegrees(
origin * MathExtensions.Rad2Deg,
destination * MathExtensions.Rad2Deg,
mode
) * MathExtensions.Deg2Rad;
}
}

View file

@ -0,0 +1 @@
uid://ctryd158yesn6

View file

@ -0,0 +1,30 @@
using Godot;
using GTweens.Extensions;
using GTweens.Tweens;
namespace GTweensGodot.Extensions;
public static class AudioStreamPlayer2DExtensions
{
public static GTween TweenVolumeDb(this AudioStreamPlayer2D target, float to, float duration)
{
return GTweenExtensions.Tween(
() => target.VolumeDb,
current => target.VolumeDb = current,
to,
duration,
GodotObjectExtensions.GetGodotObjectValidationFunction(target)
);
}
public static GTween TweenPitchScale(this AudioStreamPlayer2D target, float to, float duration)
{
return GTweenExtensions.Tween(
() => target.PitchScale,
current => target.PitchScale = current,
to,
duration,
GodotObjectExtensions.GetGodotObjectValidationFunction(target)
);
}
}

View file

@ -0,0 +1 @@
uid://ecwl3ubgr054

View file

@ -0,0 +1,52 @@
using Godot;
using GTweens.Extensions;
using GTweens.Tweens;
namespace GTweensGodot.Extensions;
public static class AudioStreamPlayer3DExtensions
{
public static GTween TweenVolumeDb(this AudioStreamPlayer3D target, float to, float duration)
{
return GTweenExtensions.Tween(
() => target.VolumeDb,
current => target.VolumeDb = current,
to,
duration,
GodotObjectExtensions.GetGodotObjectValidationFunction(target)
);
}
public static GTween TweenPitchScale(this AudioStreamPlayer3D target, float to, float duration)
{
return GTweenExtensions.Tween(
() => target.PitchScale,
current => target.PitchScale = current,
to,
duration,
GodotObjectExtensions.GetGodotObjectValidationFunction(target)
);
}
public static GTween TweenAttenuationFilterDb(this AudioStreamPlayer3D target, float to, float duration)
{
return GTweenExtensions.Tween(
() => target.AttenuationFilterDb,
current => target.AttenuationFilterDb = current,
to,
duration,
GodotObjectExtensions.GetGodotObjectValidationFunction(target)
);
}
public static GTween TweenAttenuationFilterCutoffHz(this AudioStreamPlayer3D target, float to, float duration)
{
return GTweenExtensions.Tween(
() => target.AttenuationFilterCutoffHz,
current => target.AttenuationFilterCutoffHz = current,
to,
duration,
GodotObjectExtensions.GetGodotObjectValidationFunction(target)
);
}
}

View file

@ -0,0 +1 @@
uid://b6hmb83ornmiv

View file

@ -0,0 +1,74 @@
using Godot;
using GTweens.Extensions;
using GTweens.Tweens;
namespace GTweensGodot.Extensions;
public static class BaseMaterial3DExtensions
{
public static GTween TweenAlbedoColor(this BaseMaterial3D target, Color to, float duration)
{
return GTweenGodotExtensions.Tween(
() => target.AlbedoColor,
current => target.AlbedoColor = current,
to,
duration,
GodotObjectExtensions.GetGodotObjectValidationFunction(target)
);
}
public static GTween TweenAlbedoColorRgb(this BaseMaterial3D target, Color to, float duration)
{
return GTweenGodotExtensions.Tween(
() => target.AlbedoColor,
current => target.AlbedoColor = new Color(current.R, current.G, current.B, target.AlbedoColor.A),
to,
duration,
GodotObjectExtensions.GetGodotObjectValidationFunction(target)
);
}
public static GTween TweenAlbedoColorAlpha(this BaseMaterial3D target, float to, float duration)
{
return GTweenExtensions.Tween(
() => target.AlbedoColor.A,
current => target.AlbedoColor = new Color(target.AlbedoColor.R, target.AlbedoColor.G, target.AlbedoColor.B, current),
to,
duration,
GodotObjectExtensions.GetGodotObjectValidationFunction(target)
);
}
public static GTween TweenMetallic(this BaseMaterial3D target, float to, float duration)
{
return GTweenExtensions.Tween(
() => target.Metallic,
current => target.Metallic = current,
to,
duration,
GodotObjectExtensions.GetGodotObjectValidationFunction(target)
);
}
public static GTween TweenMetallicSpecular(this BaseMaterial3D target, float to, float duration)
{
return GTweenExtensions.Tween(
() => target.MetallicSpecular,
current => target.MetallicSpecular = current,
to,
duration,
GodotObjectExtensions.GetGodotObjectValidationFunction(target)
);
}
public static GTween TweenRoughness(this BaseMaterial3D target, float to, float duration)
{
return GTweenExtensions.Tween(
() => target.Roughness,
current => target.Roughness = current,
to,
duration,
GodotObjectExtensions.GetGodotObjectValidationFunction(target)
);
}
}

View file

@ -0,0 +1 @@
uid://cbrinkf16qyff

View file

@ -0,0 +1,74 @@
using Godot;
using GTweens.Extensions;
using GTweens.Tweens;
namespace GTweensGodot.Extensions;
public static class Camera2DExtensions
{
public static GTween TweenOffset(this Camera2D target, Vector2 to, float duration)
{
return GTweenGodotExtensions.Tween(
() => target.Offset,
current => target.Offset = current,
to,
duration,
GodotObjectExtensions.GetGodotObjectValidationFunction(target)
);
}
public static GTween TweenOffsetX(this Camera2D target, float to, float duration)
{
return GTweenExtensions.Tween(
() => target.Offset.X,
current => target.Offset = new Vector2(current, target.Offset.Y),
to,
duration,
GodotObjectExtensions.GetGodotObjectValidationFunction(target)
);
}
public static GTween TweenOffsetY(this Camera2D target, float to, float duration)
{
return GTweenExtensions.Tween(
() => target.Offset.Y,
current => target.Offset = new Vector2(target.Offset.X, current),
to,
duration,
GodotObjectExtensions.GetGodotObjectValidationFunction(target)
);
}
public static GTween TweenZoom(this Camera2D target, Vector2 to, float duration)
{
return GTweenGodotExtensions.Tween(
() => target.Zoom,
current => target.Zoom = current,
to,
duration,
GodotObjectExtensions.GetGodotObjectValidationFunction(target)
);
}
public static GTween TweenZoomX(this Camera2D target, float to, float duration)
{
return GTweenExtensions.Tween(
() => target.Zoom.X,
current => target.Zoom = new Vector2(current, target.Zoom.Y),
to,
duration,
GodotObjectExtensions.GetGodotObjectValidationFunction(target)
);
}
public static GTween TweenZoomY(this Camera2D target, float to, float duration)
{
return GTweenExtensions.Tween(
() => target.Zoom.Y,
current => target.Zoom = new Vector2(target.Zoom.X, current),
to,
duration,
GodotObjectExtensions.GetGodotObjectValidationFunction(target)
);
}
}

View file

@ -0,0 +1 @@
uid://rsvu3cctnr2k

View file

@ -0,0 +1,41 @@
using Godot;
using GTweens.Extensions;
using GTweens.Tweens;
namespace GTweensGodot.Extensions;
public static class Camera3DExtensions
{
public static GTween TweenHOffset(this Camera3D target, float to, float duration)
{
return GTweenExtensions.Tween(
() => target.HOffset,
current => target.HOffset = current,
to,
duration,
GodotObjectExtensions.GetGodotObjectValidationFunction(target)
);
}
public static GTween TweenVOffset(this Camera3D target, float to, float duration)
{
return GTweenExtensions.Tween(
() => target.VOffset,
current => target.VOffset = current,
to,
duration,
GodotObjectExtensions.GetGodotObjectValidationFunction(target)
);
}
public static GTween TweenFov(this Camera3D target, float to, float duration)
{
return GTweenExtensions.Tween(
() => target.Fov,
current => target.Fov = current,
to,
duration,
GodotObjectExtensions.GetGodotObjectValidationFunction(target)
);
}
}

View file

@ -0,0 +1 @@
uid://ckmn5xp6nf40u

Some files were not shown because too many files have changed in this diff Show more