diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 00000000..8516b21e
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -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.
diff --git a/GTweensGodot/GTweens/CONTRIBUTING.md b/GTweensGodot/GTweens/CONTRIBUTING.md
new file mode 100644
index 00000000..8516b21e
--- /dev/null
+++ b/GTweensGodot/GTweens/CONTRIBUTING.md
@@ -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.
diff --git a/GTweensGodot/GTweens/LICENSE b/GTweensGodot/GTweens/LICENSE
new file mode 100644
index 00000000..ad4658a9
--- /dev/null
+++ b/GTweensGodot/GTweens/LICENSE
@@ -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.
diff --git a/GTweensGodot/GTweens/README.md b/GTweensGodot/GTweens/README.md
new file mode 100644
index 00000000..a6a5f24e
--- /dev/null
+++ b/GTweensGodot/GTweens/README.md
@@ -0,0 +1,138 @@
+[](https://opensource.org/licenses/MIT)
+[](https://github.com/Guillemsc/GTweens/blob/main/CONTRIBUTING.md)
+[](https://github.com/Guillemsc/GTweens/releases/latest)
+[](https://www.nuget.org/packages/GTweens)
+[](https://www.nuget.org/packages/GTweens)
+[](https://github.com/Guillemsc/GTweens/actions/workflows/tests.yml)
+[](https://twitter.com/6uillem)
+
+
+
+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.
diff --git a/GTweensGodot/GTweens/Source/Builders/GTweenSequenceBuilder.cs b/GTweensGodot/GTweens/Source/Builders/GTweenSequenceBuilder.cs
new file mode 100644
index 00000000..26fff463
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Builders/GTweenSequenceBuilder.cs
@@ -0,0 +1,169 @@
+using System;
+using GTweens.TweenBehaviours;
+using GTweens.Tweens;
+
+namespace GTweens.Builders;
+
+///
+/// Builder class for creating sequences of tweens.
+///
+public sealed class GTweenSequenceBuilder
+{
+ readonly SequenceTweenBehaviour _sequenceTweenBehaviour;
+ readonly GTween _gTween;
+
+ bool _creatingGroupTween;
+ GroupTweenBehaviour? _groupTweenBehaviour;
+
+ GTweenSequenceBuilder()
+ {
+ _sequenceTweenBehaviour = new SequenceTweenBehaviour();
+ _gTween = new GTween(_sequenceTweenBehaviour);
+ }
+
+ ///
+ /// Creates a new instance of the .
+ ///
+ /// A new instance of the builder.
+ public static GTweenSequenceBuilder New()
+ {
+ return new GTweenSequenceBuilder();
+ }
+
+ ///
+ /// Adds the given tween to the end of the Sequence. This tween will play after all the previous tweens have finished.
+ ///
+ /// The GTween to append to the sequence.
+ /// The current instance of the builder.
+ public GTweenSequenceBuilder Append(GTween gTween)
+ {
+ _creatingGroupTween = false;
+
+ _sequenceTweenBehaviour.Add(gTween);
+
+ return this;
+ }
+
+ ///
+ /// 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.
+ ///
+ /// The GTween to join with the sequence.
+ /// The current instance of the builder.
+ 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;
+ }
+
+ ///
+ /// Appends a callback action to the end of the sequence.
+ ///
+ /// The callback action to append.
+ /// Whether to call the callback if the tween is asked to complete instantly.
+ /// The current instance of the builder.
+ public GTweenSequenceBuilder AppendCallback(Action callback, bool callIfCompletingInstantly = true)
+ {
+ CallbackTweenBehaviour callbackTweenBehaviour = new(callback, callIfCompletingInstantly);
+ Append(new GTween(callbackTweenBehaviour));
+
+ return this;
+ }
+
+ ///
+ /// 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.
+ ///
+ /// The callback action to append.
+ /// Whether to call the callback if the tween is asked to complete instantly.
+ /// The current instance of the builder.
+ public GTweenSequenceBuilder JoinCallback(Action callback, bool callIfCompletingInstantly = true)
+ {
+ CallbackTweenBehaviour callbackTweenBehaviour = new(callback, callIfCompletingInstantly);
+ Join(new GTween(callbackTweenBehaviour));
+
+ return this;
+ }
+
+ ///
+ /// Appends a time delay to the end of the sequence.
+ ///
+ /// The duration of the time delay in seconds.
+ /// The current instance of the builder.
+ public GTweenSequenceBuilder AppendTime(float timeSeconds)
+ {
+ WaitTimeTweenBehaviour timeTweenBehaviour = new(timeSeconds);
+ Append(new GTween(timeTweenBehaviour));
+
+ return this;
+ }
+
+ ///
+ /// 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.
+ ///
+ /// The duration of the time delay in seconds.
+ /// The current instance of the builder.
+ public GTweenSequenceBuilder JoinTime(float timeSeconds)
+ {
+ WaitTimeTweenBehaviour timeTweenBehaviour = new(timeSeconds);
+ Join(new GTween(timeTweenBehaviour));
+
+ return this;
+ }
+
+ ///
+ /// Provides a new GTweenSequenceBuilder for building a sequence, and then adds it to the end of the sequence.
+ ///
+ /// An action that defines the nested sequence using a new GTweenSequenceBuilder.
+ /// The current instance of the builder.
+ public GTweenSequenceBuilder AppendSequence(Action createSequence)
+ {
+ GTweenSequenceBuilder sequenceBuilder = New();
+ createSequence.Invoke(sequenceBuilder);
+ Append(sequenceBuilder.Build());
+
+ return this;
+ }
+
+ ///
+ /// 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.
+ ///
+ /// An action that defines the nested sequence using a new GTweenSequenceBuilder.
+ /// The current instance of the builder.
+ public GTweenSequenceBuilder JoinSequence(Action createSequence)
+ {
+ GTweenSequenceBuilder sequenceBuilder = New();
+ createSequence.Invoke(sequenceBuilder);
+ Join(sequenceBuilder.Build());
+
+ return this;
+ }
+
+ ///
+ /// Builds and returns the final GTween representing the sequence.
+ ///
+ /// The GTween representing the built sequence.
+ public GTween Build() => _gTween;
+}
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/Builders/GTweenSequenceBuilder.cs.uid b/GTweensGodot/GTweens/Source/Builders/GTweenSequenceBuilder.cs.uid
new file mode 100644
index 00000000..125feb58
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Builders/GTweenSequenceBuilder.cs.uid
@@ -0,0 +1 @@
+uid://bt2o7k0sblp2r
diff --git a/GTweensGodot/GTweens/Source/Contexts/GTweensContext.cs b/GTweensGodot/GTweens/Source/Contexts/GTweensContext.cs
new file mode 100644
index 00000000..bcebf2ac
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Contexts/GTweensContext.cs
@@ -0,0 +1,114 @@
+using System.Collections.Generic;
+using System.Diagnostics;
+using GTweens.Tweens;
+
+namespace GTweens.Contexts
+{
+ ///
+ /// Manages and updates a collection of GTweens.
+ ///
+ public sealed class GTweensContext
+ {
+ ///
+ /// Gets or sets the time scale at which the tweens should play.
+ ///
+ public float TimeScale { get; set; } = 1f;
+
+ ///
+ /// Gets the duration of the last tweens tick in milliseconds.
+ ///
+ public float TickDurationMs { get; private set; }
+
+ readonly List _aliveTweens = new();
+ readonly List _tweensToAdd = new();
+ readonly List _tweensToRemove = new();
+
+ readonly Stopwatch _updateStopwatch = new();
+
+ ///
+ /// Plays a GTween within the context.
+ ///
+ /// The GTween to play.
+ public void Play(GTween gTween)
+ {
+ if(gTween.IsNested)
+ {
+ return;
+ }
+
+ if(gTween.IsAlive)
+ {
+ TryStartTween(gTween);
+ return;
+ }
+
+ gTween.IsAlive = true;
+
+ _tweensToAdd.Add(gTween);
+
+ TryStartTween(gTween);
+ }
+
+ ///
+ /// Updates the context and all managed tweens.
+ ///
+ /// The elapsed time since the last update in seconds.
+ 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;
+ }
+
+ ///
+ /// Clears all tweens from the context.
+ ///
+ public void Clear()
+ {
+ _aliveTweens.Clear();
+ _tweensToAdd.Clear();
+ _tweensToRemove.Clear();
+ }
+
+ void TryStartTween(GTween gTween)
+ {
+ if (!gTween.IsPlaying)
+ {
+ gTween.Start();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/Contexts/GTweensContext.cs.uid b/GTweensGodot/GTweens/Source/Contexts/GTweensContext.cs.uid
new file mode 100644
index 00000000..e5aef1ab
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Contexts/GTweensContext.cs.uid
@@ -0,0 +1 @@
+uid://cc0xhrqaeyj2a
diff --git a/GTweensGodot/GTweens/Source/Delegates/ValidationDelegates.cs b/GTweensGodot/GTweens/Source/Delegates/ValidationDelegates.cs
new file mode 100644
index 00000000..8d1138fc
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Delegates/ValidationDelegates.cs
@@ -0,0 +1,6 @@
+namespace GTweens.Delegates;
+
+public static class ValidationDelegates
+{
+ public delegate bool Validation();
+}
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/Delegates/ValidationDelegates.cs.uid b/GTweensGodot/GTweens/Source/Delegates/ValidationDelegates.cs.uid
new file mode 100644
index 00000000..abcdbe2b
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Delegates/ValidationDelegates.cs.uid
@@ -0,0 +1 @@
+uid://dgm5i26rfdj1t
diff --git a/GTweensGodot/GTweens/Source/Easings/Easing.cs b/GTweensGodot/GTweens/Source/Easings/Easing.cs
new file mode 100644
index 00000000..08f69263
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Easings/Easing.cs
@@ -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
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/Easings/Easing.cs.uid b/GTweensGodot/GTweens/Source/Easings/Easing.cs.uid
new file mode 100644
index 00000000..f20f3f55
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Easings/Easing.cs.uid
@@ -0,0 +1 @@
+uid://h86tmt5twtn8
diff --git a/GTweensGodot/GTweens/Source/Easings/EasingDelegate.cs b/GTweensGodot/GTweens/Source/Easings/EasingDelegate.cs
new file mode 100644
index 00000000..9e9219e7
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Easings/EasingDelegate.cs
@@ -0,0 +1,4 @@
+namespace GTweens.Easings
+{
+ public delegate float EasingDelegate(float a, float b, float t);
+}
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/Easings/EasingDelegate.cs.uid b/GTweensGodot/GTweens/Source/Easings/EasingDelegate.cs.uid
new file mode 100644
index 00000000..582ea8fe
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Easings/EasingDelegate.cs.uid
@@ -0,0 +1 @@
+uid://d3yvf3ck512ig
diff --git a/GTweensGodot/GTweens/Source/Easings/PresetEasingDelegateFactory.cs b/GTweensGodot/GTweens/Source/Easings/PresetEasingDelegateFactory.cs
new file mode 100644
index 00000000..51d51bfc
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Easings/PresetEasingDelegateFactory.cs
@@ -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;
+ }
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/Easings/PresetEasingDelegateFactory.cs.uid b/GTweensGodot/GTweens/Source/Easings/PresetEasingDelegateFactory.cs.uid
new file mode 100644
index 00000000..fd228e80
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Easings/PresetEasingDelegateFactory.cs.uid
@@ -0,0 +1 @@
+uid://b70204re20wwk
diff --git a/GTweensGodot/GTweens/Source/Enums/ResetMode.cs b/GTweensGodot/GTweens/Source/Enums/ResetMode.cs
new file mode 100644
index 00000000..c78836ba
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Enums/ResetMode.cs
@@ -0,0 +1,28 @@
+namespace GTweens.Enums
+{
+ ///
+ /// Specifies different modes for resetting the values of a tween animation.
+ ///
+ public enum ResetMode
+ {
+ ///
+ /// Resets the values to their initial state, as they were when the tween animation started.
+ ///
+ InitialValues,
+
+ ///
+ /// Resets the values by using the difference between initial and final values, effectively incrementing the new initial and final values.
+ ///
+ IncrementalValues,
+
+ ///
+ /// Each time reverses the animation initial and final values, in a ping-pong fashion.
+ ///
+ PingPong,
+
+ ///
+ /// Leaves the values unchanged, maintaining their current state.
+ ///
+ CurrentValues,
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/Enums/ResetMode.cs.uid b/GTweensGodot/GTweens/Source/Enums/ResetMode.cs.uid
new file mode 100644
index 00000000..3f516fee
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Enums/ResetMode.cs.uid
@@ -0,0 +1 @@
+uid://rg4640a2ekfw
diff --git a/GTweensGodot/GTweens/Source/Enums/RotationMode.cs b/GTweensGodot/GTweens/Source/Enums/RotationMode.cs
new file mode 100644
index 00000000..753f7d44
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Enums/RotationMode.cs
@@ -0,0 +1,18 @@
+namespace GTweens.Enums
+{
+ ///
+ /// Specifies different rotation modes for tweening operations.
+ ///
+ public enum RotationMode
+ {
+ ///
+ /// Rotates objects using the shortest distance between the initial and final angles.
+ ///
+ ShortestDistance,
+
+ ///
+ /// Rotates objects based on the total angular distance, which may involve multiple rotations.
+ ///
+ TotalDistance,
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/Enums/RotationMode.cs.uid b/GTweensGodot/GTweens/Source/Enums/RotationMode.cs.uid
new file mode 100644
index 00000000..aab1f446
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Enums/RotationMode.cs.uid
@@ -0,0 +1 @@
+uid://rnjfaov7hxcd
diff --git a/GTweensGodot/GTweens/Source/Extensions/AngleExtensions.cs b/GTweensGodot/GTweens/Source/Extensions/AngleExtensions.cs
new file mode 100644
index 00000000..b15041fe
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Extensions/AngleExtensions.cs
@@ -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)
+ );
+ }
+
+ ///
+ /// Calculates the shortest difference between two given angles.
+ ///
+ 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;
+ }
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/Extensions/AngleExtensions.cs.uid b/GTweensGodot/GTweens/Source/Extensions/AngleExtensions.cs.uid
new file mode 100644
index 00000000..c6a5d730
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Extensions/AngleExtensions.cs.uid
@@ -0,0 +1 @@
+uid://boj44m1nwtj83
diff --git a/GTweensGodot/GTweens/Source/Extensions/GTweenExtensions.cs b/GTweensGodot/GTweens/Source/Extensions/GTweenExtensions.cs
new file mode 100644
index 00000000..56eed0d7
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Extensions/GTweenExtensions.cs
@@ -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.Getter getter,
+ Tweener.Setter setter,
+ Tweener.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.Getter getter,
+ Tweener.Setter setter,
+ int to,
+ float duration,
+ ValidationDelegates.Validation validation
+ ) => Tween(getter, setter, () => to, duration, validation);
+
+ public static GTween Tween(
+ Tweener.Getter getter,
+ Tweener.Setter setter,
+ int to,
+ float duration
+ ) => Tween(getter, setter, () => to, duration, ValidationExtensions.AlwaysValid);
+
+ public static GTween Tween(
+ Tweener.Getter getter,
+ Tweener.Setter setter,
+ Tweener.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.Getter getter,
+ Tweener.Setter setter,
+ float to,
+ float duration,
+ ValidationDelegates.Validation validation
+ ) => Tween(getter, setter, () => to, duration, validation);
+
+ public static GTween Tween(
+ Tweener.Getter getter,
+ Tweener.Setter setter,
+ float to,
+ float duration
+ ) => Tween(getter, setter, to, duration, ValidationExtensions.AlwaysValid);
+
+ public static GTween Tween(
+ Tweener.Getter getter,
+ Tweener.Setter setter,
+ Tweener.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.Getter getter,
+ Tweener.Setter setter,
+ Vector2 to,
+ float duration,
+ ValidationDelegates.Validation validation
+ ) => Tween(getter, setter, () => to, duration, validation);
+
+
+ public static GTween Tween(
+ Tweener.Getter getter,
+ Tweener.Setter setter,
+ Vector2 to,
+ float duration
+ ) => Tween(getter, setter, to, duration, ValidationExtensions.AlwaysValid);
+
+ public static GTween Tween(
+ Tweener.Getter getter,
+ Tweener.Setter setter,
+ Tweener.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.Getter getter,
+ Tweener.Setter setter,
+ Vector3 to,
+ float duration,
+ ValidationDelegates.Validation validation
+ ) => Tween(getter, setter, () => to, duration, validation);
+
+ public static GTween Tween(
+ Tweener.Getter getter,
+ Tweener.Setter setter,
+ Vector3 to,
+ float duration
+ ) => Tween(getter, setter, to, duration, ValidationExtensions.AlwaysValid);
+
+ public static GTween Tween(
+ Tweener.Getter getter,
+ Tweener.Setter setter,
+ Tweener.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.Getter getter,
+ Tweener.Setter setter,
+ Vector4 to,
+ float duration,
+ ValidationDelegates.Validation validation
+ ) => Tween(getter, setter, () => to, duration, validation);
+
+ public static GTween Tween(
+ Tweener.Getter getter,
+ Tweener.Setter setter,
+ Vector4 to,
+ float duration
+ ) => Tween(getter, setter, to, duration, ValidationExtensions.AlwaysValid);
+
+ public static GTween Tween(
+ Tweener.Getter getter,
+ Tweener.Setter setter,
+ Tweener.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.Getter getter,
+ Tweener.Setter setter,
+ Color to,
+ float duration,
+ ValidationDelegates.Validation validation
+ ) => Tween(getter, setter, () => to, duration, validation);
+
+ public static GTween Tween(
+ Tweener.Getter getter,
+ Tweener.Setter setter,
+ Color to,
+ float duration
+ ) => Tween(getter, setter, to, duration, ValidationExtensions.AlwaysValid);
+
+ public static GTween Tween(
+ Tweener.Getter getter,
+ Tweener.Setter setter,
+ Tweener.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.Getter getter,
+ Tweener.Setter setter,
+ Quaternion to,
+ float duration,
+ ValidationDelegates.Validation validation
+ ) => Tween(getter, setter, () => to, duration, validation);
+
+ public static GTween Tween(
+ Tweener.Getter getter,
+ Tweener.Setter setter,
+ Quaternion to,
+ float duration
+ ) => Tween(getter, setter, to, duration, ValidationExtensions.AlwaysValid);
+
+ public static GTween Tween(
+ int from,
+ int to,
+ Tweener.Setter setter,
+ float duration
+ )
+ {
+ return Tween(
+ () => from,
+ setter,
+ to,
+ duration,
+ ValidationExtensions.AlwaysValid
+ );
+ }
+
+ public static GTween Tween(
+ float from,
+ float to,
+ Tweener.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;
+ }
+
+ ///
+ /// Asynchronously waits for the completion of a GTween animation or cancellation through a CancellationToken.
+ ///
+ /// The GTween instance to monitor for completion.
+ /// The CancellationToken that can be used to cancel the operation.
+ ///
+ /// A Task that represents the asynchronous operation. The Task completes when the GTween animation is complete,
+ /// or when the CancellationToken is signaled for cancellation.
+ ///
+ 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;
+ }
+ }
+}
diff --git a/GTweensGodot/GTweens/Source/Extensions/GTweenExtensions.cs.uid b/GTweensGodot/GTweens/Source/Extensions/GTweenExtensions.cs.uid
new file mode 100644
index 00000000..b8d48b25
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Extensions/GTweenExtensions.cs.uid
@@ -0,0 +1 @@
+uid://dei0hda724u2a
diff --git a/GTweensGodot/GTweens/Source/Extensions/MathExtensions.cs b/GTweensGodot/GTweens/Source/Extensions/MathExtensions.cs
new file mode 100644
index 00000000..8f176564
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Extensions/MathExtensions.cs
@@ -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;
+ }
+
+ ///
+ /// Loops the value t, so that it is never larger than length and never smaller than 0.
+ ///
+ public static float Repeat(float t, float length)
+ {
+ return Math.Clamp(t - (float)Math.Floor(t / length) * length, 0.0f, length);
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/Extensions/MathExtensions.cs.uid b/GTweensGodot/GTweens/Source/Extensions/MathExtensions.cs.uid
new file mode 100644
index 00000000..477cd375
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Extensions/MathExtensions.cs.uid
@@ -0,0 +1 @@
+uid://bouwnkbl68u6a
diff --git a/GTweensGodot/GTweens/Source/Extensions/SystemColorExtensions.cs b/GTweensGodot/GTweens/Source/Extensions/SystemColorExtensions.cs
new file mode 100644
index 00000000..f50e6851
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Extensions/SystemColorExtensions.cs
@@ -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)
+ );
+ }
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/Extensions/SystemColorExtensions.cs.uid b/GTweensGodot/GTweens/Source/Extensions/SystemColorExtensions.cs.uid
new file mode 100644
index 00000000..f03609a0
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Extensions/SystemColorExtensions.cs.uid
@@ -0,0 +1 @@
+uid://cftquavd2ss24
diff --git a/GTweensGodot/GTweens/Source/Extensions/ValidationExtensions.cs b/GTweensGodot/GTweens/Source/Extensions/ValidationExtensions.cs
new file mode 100644
index 00000000..876c0ea7
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Extensions/ValidationExtensions.cs
@@ -0,0 +1,8 @@
+using GTweens.Delegates;
+
+namespace GTweens.Extensions;
+
+public static class ValidationExtensions
+{
+ public static readonly ValidationDelegates.Validation AlwaysValid = () => true;
+}
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/Extensions/ValidationExtensions.cs.uid b/GTweensGodot/GTweens/Source/Extensions/ValidationExtensions.cs.uid
new file mode 100644
index 00000000..362593fa
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Extensions/ValidationExtensions.cs.uid
@@ -0,0 +1 @@
+uid://yer2h7qavcpt
diff --git a/GTweensGodot/GTweens/Source/Interpolators/FloatInterpolator.cs b/GTweensGodot/GTweens/Source/Interpolators/FloatInterpolator.cs
new file mode 100644
index 00000000..d8230436
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Interpolators/FloatInterpolator.cs
@@ -0,0 +1,34 @@
+using GTweens.Easings;
+
+namespace GTweens.Interpolators
+{
+ public sealed class FloatInterpolator : IInterpolator
+ {
+ 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;
+ }
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/Interpolators/FloatInterpolator.cs.uid b/GTweensGodot/GTweens/Source/Interpolators/FloatInterpolator.cs.uid
new file mode 100644
index 00000000..69703bd5
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Interpolators/FloatInterpolator.cs.uid
@@ -0,0 +1 @@
+uid://b3m1wga6bh0qn
diff --git a/GTweensGodot/GTweens/Source/Interpolators/IInterpolator.cs b/GTweensGodot/GTweens/Source/Interpolators/IInterpolator.cs
new file mode 100644
index 00000000..46788ba6
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Interpolators/IInterpolator.cs
@@ -0,0 +1,37 @@
+using GTweens.Easings;
+
+namespace GTweens.Interpolators
+{
+ ///
+ /// Represents an interpolator for working with transitions between two values of type .
+ ///
+ /// The type of values to interpolate.
+ public interface IInterpolator
+ {
+ ///
+ /// Evaluates the intermediate value between the initial and final values based on the specified time and easing function.
+ ///
+ /// The initial value.
+ /// The final value.
+ /// The interpolation time (usually between 0 and 1).
+ /// The easing function to apply during interpolation.
+ /// The interpolated value between and .
+ T Evaluate(T initialValue, T finalValue, float time, EasingDelegate easingFunction);
+
+ ///
+ /// Subtracts two values of type .
+ ///
+ /// The initial value.
+ /// The final value.
+ /// The result of subtracting from .
+ T Subtract(T initialValue, T finalValue);
+
+ ///
+ /// Adds two values of type .
+ ///
+ /// The initial value.
+ /// The final value.
+ /// The result of adding to .
+ T Add(T initialValue, T finalValue);
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/Interpolators/IInterpolator.cs.uid b/GTweensGodot/GTweens/Source/Interpolators/IInterpolator.cs.uid
new file mode 100644
index 00000000..c3899974
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Interpolators/IInterpolator.cs.uid
@@ -0,0 +1 @@
+uid://83qvtsiku48u
diff --git a/GTweensGodot/GTweens/Source/Interpolators/IntInterpolator.cs b/GTweensGodot/GTweens/Source/Interpolators/IntInterpolator.cs
new file mode 100644
index 00000000..a96fbb29
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Interpolators/IntInterpolator.cs
@@ -0,0 +1,34 @@
+using GTweens.Easings;
+
+namespace GTweens.Interpolators
+{
+ public sealed class IntInterpolator : IInterpolator
+ {
+ 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;
+ }
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/Interpolators/IntInterpolator.cs.uid b/GTweensGodot/GTweens/Source/Interpolators/IntInterpolator.cs.uid
new file mode 100644
index 00000000..1c373397
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Interpolators/IntInterpolator.cs.uid
@@ -0,0 +1 @@
+uid://e1vtsq83j4g6
diff --git a/GTweensGodot/GTweens/Source/Interpolators/SystemColorInterpolator.cs b/GTweensGodot/GTweens/Source/Interpolators/SystemColorInterpolator.cs
new file mode 100644
index 00000000..d30060ca
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Interpolators/SystemColorInterpolator.cs
@@ -0,0 +1,51 @@
+using System.Drawing;
+using GTweens.Easings;
+using GTweens.Extensions;
+
+namespace GTweens.Interpolators
+{
+ public sealed class SystemColorInterpolator : IInterpolator
+ {
+ 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
+ );
+ }
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/Interpolators/SystemColorInterpolator.cs.uid b/GTweensGodot/GTweens/Source/Interpolators/SystemColorInterpolator.cs.uid
new file mode 100644
index 00000000..86df5d16
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Interpolators/SystemColorInterpolator.cs.uid
@@ -0,0 +1 @@
+uid://bthivyns1lr7a
diff --git a/GTweensGodot/GTweens/Source/Interpolators/SystemQuaternionInterpolator.cs b/GTweensGodot/GTweens/Source/Interpolators/SystemQuaternionInterpolator.cs
new file mode 100644
index 00000000..cb88402a
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Interpolators/SystemQuaternionInterpolator.cs
@@ -0,0 +1,37 @@
+using System.Numerics;
+using GTweens.Easings;
+
+namespace GTweens.Interpolators
+{
+ public sealed class SystemQuaternionInterpolator : IInterpolator
+ {
+ 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;
+ }
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/Interpolators/SystemQuaternionInterpolator.cs.uid b/GTweensGodot/GTweens/Source/Interpolators/SystemQuaternionInterpolator.cs.uid
new file mode 100644
index 00000000..66a007b4
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Interpolators/SystemQuaternionInterpolator.cs.uid
@@ -0,0 +1 @@
+uid://d2onw3tx1lfu7
diff --git a/GTweensGodot/GTweens/Source/Interpolators/SystemVector2Interpolator.cs b/GTweensGodot/GTweens/Source/Interpolators/SystemVector2Interpolator.cs
new file mode 100644
index 00000000..66816106
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Interpolators/SystemVector2Interpolator.cs
@@ -0,0 +1,38 @@
+using System.Numerics;
+using GTweens.Easings;
+
+namespace GTweens.Interpolators
+{
+ public sealed class SystemVector2Interpolator : IInterpolator
+ {
+ 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;
+ }
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/Interpolators/SystemVector2Interpolator.cs.uid b/GTweensGodot/GTweens/Source/Interpolators/SystemVector2Interpolator.cs.uid
new file mode 100644
index 00000000..f9e7a316
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Interpolators/SystemVector2Interpolator.cs.uid
@@ -0,0 +1 @@
+uid://dvtde4b3gjv32
diff --git a/GTweensGodot/GTweens/Source/Interpolators/SystemVector3Interpolator.cs b/GTweensGodot/GTweens/Source/Interpolators/SystemVector3Interpolator.cs
new file mode 100644
index 00000000..74dd35b5
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Interpolators/SystemVector3Interpolator.cs
@@ -0,0 +1,39 @@
+using System.Numerics;
+using GTweens.Easings;
+
+namespace GTweens.Interpolators
+{
+ public sealed class SystemVector3Interpolator : IInterpolator
+ {
+ 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;
+ }
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/Interpolators/SystemVector3Interpolator.cs.uid b/GTweensGodot/GTweens/Source/Interpolators/SystemVector3Interpolator.cs.uid
new file mode 100644
index 00000000..1c6c1b19
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Interpolators/SystemVector3Interpolator.cs.uid
@@ -0,0 +1 @@
+uid://cdm8j104f7hgo
diff --git a/GTweensGodot/GTweens/Source/Interpolators/SystemVector3RotationInterpolator.cs b/GTweensGodot/GTweens/Source/Interpolators/SystemVector3RotationInterpolator.cs
new file mode 100644
index 00000000..ff09dd4a
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Interpolators/SystemVector3RotationInterpolator.cs
@@ -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
+// {
+// 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;
+// }
+// }
+// }
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/Interpolators/SystemVector3RotationInterpolator.cs.uid b/GTweensGodot/GTweens/Source/Interpolators/SystemVector3RotationInterpolator.cs.uid
new file mode 100644
index 00000000..d9ae627a
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Interpolators/SystemVector3RotationInterpolator.cs.uid
@@ -0,0 +1 @@
+uid://c8hpkxetb6uyg
diff --git a/GTweensGodot/GTweens/Source/Interpolators/SystemVector4Interpolator.cs b/GTweensGodot/GTweens/Source/Interpolators/SystemVector4Interpolator.cs
new file mode 100644
index 00000000..ccdacaa1
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Interpolators/SystemVector4Interpolator.cs
@@ -0,0 +1,40 @@
+using System.Numerics;
+using GTweens.Easings;
+
+namespace GTweens.Interpolators
+{
+ public sealed class SystemVector4Interpolator : IInterpolator
+ {
+ 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;
+ }
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/Interpolators/SystemVector4Interpolator.cs.uid b/GTweensGodot/GTweens/Source/Interpolators/SystemVector4Interpolator.cs.uid
new file mode 100644
index 00000000..04e2e93c
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Interpolators/SystemVector4Interpolator.cs.uid
@@ -0,0 +1 @@
+uid://cmwi4emxwsy8c
diff --git a/GTweensGodot/GTweens/Source/TweenBehaviours/CallbackTweenBehaviour.cs b/GTweensGodot/GTweens/Source/TweenBehaviours/CallbackTweenBehaviour.cs
new file mode 100644
index 00000000..03e785ce
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/TweenBehaviours/CallbackTweenBehaviour.cs
@@ -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;
+ }
+}
diff --git a/GTweensGodot/GTweens/Source/TweenBehaviours/CallbackTweenBehaviour.cs.uid b/GTweensGodot/GTweens/Source/TweenBehaviours/CallbackTweenBehaviour.cs.uid
new file mode 100644
index 00000000..809b97c8
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/TweenBehaviours/CallbackTweenBehaviour.cs.uid
@@ -0,0 +1 @@
+uid://b4nvwfr8t2hvu
diff --git a/GTweensGodot/GTweens/Source/TweenBehaviours/GroupTweenBehaviour.cs b/GTweensGodot/GTweens/Source/TweenBehaviours/GroupTweenBehaviour.cs
new file mode 100644
index 00000000..93f0091e
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/TweenBehaviours/GroupTweenBehaviour.cs
@@ -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 Tweens => _tweens;
+
+ readonly List _tweens = new();
+ readonly List _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();
+ }
+ }
+ }
+}
diff --git a/GTweensGodot/GTweens/Source/TweenBehaviours/GroupTweenBehaviour.cs.uid b/GTweensGodot/GTweens/Source/TweenBehaviours/GroupTweenBehaviour.cs.uid
new file mode 100644
index 00000000..ca90a719
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/TweenBehaviours/GroupTweenBehaviour.cs.uid
@@ -0,0 +1 @@
+uid://b0sfk7ps1fav6
diff --git a/GTweensGodot/GTweens/Source/TweenBehaviours/ITweenBehaviour.cs b/GTweensGodot/GTweens/Source/TweenBehaviours/ITweenBehaviour.cs
new file mode 100644
index 00000000..ed087e9c
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/TweenBehaviours/ITweenBehaviour.cs
@@ -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();
+}
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/TweenBehaviours/ITweenBehaviour.cs.uid b/GTweensGodot/GTweens/Source/TweenBehaviours/ITweenBehaviour.cs.uid
new file mode 100644
index 00000000..985e5228
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/TweenBehaviours/ITweenBehaviour.cs.uid
@@ -0,0 +1 @@
+uid://ceieq47mwyq5q
diff --git a/GTweensGodot/GTweens/Source/TweenBehaviours/InterpolationTweenBehaviour.cs b/GTweensGodot/GTweens/Source/TweenBehaviours/InterpolationTweenBehaviour.cs
new file mode 100644
index 00000000..d9fb9cae
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/TweenBehaviours/InterpolationTweenBehaviour.cs
@@ -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 _tweeners = new();
+ readonly List _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();
+ }
+ }
+ }
+}
diff --git a/GTweensGodot/GTweens/Source/TweenBehaviours/InterpolationTweenBehaviour.cs.uid b/GTweensGodot/GTweens/Source/TweenBehaviours/InterpolationTweenBehaviour.cs.uid
new file mode 100644
index 00000000..19eba961
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/TweenBehaviours/InterpolationTweenBehaviour.cs.uid
@@ -0,0 +1 @@
+uid://cx1regaakoijq
diff --git a/GTweensGodot/GTweens/Source/TweenBehaviours/SequenceTweenBehaviour.cs b/GTweensGodot/GTweens/Source/TweenBehaviours/SequenceTweenBehaviour.cs
new file mode 100644
index 00000000..9534dccc
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/TweenBehaviours/SequenceTweenBehaviour.cs
@@ -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 Tweens => _tweens;
+
+ readonly List _tweens = new();
+ readonly List _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();
+ }
+ }
+ }
+}
diff --git a/GTweensGodot/GTweens/Source/TweenBehaviours/SequenceTweenBehaviour.cs.uid b/GTweensGodot/GTweens/Source/TweenBehaviours/SequenceTweenBehaviour.cs.uid
new file mode 100644
index 00000000..0b46be3e
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/TweenBehaviours/SequenceTweenBehaviour.cs.uid
@@ -0,0 +1 @@
+uid://dm1lb1r6xblco
diff --git a/GTweensGodot/GTweens/Source/TweenBehaviours/TweenBehaviour.cs b/GTweensGodot/GTweens/Source/TweenBehaviours/TweenBehaviour.cs
new file mode 100644
index 00000000..8bf2b2f4
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/TweenBehaviours/TweenBehaviour.cs
@@ -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) { }
+}
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/TweenBehaviours/TweenBehaviour.cs.uid b/GTweensGodot/GTweens/Source/TweenBehaviours/TweenBehaviour.cs.uid
new file mode 100644
index 00000000..bdc73e77
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/TweenBehaviours/TweenBehaviour.cs.uid
@@ -0,0 +1 @@
+uid://rx0cbwgbajym
diff --git a/GTweensGodot/GTweens/Source/TweenBehaviours/WaitTimeTween.cs b/GTweensGodot/GTweens/Source/TweenBehaviours/WaitTimeTween.cs
new file mode 100644
index 00000000..8a111311
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/TweenBehaviours/WaitTimeTween.cs
@@ -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;
+ }
+ }
+}
diff --git a/GTweensGodot/GTweens/Source/TweenBehaviours/WaitTimeTween.cs.uid b/GTweensGodot/GTweens/Source/TweenBehaviours/WaitTimeTween.cs.uid
new file mode 100644
index 00000000..7bba8e11
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/TweenBehaviours/WaitTimeTween.cs.uid
@@ -0,0 +1 @@
+uid://m7stdrq84q6r
diff --git a/GTweensGodot/GTweens/Source/Tweeners/FloatTweener.cs b/GTweensGodot/GTweens/Source/Tweeners/FloatTweener.cs
new file mode 100644
index 00000000..527b0f40
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Tweeners/FloatTweener.cs
@@ -0,0 +1,25 @@
+using GTweens.Delegates;
+using GTweens.Interpolators;
+
+namespace GTweens.Tweeners;
+
+public sealed class FloatTweener : Tweener
+{
+ public FloatTweener(
+ Getter currentValueGetter,
+ Setter setter,
+ Getter to,
+ float duration,
+ ValidationDelegates.Validation validation
+ )
+ : base(
+ currentValueGetter,
+ setter,
+ to,
+ duration,
+ FloatInterpolator.Instance,
+ validation
+ )
+ {
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/Tweeners/FloatTweener.cs.uid b/GTweensGodot/GTweens/Source/Tweeners/FloatTweener.cs.uid
new file mode 100644
index 00000000..b8a1636f
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Tweeners/FloatTweener.cs.uid
@@ -0,0 +1 @@
+uid://bywdapy07yjny
diff --git a/GTweensGodot/GTweens/Source/Tweeners/ITweener.cs b/GTweensGodot/GTweens/Source/Tweeners/ITweener.cs
new file mode 100644
index 00000000..2503371c
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Tweeners/ITweener.cs
@@ -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();
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/Tweeners/ITweener.cs.uid b/GTweensGodot/GTweens/Source/Tweeners/ITweener.cs.uid
new file mode 100644
index 00000000..3c45f4e9
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Tweeners/ITweener.cs.uid
@@ -0,0 +1 @@
+uid://k17rtk6wh5xf
diff --git a/GTweensGodot/GTweens/Source/Tweeners/IntTweener.cs b/GTweensGodot/GTweens/Source/Tweeners/IntTweener.cs
new file mode 100644
index 00000000..81568c08
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Tweeners/IntTweener.cs
@@ -0,0 +1,26 @@
+using GTweens.Delegates;
+using GTweens.Interpolators;
+
+namespace GTweens.Tweeners
+{
+ public sealed class IntTweener : Tweener
+ {
+ internal IntTweener(
+ Getter currValueGetter,
+ Setter setter,
+ Getter to,
+ float duration,
+ ValidationDelegates.Validation validation
+ )
+ : base(
+ currValueGetter,
+ setter,
+ to,
+ duration,
+ IntInterpolator.Instance,
+ validation
+ )
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/Tweeners/IntTweener.cs.uid b/GTweensGodot/GTweens/Source/Tweeners/IntTweener.cs.uid
new file mode 100644
index 00000000..6b239ff7
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Tweeners/IntTweener.cs.uid
@@ -0,0 +1 @@
+uid://ntjjh7jiu8vt
diff --git a/GTweensGodot/GTweens/Source/Tweeners/SystemColorTweener.cs b/GTweensGodot/GTweens/Source/Tweeners/SystemColorTweener.cs
new file mode 100644
index 00000000..678ffff4
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Tweeners/SystemColorTweener.cs
@@ -0,0 +1,26 @@
+using System.Drawing;
+using GTweens.Delegates;
+using GTweens.Interpolators;
+
+namespace GTweens.Tweeners
+{
+ public sealed class SystemColorTweener : Tweener
+ {
+ public SystemColorTweener(
+ Getter currValueGetter,
+ Setter setter,
+ Getter to,
+ float duration,
+ ValidationDelegates.Validation validation
+ )
+ : base(currValueGetter,
+ setter,
+ to,
+ duration,
+ SystemColorInterpolator.Instance,
+ validation
+ )
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/Tweeners/SystemColorTweener.cs.uid b/GTweensGodot/GTweens/Source/Tweeners/SystemColorTweener.cs.uid
new file mode 100644
index 00000000..eda64383
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Tweeners/SystemColorTweener.cs.uid
@@ -0,0 +1 @@
+uid://bugpyjerorwcw
diff --git a/GTweensGodot/GTweens/Source/Tweeners/SystemQuaternionTweener.cs b/GTweensGodot/GTweens/Source/Tweeners/SystemQuaternionTweener.cs
new file mode 100644
index 00000000..a5f409e4
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Tweeners/SystemQuaternionTweener.cs
@@ -0,0 +1,27 @@
+using System.Numerics;
+using GTweens.Delegates;
+using GTweens.Interpolators;
+
+namespace GTweens.Tweeners
+{
+ public sealed class SystemQuaternionTweener : Tweener
+ {
+ public SystemQuaternionTweener(
+ Getter currValueGetter,
+ Setter setter,
+ Getter to,
+ float duration,
+ ValidationDelegates.Validation validation
+ )
+ : base(
+ currValueGetter,
+ setter,
+ to,
+ duration,
+ SystemQuaternionInterpolator.Instance,
+ validation
+ )
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/Tweeners/SystemQuaternionTweener.cs.uid b/GTweensGodot/GTweens/Source/Tweeners/SystemQuaternionTweener.cs.uid
new file mode 100644
index 00000000..d381bfa4
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Tweeners/SystemQuaternionTweener.cs.uid
@@ -0,0 +1 @@
+uid://cvhxhs2yx2njy
diff --git a/GTweensGodot/GTweens/Source/Tweeners/SystemVector2Tweener.cs b/GTweensGodot/GTweens/Source/Tweeners/SystemVector2Tweener.cs
new file mode 100644
index 00000000..e51f61b0
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Tweeners/SystemVector2Tweener.cs
@@ -0,0 +1,27 @@
+using System.Numerics;
+using GTweens.Delegates;
+using GTweens.Interpolators;
+
+namespace GTweens.Tweeners
+{
+ public sealed class SystemVector2Tweener : Tweener
+ {
+ public SystemVector2Tweener(
+ Getter currValueGetter,
+ Setter setter,
+ Getter to,
+ float duration,
+ ValidationDelegates.Validation validation
+ )
+ : base(
+ currValueGetter,
+ setter,
+ to,
+ duration,
+ SystemVector2Interpolator.Instance,
+ validation
+ )
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/Tweeners/SystemVector2Tweener.cs.uid b/GTweensGodot/GTweens/Source/Tweeners/SystemVector2Tweener.cs.uid
new file mode 100644
index 00000000..9e33c5fd
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Tweeners/SystemVector2Tweener.cs.uid
@@ -0,0 +1 @@
+uid://ckm388yjwcuu6
diff --git a/GTweensGodot/GTweens/Source/Tweeners/SystemVector3Tweener.cs b/GTweensGodot/GTweens/Source/Tweeners/SystemVector3Tweener.cs
new file mode 100644
index 00000000..85842795
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Tweeners/SystemVector3Tweener.cs
@@ -0,0 +1,27 @@
+using System.Numerics;
+using GTweens.Delegates;
+using GTweens.Interpolators;
+
+namespace GTweens.Tweeners
+{
+ public sealed class SystemVector3Tweener : Tweener
+ {
+ public SystemVector3Tweener(
+ Getter currValueGetter,
+ Setter setter,
+ Getter to,
+ float duration,
+ ValidationDelegates.Validation validation
+ )
+ : base(
+ currValueGetter,
+ setter,
+ to,
+ duration,
+ SystemVector3Interpolator.Instance,
+ validation
+ )
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/Tweeners/SystemVector3Tweener.cs.uid b/GTweensGodot/GTweens/Source/Tweeners/SystemVector3Tweener.cs.uid
new file mode 100644
index 00000000..992bd655
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Tweeners/SystemVector3Tweener.cs.uid
@@ -0,0 +1 @@
+uid://bpptxf58855kt
diff --git a/GTweensGodot/GTweens/Source/Tweeners/SystemVector4Tweener.cs b/GTweensGodot/GTweens/Source/Tweeners/SystemVector4Tweener.cs
new file mode 100644
index 00000000..bfd08f0a
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Tweeners/SystemVector4Tweener.cs
@@ -0,0 +1,27 @@
+using System.Numerics;
+using GTweens.Delegates;
+using GTweens.Interpolators;
+
+namespace GTweens.Tweeners
+{
+ public sealed class SystemVector4Tweener : Tweener
+ {
+ public SystemVector4Tweener(
+ Getter currValueGetter,
+ Setter setter,
+ Getter to,
+ float duration,
+ ValidationDelegates.Validation validation
+ )
+ : base(
+ currValueGetter,
+ setter,
+ to,
+ duration,
+ SystemVector4Interpolator.Instance,
+ validation
+ )
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/Tweeners/SystemVector4Tweener.cs.uid b/GTweensGodot/GTweens/Source/Tweeners/SystemVector4Tweener.cs.uid
new file mode 100644
index 00000000..c7228e39
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Tweeners/SystemVector4Tweener.cs.uid
@@ -0,0 +1 @@
+uid://b4534l80h30dx
diff --git a/GTweensGodot/GTweens/Source/Tweeners/Tweener.cs b/GTweensGodot/GTweens/Source/Tweeners/Tweener.cs
new file mode 100644
index 00000000..eeca9159
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Tweeners/Tweener.cs
@@ -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 : 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 _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 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;
+ }
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/Tweeners/Tweener.cs.uid b/GTweensGodot/GTweens/Source/Tweeners/Tweener.cs.uid
new file mode 100644
index 00000000..4c699ce0
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Tweeners/Tweener.cs.uid
@@ -0,0 +1 @@
+uid://cy5dli5pvpgrj
diff --git a/GTweensGodot/GTweens/Source/Tweeners/Vector3RotationTweener.cs b/GTweensGodot/GTweens/Source/Tweeners/Vector3RotationTweener.cs
new file mode 100644
index 00000000..397aba8e
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Tweeners/Vector3RotationTweener.cs
@@ -0,0 +1,27 @@
+// using Juce.Tweening.Interpolators;
+// using UnityEngine;
+//
+// namespace Juce.Tweening.Tweeners
+// {
+// public class Vector3RotationTweener : Tweener
+// {
+// public Vector3RotationTweener(
+// Getter currValueGetter,
+// Setter setter,
+// Getter finalValueGetter,
+// RotationMode rotationMode,
+// float duration,
+// Validation validation
+// )
+// : base(
+// currValueGetter,
+// setter,
+// finalValueGetter,
+// duration,
+// new SystemVector3RotationInterpolator(rotationMode),
+// validation
+// )
+// {
+// }
+// }
+// }
\ No newline at end of file
diff --git a/GTweensGodot/GTweens/Source/Tweeners/Vector3RotationTweener.cs.uid b/GTweensGodot/GTweens/Source/Tweeners/Vector3RotationTweener.cs.uid
new file mode 100644
index 00000000..4dcb6cd3
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Tweeners/Vector3RotationTweener.cs.uid
@@ -0,0 +1 @@
+uid://by4baldnaurb8
diff --git a/GTweensGodot/GTweens/Source/Tweens/GTween.cs b/GTweensGodot/GTweens/Source/Tweens/GTween.cs
new file mode 100644
index 00000000..4087934b
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Tweens/GTween.cs
@@ -0,0 +1,423 @@
+using System;
+using GTweens.Easings;
+using GTweens.Enums;
+using GTweens.TweenBehaviours;
+
+namespace GTweens.Tweens
+{
+ ///
+ /// Represents the core item for building tweening animations.
+ ///
+ 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? 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;
+ }
+
+ ///
+ /// Starts the tween.
+ ///
+ /// Determines if the tween should complete instantly.
+ public void Start(bool isCompletingInstantly = false)
+ {
+ if (IsPlaying)
+ {
+ Kill();
+ }
+
+ IsPlaying = true;
+ IsCompleted = false;
+ IsKilled = false;
+
+ _delayRemaining = Delay;
+ _loopsRemaining = Loops;
+
+ Behaviour.Start(isCompletingInstantly);
+
+ OnStartAction?.Invoke();
+ }
+
+ ///
+ /// Advances the tween by a given delta time.
+ ///
+ /// The elapsed time since the last update.
+ 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();
+ }
+ }
+
+ ///
+ /// 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.
+ ///
+ public GTween SetPaused(bool paused)
+ {
+ IsPaused = paused;
+ return this;
+ }
+
+ ///
+ /// Instantly reaches the final state of the tween, and stops playing.
+ ///
+ public void Complete()
+ {
+ if (!IsPlaying && !IsCompleted)
+ {
+ Start(true);
+ }
+
+ Behaviour.Complete();
+
+ _loopsRemaining = 0;
+
+ MarkFinished();
+ }
+
+ ///
+ /// Kills the tween. This means that the tween will stop playing, leaving it at its current state.
+ ///
+ public void Kill()
+ {
+ if (!IsPlaying)
+ {
+ return;
+ }
+
+ IsPlaying = false;
+ IsCompleted = false;
+ IsKilled = true;
+
+ Behaviour.Kill();
+
+ OnKillAction?.Invoke();
+ OnCompleteOrKillAction?.Invoke();
+ }
+
+ ///
+ /// Resets the tween, optionally killing it and specifying the reset mode.
+ ///
+ /// Whether to kill the tween.
+ /// The reset mode to use.
+ /// The current GTween instance for method chaining.
+ 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;
+ }
+
+ ///
+ /// Simulates the progress of a GTween animation for a specified duration.
+ ///
+ /// The simulated time in seconds.
+ /// The current GTween instance for method chaining.
+ 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;
+ }
+
+ ///
+ /// Adds some delay (in seconds) at the begining of the tween.
+ ///
+ public GTween SetDelay(float delaySeconds)
+ {
+ Delay = delaySeconds;
+ return this;
+ }
+
+ ///
+ /// 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.
+ ///
+ /// The time scale to set.
+ /// The current GTween instance for method chaining.
+ public GTween SetTimeScale(float timeScale)
+ {
+ TimeScale = timeScale;
+ OnTimeScaleChangedAction?.Invoke(timeScale);
+ return this;
+ }
+
+ ///
+ /// Sets the easing function for the tween.
+ ///
+ /// The custom easing function to use.
+ /// The current GTween instance for method chaining.
+ public GTween SetEasing(EasingDelegate easingFunction)
+ {
+ Behaviour.SetEasing(easingFunction);
+ return this;
+ }
+
+ ///
+ /// Sets the predefined easing function for the tween.
+ ///
+ /// The predefined easing to use.
+ /// The current GTween instance for method chaining.
+ public GTween SetEasing(Easing easing)
+ {
+ return SetEasing(PresetEasingDelegateFactory.GetEaseDelegate(easing));
+ }
+
+ ///
+ /// Sets the number of loops and the reset mode for the tween.
+ ///
+ /// The number of loops.
+ /// The reset mode to use when looping.
+ /// The current GTween instance for method chaining.
+ public GTween SetLoops(int loops, ResetMode resetMode = ResetMode.InitialValues)
+ {
+ Loops = Math.Max(loops, 0);
+ LoopResetMode = resetMode;
+ return this;
+ }
+
+ ///
+ /// Sets the tween to have and almost infinite amount of loops with the specified reset mode.
+ ///
+ /// The reset mode to use when looping.
+ /// The current GTween instance for method chaining.
+ public GTween SetMaxLoops(ResetMode resetMode = ResetMode.InitialValues)
+ {
+ return SetLoops(int.MaxValue, resetMode);
+ }
+
+ ///
+ /// Calculates the total duration of the tween.
+ ///
+ public float GetDuration()
+ {
+ return Behaviour.GetDuration();
+ }
+
+ ///
+ /// Calculates the time elapsed since the tween started playing.
+ ///
+ public float GetElapsed()
+ {
+ if(!IsPlaying && !IsCompleted)
+ {
+ return 0f;
+ }
+
+ if(!IsPlaying && IsCompleted)
+ {
+ return GetDuration();
+ }
+
+ return Behaviour.GetElapsed();
+ }
+
+ ///
+ /// Gets the time left remaining on the tween (duration - elapsed).
+ ///
+ 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 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();
+ }
+ }
+}
diff --git a/GTweensGodot/GTweens/Source/Tweens/GTween.cs.uid b/GTweensGodot/GTweens/Source/Tweens/GTween.cs.uid
new file mode 100644
index 00000000..3cd8e64e
--- /dev/null
+++ b/GTweensGodot/GTweens/Source/Tweens/GTween.cs.uid
@@ -0,0 +1 @@
+uid://d2cnyj34v2qq4
diff --git a/GTweensGodot/Godot/Source/Contexts/GodotGTweensContext.cs b/GTweensGodot/Godot/Source/Contexts/GodotGTweensContext.cs
new file mode 100644
index 00000000..e293eeb0
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Contexts/GodotGTweensContext.cs
@@ -0,0 +1,25 @@
+using GTweens.Contexts;
+
+namespace GTweensGodot.Contexts;
+
+///
+/// Represents a context for managing tweens in the Godot environment.
+///
+public class GodotGTweensContext
+{
+ public static readonly GodotGTweensContext Instance = new();
+
+ ///
+ /// Gets the unpausable context for managing tweens. This context is always running, even when GetTree().Paused
+ /// is set to true.
+ ///
+ public GTweensContext UnpausableContext { get; } = new();
+
+ ///
+ /// Gets the pausable context for managing tweens. This context is stops running when GetTree().Paused
+ /// is set to true.
+ ///
+ public GTweensContext PausableContext { get; } = new();
+
+ GodotGTweensContext() { }
+}
\ No newline at end of file
diff --git a/GTweensGodot/Godot/Source/Contexts/GodotGTweensContext.cs.uid b/GTweensGodot/Godot/Source/Contexts/GodotGTweensContext.cs.uid
new file mode 100644
index 00000000..797d76c2
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Contexts/GodotGTweensContext.cs.uid
@@ -0,0 +1 @@
+uid://di15j01ica1hi
diff --git a/GTweensGodot/Godot/Source/Contexts/GodotGTweensContextNode.cs b/GTweensGodot/Godot/Source/Contexts/GodotGTweensContextNode.cs
new file mode 100644
index 00000000..1e076baa
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Contexts/GodotGTweensContextNode.cs
@@ -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);
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/Godot/Source/Contexts/GodotGTweensContextNode.cs.uid b/GTweensGodot/Godot/Source/Contexts/GodotGTweensContextNode.cs.uid
new file mode 100644
index 00000000..16d5cb62
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Contexts/GodotGTweensContextNode.cs.uid
@@ -0,0 +1 @@
+uid://b51ltpwp3fkt0
diff --git a/GTweensGodot/Godot/Source/Extensions/AngleExtensions.cs b/GTweensGodot/Godot/Source/Extensions/AngleExtensions.cs
new file mode 100644
index 00000000..660a79df
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/AngleExtensions.cs
@@ -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;
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/Godot/Source/Extensions/AngleExtensions.cs.uid b/GTweensGodot/Godot/Source/Extensions/AngleExtensions.cs.uid
new file mode 100644
index 00000000..39043629
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/AngleExtensions.cs.uid
@@ -0,0 +1 @@
+uid://ctryd158yesn6
diff --git a/GTweensGodot/Godot/Source/Extensions/AudioStreamPlayer2DExtensions.cs b/GTweensGodot/Godot/Source/Extensions/AudioStreamPlayer2DExtensions.cs
new file mode 100644
index 00000000..fd3b8c14
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/AudioStreamPlayer2DExtensions.cs
@@ -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)
+ );
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/Godot/Source/Extensions/AudioStreamPlayer2DExtensions.cs.uid b/GTweensGodot/Godot/Source/Extensions/AudioStreamPlayer2DExtensions.cs.uid
new file mode 100644
index 00000000..91462675
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/AudioStreamPlayer2DExtensions.cs.uid
@@ -0,0 +1 @@
+uid://ecwl3ubgr054
diff --git a/GTweensGodot/Godot/Source/Extensions/AudioStreamPlayer3DExtensions.cs b/GTweensGodot/Godot/Source/Extensions/AudioStreamPlayer3DExtensions.cs
new file mode 100644
index 00000000..bd12f6d2
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/AudioStreamPlayer3DExtensions.cs
@@ -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)
+ );
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/Godot/Source/Extensions/AudioStreamPlayer3DExtensions.cs.uid b/GTweensGodot/Godot/Source/Extensions/AudioStreamPlayer3DExtensions.cs.uid
new file mode 100644
index 00000000..fdad9996
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/AudioStreamPlayer3DExtensions.cs.uid
@@ -0,0 +1 @@
+uid://b6hmb83ornmiv
diff --git a/GTweensGodot/Godot/Source/Extensions/BaseMaterial3DExtensions.cs b/GTweensGodot/Godot/Source/Extensions/BaseMaterial3DExtensions.cs
new file mode 100644
index 00000000..1226f3f7
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/BaseMaterial3DExtensions.cs
@@ -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)
+ );
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/Godot/Source/Extensions/BaseMaterial3DExtensions.cs.uid b/GTweensGodot/Godot/Source/Extensions/BaseMaterial3DExtensions.cs.uid
new file mode 100644
index 00000000..d9c8bdd6
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/BaseMaterial3DExtensions.cs.uid
@@ -0,0 +1 @@
+uid://cbrinkf16qyff
diff --git a/GTweensGodot/Godot/Source/Extensions/Camera2DExtensions.cs b/GTweensGodot/Godot/Source/Extensions/Camera2DExtensions.cs
new file mode 100644
index 00000000..7318a29b
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/Camera2DExtensions.cs
@@ -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)
+ );
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/Godot/Source/Extensions/Camera2DExtensions.cs.uid b/GTweensGodot/Godot/Source/Extensions/Camera2DExtensions.cs.uid
new file mode 100644
index 00000000..5a242224
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/Camera2DExtensions.cs.uid
@@ -0,0 +1 @@
+uid://rsvu3cctnr2k
diff --git a/GTweensGodot/Godot/Source/Extensions/Camera3DExtensions.cs b/GTweensGodot/Godot/Source/Extensions/Camera3DExtensions.cs
new file mode 100644
index 00000000..7afadc3d
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/Camera3DExtensions.cs
@@ -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)
+ );
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/Godot/Source/Extensions/Camera3DExtensions.cs.uid b/GTweensGodot/Godot/Source/Extensions/Camera3DExtensions.cs.uid
new file mode 100644
index 00000000..8560d0b1
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/Camera3DExtensions.cs.uid
@@ -0,0 +1 @@
+uid://ckmn5xp6nf40u
diff --git a/GTweensGodot/Godot/Source/Extensions/CanvasItemExtensions.cs b/GTweensGodot/Godot/Source/Extensions/CanvasItemExtensions.cs
new file mode 100644
index 00000000..b6606162
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/CanvasItemExtensions.cs
@@ -0,0 +1,74 @@
+using Godot;
+using GTweens.Extensions;
+using GTweens.Tweens;
+
+namespace GTweensGodot.Extensions;
+
+public static class CanvasItemExtensions
+{
+ public static GTween TweenModulate(this CanvasItem target, Color to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.Modulate,
+ current => target.Modulate = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenModulateRgb(this CanvasItem target, Color to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.Modulate,
+ current => target.Modulate = new Color(current.R, current.G, current.B, target.Modulate.A),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenModulateAlpha(this CanvasItem target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.Modulate.A,
+ current => target.Modulate = new Color(target.Modulate.R, target.Modulate.G, target.Modulate.B, current),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenSelfModulate(this CanvasItem target, Color to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.SelfModulate,
+ current => target.SelfModulate = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenSelfModulateRgb(this CanvasItem target, Color to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.SelfModulate,
+ current => target.SelfModulate = new Color(current.R, current.G, current.B, target.SelfModulate.A),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenSelfModulateAlpha(this CanvasItem target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.SelfModulate.A,
+ current => target.SelfModulate = new Color(target.SelfModulate.R, target.SelfModulate.G, target.SelfModulate.B, current),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/Godot/Source/Extensions/CanvasItemExtensions.cs.uid b/GTweensGodot/Godot/Source/Extensions/CanvasItemExtensions.cs.uid
new file mode 100644
index 00000000..c03f87c9
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/CanvasItemExtensions.cs.uid
@@ -0,0 +1 @@
+uid://bl6m35eo2x84k
diff --git a/GTweensGodot/Godot/Source/Extensions/CanvasModulateExtensions.cs b/GTweensGodot/Godot/Source/Extensions/CanvasModulateExtensions.cs
new file mode 100644
index 00000000..c41402e9
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/CanvasModulateExtensions.cs
@@ -0,0 +1,41 @@
+using Godot;
+using GTweens.Extensions;
+using GTweens.Tweens;
+
+namespace GTweensGodot.Extensions;
+
+public static class CanvasModulateExtensions
+{
+ public static GTween TweenColor(this CanvasModulate target, Color to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.Color,
+ current => target.Color = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenColorRgb(this CanvasModulate target, Color to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.Color,
+ current => target.Color = new Color(current.R, current.G, current.B, target.Color.A),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenColorAlpha(this CanvasModulate target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.Color.A,
+ current => target.Color = new Color(target.Color.R, target.Color.G, target.Color.B, current),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/Godot/Source/Extensions/CanvasModulateExtensions.cs.uid b/GTweensGodot/Godot/Source/Extensions/CanvasModulateExtensions.cs.uid
new file mode 100644
index 00000000..6dbdb2c9
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/CanvasModulateExtensions.cs.uid
@@ -0,0 +1 @@
+uid://iuhveeivk72w
diff --git a/GTweensGodot/Godot/Source/Extensions/ControlExtensions.cs b/GTweensGodot/Godot/Source/Extensions/ControlExtensions.cs
new file mode 100644
index 00000000..1ee97800
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/ControlExtensions.cs
@@ -0,0 +1,196 @@
+using Godot;
+using GTweens.Enums;
+using GTweens.Extensions;
+using GTweens.Tweens;
+
+namespace GTweensGodot.Extensions;
+
+public static class ControlExtensions
+{
+ public static GTween TweenGlobalPosition(this Control target, Vector2 to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.GlobalPosition,
+ current => target.GlobalPosition = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenGlobalPositionX(this Control target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.GlobalPosition.X,
+ current => target.GlobalPosition = new Vector2(current, target.GlobalPosition.Y),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenGlobalPositionY(this Control target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.GlobalPosition.Y,
+ current => target.GlobalPosition = new Vector2(target.GlobalPosition.X, current),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenPosition(this Control target, Vector2 to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.Position,
+ current => target.Position = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenPositionX(this Control target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.Position.X,
+ current => target.Position = new Vector2(current, target.Position.Y),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenPositionY(this Control target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.Position.Y,
+ current => target.Position = new Vector2(target.Position.X, current),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenRotation(this Control target, float to, float duration, RotationMode rotationMode = RotationMode.ShortestDistance)
+ {
+ return GTweenExtensions.Tween(
+ () => target.Rotation,
+ current => target.Rotation = current,
+ () => GTweens.Extensions.AngleExtensions.GetDestinationAngleRadiants(target.Rotation, to, rotationMode),
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenRotationDegrees(this Control target, float to, float duration, RotationMode rotationMode = RotationMode.ShortestDistance)
+ {
+ return GTweenExtensions.Tween(
+ () => target.RotationDegrees,
+ current => target.RotationDegrees = current,
+ () => GTweens.Extensions.AngleExtensions.GetDestinationAngleDegrees(target.RotationDegrees, to, rotationMode),
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenScale(this Control target, Vector2 to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.Scale,
+ current => target.Scale = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenScaleX(this Control target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.Scale.X,
+ current => target.Scale = new Vector2(current, target.Scale.Y),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenScaleY(this Control target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.Scale.Y,
+ current => target.Scale = new Vector2(target.Scale.X, current),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenSize(this Control target, Vector2 to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.Size,
+ current => target.Size = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenSizeX(this Control target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.Size.X,
+ current => target.Size = new Vector2(current, target.Size.Y),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenSizeY(this Control target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.Size.Y,
+ current => target.Size = new Vector2(target.Size.X, current),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenPivotOffset(this Control target, Vector2 to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.PivotOffset,
+ current => target.PivotOffset = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenPivotOffsetX(this Control target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.PivotOffset.X,
+ current => target.PivotOffset = new Vector2(current, target.PivotOffset.Y),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenPivotOffsetY(this Control target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.PivotOffset.Y,
+ current => target.PivotOffset = new Vector2(target.PivotOffset.X, current),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+}
diff --git a/GTweensGodot/Godot/Source/Extensions/ControlExtensions.cs.uid b/GTweensGodot/Godot/Source/Extensions/ControlExtensions.cs.uid
new file mode 100644
index 00000000..76c322e8
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/ControlExtensions.cs.uid
@@ -0,0 +1 @@
+uid://cc57owpk8jiyg
diff --git a/GTweensGodot/Godot/Source/Extensions/CurveExtensions.cs b/GTweensGodot/Godot/Source/Extensions/CurveExtensions.cs
new file mode 100644
index 00000000..d1ceec8a
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/CurveExtensions.cs
@@ -0,0 +1,19 @@
+using Godot;
+using GTweens.Easings;
+
+namespace GTweensGodot.Extensions;
+
+public static class CurveExtensions
+{
+ public static EasingDelegate ToEasingDelegate(this Curve curve)
+ {
+ float Result(float a, float b, float t)
+ {
+ float newT = curve.Sample(t);
+
+ return a + ((b - a) * newT);
+ }
+
+ return Result;
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/Godot/Source/Extensions/CurveExtensions.cs.uid b/GTweensGodot/Godot/Source/Extensions/CurveExtensions.cs.uid
new file mode 100644
index 00000000..bd18991a
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/CurveExtensions.cs.uid
@@ -0,0 +1 @@
+uid://ccquxii7a7i11
diff --git a/GTweensGodot/Godot/Source/Extensions/GTweenGodotExtensions.cs b/GTweensGodot/Godot/Source/Extensions/GTweenGodotExtensions.cs
new file mode 100644
index 00000000..ccb23fe1
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/GTweenGodotExtensions.cs
@@ -0,0 +1,311 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Godot;
+using GTweens.Delegates;
+using GTweens.Extensions;
+using GTweens.TweenBehaviours;
+using GTweens.Tweeners;
+using GTweens.Tweens;
+using GTweensGodot.Contexts;
+using GTweensGodot.Tweeners;
+
+namespace GTweensGodot.Extensions;
+
+public static class GTweenGodotExtensions
+{
+ public static GTween Tween(
+ Tweener.Getter getter,
+ Tweener.Setter setter,
+ Tweener.Getter to,
+ float duration,
+ ValidationDelegates.Validation validation
+ )
+ {
+ InterpolationTweenBehaviour tweenBehaviour = new InterpolationTweenBehaviour();
+ tweenBehaviour.Add(new GodotVector2Tweener(getter, setter, to, duration, validation));
+ return new GTween(tweenBehaviour);
+ }
+
+ public static GTween Tween(
+ Tweener.Getter getter,
+ Tweener.Setter setter,
+ Vector2 to,
+ float duration,
+ ValidationDelegates.Validation validation
+ ) => Tween(getter, setter, () => to, duration, validation);
+
+ public static GTween Tween(
+ Tweener.Getter getter,
+ Tweener.Setter setter,
+ Vector2 to,
+ float duration
+ ) => Tween(getter, setter, to, duration, ValidationExtensions.AlwaysValid);
+
+ public static GTween Tween(
+ Tweener.Getter getter,
+ Tweener.Setter setter,
+ Tweener.Getter to,
+ float duration,
+ ValidationDelegates.Validation validation
+ )
+ {
+ InterpolationTweenBehaviour tweenBehaviour = new InterpolationTweenBehaviour();
+ tweenBehaviour.Add(new GodotVector2ITweener(getter, setter, to, duration, validation));
+ return new GTween(tweenBehaviour);
+ }
+
+ public static GTween Tween(
+ Tweener.Getter getter,
+ Tweener.Setter setter,
+ Vector2I to,
+ float duration,
+ ValidationDelegates.Validation validation
+ ) => Tween(getter, setter, () => to, duration, validation);
+
+ public static GTween Tween(
+ Tweener.Getter getter,
+ Tweener.Setter setter,
+ Vector2I to,
+ float duration
+ ) => Tween(getter, setter, to, duration, ValidationExtensions.AlwaysValid);
+
+ public static GTween Tween(
+ Tweener.Getter getter,
+ Tweener.Setter setter,
+ Tweener.Getter to,
+ float duration,
+ ValidationDelegates.Validation validation
+ )
+ {
+ InterpolationTweenBehaviour tweenBehaviour = new InterpolationTweenBehaviour();
+ tweenBehaviour.Add(new GodotVector3Tweener(getter, setter, to, duration, validation));
+ return new GTween(tweenBehaviour);
+ }
+
+ public static GTween Tween(
+ Tweener.Getter getter,
+ Tweener.Setter setter,
+ Vector3 to,
+ float duration,
+ ValidationDelegates.Validation validation
+ ) => Tween(getter, setter, () => to, duration, validation);
+
+ public static GTween Tween(
+ Tweener.Getter getter,
+ Tweener.Setter setter,
+ Vector3 to,
+ float duration
+ ) => Tween(getter, setter, to, duration, ValidationExtensions.AlwaysValid);
+
+ public static GTween Tween(
+ Tweener.Getter getter,
+ Tweener.Setter setter,
+ Tweener.Getter to,
+ float duration,
+ ValidationDelegates.Validation validation
+ )
+ {
+ InterpolationTweenBehaviour tweenBehaviour = new InterpolationTweenBehaviour();
+ tweenBehaviour.Add(new GodotColorTweener(getter, setter, to, duration, validation));
+ return new GTween(tweenBehaviour);
+ }
+
+ public static GTween Tween(
+ Tweener.Getter getter,
+ Tweener.Setter setter,
+ Color to,
+ float duration,
+ ValidationDelegates.Validation validation
+ ) => Tween(getter, setter, () => to, duration, validation);
+
+ public static GTween Tween(
+ Tweener.Getter getter,
+ Tweener.Setter setter,
+ Color to,
+ float duration
+ ) => Tween(getter, setter, to, duration, ValidationExtensions.AlwaysValid);
+
+ ///
+ /// Sets the easing function for a GTween using a specified Curve.
+ ///
+ /// The GTween to set the easing function for.
+ /// The Curve representing the desired easing behavior.
+ /// The modified GTween with the specified easing function.
+ /// Thrown if is null.
+ public static GTween SetEasing(this GTween gTween, Curve curve)
+ {
+ if (curve == null)
+ {
+ throw new ArgumentNullException(
+ $"Tried to {nameof(SetEasing)} on a {nameof(GTween)} with a null {nameof(Curve)}"
+ );
+ }
+
+ return gTween.SetEasing(curve.ToEasingDelegate());
+ }
+
+ ///
+ /// Plays a GTween. This tween will be paused when GetTree().Paused is set to true.
+ ///
+ /// The GTween to play.
+ public static void Play(this GTween tween)
+ {
+ GodotGTweensContext.Instance.PausableContext.Play(tween);
+ }
+
+ ///
+ /// Plays a GTween. This tween will not be paused when GetTree().Paused is set to true.
+ ///
+ /// The GTween to play.
+ public static void PlayUnpausable(this GTween tween)
+ {
+ GodotGTweensContext.Instance.UnpausableContext.Play(tween);
+ }
+
+ ///
+ /// Plays a GTween. This tween will be paused when GetTree().Paused is set to true.
+ ///
+ /// The GTween to play.
+ /// If set to true, sets the tween as completed after playing, making it reach the end instantly.
+ public static void Play(this GTween tween, bool instantly)
+ {
+ tween.Play();
+
+ if (instantly)
+ {
+ tween.Complete();
+ }
+ }
+
+ ///
+ /// Plays a GTween. This tween will not be paused when GetTree().Paused is set to true.
+ ///
+ /// The GTween to play.
+ /// If set to true, sets the tween as completed after playing, making it reach the end instantly.
+ public static void PlayUnpausable(this GTween tween, bool instantly)
+ {
+ tween.PlayUnpausable();
+
+ if (instantly)
+ {
+ tween.Complete();
+ }
+ }
+
+ ///
+ /// Asynchronously plays a GTween and awaits its completion or cancellation.
+ /// If the cancellationToken cancellation is requested, the tween will be killed.
+ /// This tween will be paused when GetTree().Paused is set to true.
+ ///
+ /// The GTween to play.
+ /// A token to cancel the GTween's execution.
+ /// A Task representing the asynchronous operation.
+ public static Task PlayAsync(this GTween gTween, CancellationToken cancellationToken)
+ {
+ gTween.Play();
+
+ cancellationToken.Register(gTween.Kill);
+
+ return gTween.AwaitCompleteOrKill(cancellationToken);
+ }
+
+ ///
+ /// Asynchronously plays a GTween and awaits its completion or cancellation.
+ /// If the cancellationToken cancellation is requested, the tween will be killed.
+ /// This tween will not be paused when GetTree().Paused is set to true.
+ ///
+ /// The GTween to play.
+ /// A token to cancel the GTween's execution.
+ /// A Task representing the asynchronous operation.
+ public static Task PlayUnpausableAsync(this GTween gTween, CancellationToken cancellationToken)
+ {
+ gTween.PlayUnpausable();
+
+ cancellationToken.Register(gTween.Kill);
+
+ return gTween.AwaitCompleteOrKill(cancellationToken);
+ }
+
+ ///
+ /// Asynchronously plays a GTween and awaits its completion or cancellation.
+ /// If the cancellationToken cancellation is requested, the tween will be killed.
+ /// This tween will be paused when GetTree().Paused is set to true.
+ ///
+ /// The GTween to play.
+ /// If set to true, sets the tween as completed after playing, making it reach the end instantly.
+ /// A token to cancel the GTween's execution.
+ /// A Task representing the asynchronous operation.
+ public static Task PlayAsync(this GTween gTween, bool instantly, CancellationToken cancellationToken)
+ {
+ if (!instantly)
+ {
+ return gTween.PlayAsync(cancellationToken);
+ }
+
+ gTween.Play();
+ gTween.Complete();
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Asynchronously plays a GTween and awaits its completion or cancellation.
+ /// If the cancellationToken cancellation is requested, the tween will be killed.
+ /// This tween will not be paused when GetTree().Paused is set to true.
+ ///
+ /// The GTween to play.
+ /// If set to true, sets the tween as completed after playing, making it reach the end instantly.
+ /// A token to cancel the GTween's execution.
+ /// A Task representing the asynchronous operation.
+ public static Task PlayUnpausableAsync(this GTween gTween, bool instantly, CancellationToken cancellationToken)
+ {
+ if (!instantly)
+ {
+ return gTween.PlayUnpausableAsync(cancellationToken);
+ }
+
+ gTween.Play();
+ gTween.Complete();
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Asynchronously plays a GTween and awaits its completion or cancellation.
+ /// If the cancellationToken cancellation is requested, the tween will be killed.
+ /// This tween will be paused when GetTree().Paused is set to true.
+ ///
+ /// The GTween to play.
+ /// A token to complete the GTween's execution.
+ /// A token to cancel the GTween's execution.
+ /// A Task representing the asynchronous operation.
+ public static Task PlayAsync(this GTween gTween, CancellationToken completeToken, CancellationToken cancellationToken)
+ {
+ gTween.Play();
+
+ cancellationToken.Register(gTween.Kill);
+ completeToken.Register(gTween.Complete);
+
+ return gTween.AwaitCompleteOrKill(cancellationToken);
+ }
+
+ ///
+ /// Asynchronously plays a GTween and awaits its completion or cancellation.
+ /// If the cancellationToken cancellation is requested, the tween will be killed.
+ /// This tween will not be paused when GetTree().Paused is set to true.
+ ///
+ /// The GTween to play.
+ /// A token to complete the GTween's execution.
+ /// A token to cancel the GTween's execution.
+ /// A Task representing the asynchronous operation.
+ public static Task PlayUnpausableAsync(this GTween gTween, CancellationToken completeToken, CancellationToken cancellationToken)
+ {
+ gTween.PlayUnpausable();
+
+ cancellationToken.Register(gTween.Kill);
+ completeToken.Register(gTween.Complete);
+
+ return gTween.AwaitCompleteOrKill(cancellationToken);
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/Godot/Source/Extensions/GTweenGodotExtensions.cs.uid b/GTweensGodot/Godot/Source/Extensions/GTweenGodotExtensions.cs.uid
new file mode 100644
index 00000000..2dd89f39
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/GTweenGodotExtensions.cs.uid
@@ -0,0 +1 @@
+uid://be37qu6xx7nd3
diff --git a/GTweensGodot/Godot/Source/Extensions/GodotObjectExtensions.cs b/GTweensGodot/Godot/Source/Extensions/GodotObjectExtensions.cs
new file mode 100644
index 00000000..e4d153eb
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/GodotObjectExtensions.cs
@@ -0,0 +1,10 @@
+using Godot;
+using GTweens.Delegates;
+
+namespace GTweensGodot.Extensions;
+
+public static class GodotObjectExtensions
+{
+ public static ValidationDelegates.Validation GetGodotObjectValidationFunction(GodotObject godotObject)
+ => () => GodotObject.IsInstanceValid(godotObject);
+}
\ No newline at end of file
diff --git a/GTweensGodot/Godot/Source/Extensions/GodotObjectExtensions.cs.uid b/GTweensGodot/Godot/Source/Extensions/GodotObjectExtensions.cs.uid
new file mode 100644
index 00000000..367a9d3d
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/GodotObjectExtensions.cs.uid
@@ -0,0 +1 @@
+uid://d2ii15vsgypsg
diff --git a/GTweensGodot/Godot/Source/Extensions/LabelExtensions.cs b/GTweensGodot/Godot/Source/Extensions/LabelExtensions.cs
new file mode 100644
index 00000000..f7e2d259
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/LabelExtensions.cs
@@ -0,0 +1,19 @@
+using Godot;
+using GTweens.Extensions;
+using GTweens.Tweens;
+
+namespace GTweensGodot.Extensions;
+
+public static class LabelExtensions
+{
+ public static GTween TweenDisplayedTextVisibleRatio(this Label target, float value, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.VisibleRatio,
+ current => target.VisibleRatio = current,
+ value,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/Godot/Source/Extensions/LabelExtensions.cs.uid b/GTweensGodot/Godot/Source/Extensions/LabelExtensions.cs.uid
new file mode 100644
index 00000000..0095a5f3
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/LabelExtensions.cs.uid
@@ -0,0 +1 @@
+uid://daxhcgsex5bt6
diff --git a/GTweensGodot/Godot/Source/Extensions/Light2DExtensions.cs b/GTweensGodot/Godot/Source/Extensions/Light2DExtensions.cs
new file mode 100644
index 00000000..2b894115
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/Light2DExtensions.cs
@@ -0,0 +1,41 @@
+using Godot;
+using GTweens.Extensions;
+using GTweens.Tweens;
+
+namespace GTweensGodot.Extensions;
+
+public static class Light2DExtensions
+{
+ public static GTween TweenColor(this Light2D target, Color to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.Color,
+ current => target.Color = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenEnergy(this Light2D target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.Energy,
+ current => target.Energy = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenShadowColor(this Light2D target, Color to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.ShadowColor,
+ current => target.ShadowColor = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/Godot/Source/Extensions/Light2DExtensions.cs.uid b/GTweensGodot/Godot/Source/Extensions/Light2DExtensions.cs.uid
new file mode 100644
index 00000000..83c8acc1
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/Light2DExtensions.cs.uid
@@ -0,0 +1 @@
+uid://cnxrvox30dnul
diff --git a/GTweensGodot/Godot/Source/Extensions/Light3DExtensions.cs b/GTweensGodot/Godot/Source/Extensions/Light3DExtensions.cs
new file mode 100644
index 00000000..9f5c0149
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/Light3DExtensions.cs
@@ -0,0 +1,118 @@
+using Godot;
+using GTweens.Extensions;
+using GTweens.Tweens;
+
+namespace GTweensGodot.Extensions;
+
+public static class Light3DExtensions
+{
+ public static GTween TweenLightColor(this Light3D target, Color to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.LightColor,
+ current => target.LightColor = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenLightEnergy(this Light3D target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.LightEnergy,
+ current => target.LightEnergy = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenLightIndirectEnergy(this Light3D target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.LightIndirectEnergy,
+ current => target.LightIndirectEnergy = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenLightVolumetricFogEnergy(this Light3D target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.LightVolumetricFogEnergy,
+ current => target.LightVolumetricFogEnergy = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenLightAngularDistance(this Light3D target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.LightAngularDistance,
+ current => target.LightAngularDistance = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenShadowBias(this Light3D target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.ShadowBias,
+ current => target.ShadowBias = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenShadowNormalBias(this Light3D target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.ShadowNormalBias,
+ current => target.ShadowNormalBias = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenShadowTransmittanceBias(this Light3D target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.ShadowTransmittanceBias,
+ current => target.ShadowTransmittanceBias = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenShadowOpacity(this Light3D target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.ShadowOpacity,
+ current => target.ShadowOpacity = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenShadowBlur(this Light3D target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.ShadowBlur,
+ current => target.ShadowBlur = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/Godot/Source/Extensions/Light3DExtensions.cs.uid b/GTweensGodot/Godot/Source/Extensions/Light3DExtensions.cs.uid
new file mode 100644
index 00000000..d0841dae
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/Light3DExtensions.cs.uid
@@ -0,0 +1 @@
+uid://csk3p81k8w61e
diff --git a/GTweensGodot/Godot/Source/Extensions/MathExtensions.cs b/GTweensGodot/Godot/Source/Extensions/MathExtensions.cs
new file mode 100644
index 00000000..9407b165
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/MathExtensions.cs
@@ -0,0 +1,7 @@
+namespace GTweensGodot.Extensions;
+
+public static class MathExtensions
+{
+ public const float Deg2Rad = 0.01745329f;
+ public const float Rad2Deg = 57.29578f;
+}
\ No newline at end of file
diff --git a/GTweensGodot/Godot/Source/Extensions/MathExtensions.cs.uid b/GTweensGodot/Godot/Source/Extensions/MathExtensions.cs.uid
new file mode 100644
index 00000000..9ba73a6b
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/MathExtensions.cs.uid
@@ -0,0 +1 @@
+uid://bp2i5stjyqwv6
diff --git a/GTweensGodot/Godot/Source/Extensions/Node2DExtensions.cs b/GTweensGodot/Godot/Source/Extensions/Node2DExtensions.cs
new file mode 100644
index 00000000..2c17dc4c
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/Node2DExtensions.cs
@@ -0,0 +1,207 @@
+using Godot;
+using GTweens.Enums;
+using GTweens.Extensions;
+using GTweens.Tweens;
+
+namespace GTweensGodot.Extensions;
+
+public static class Node2DExtensions
+{
+ public static GTween TweenGlobalPosition(this Node2D target, Vector2 to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.GlobalPosition,
+ current => target.GlobalPosition = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenGlobalPositionX(this Node2D target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.GlobalPosition.X,
+ current => target.GlobalPosition = new Vector2(current, target.GlobalPosition.Y),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenGlobalPositionY(this Node2D target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.GlobalPosition.Y,
+ current => target.GlobalPosition = new Vector2(target.GlobalPosition.X, current),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenPosition(this Node2D target, Vector2 to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.Position,
+ current => target.Position = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenPositionX(this Node2D target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.Position.X,
+ current => target.Position = new Vector2(current, target.Position.Y),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenPositionY(this Node2D target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.Position.Y,
+ current => target.Position = new Vector2(target.Position.X, current),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenGlobalRotation(this Node2D target, float to, float duration, RotationMode rotationMode = RotationMode.ShortestDistance)
+ {
+ return GTweenExtensions.Tween(
+ () => target.GlobalRotation,
+ current => target.GlobalRotation = current,
+ () => GTweens.Extensions.AngleExtensions.GetDestinationAngleRadiants(target.GlobalRotation, to, rotationMode),
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenRotation(this Node2D target, float to, float duration, RotationMode rotationMode = RotationMode.ShortestDistance)
+ {
+ return GTweenExtensions.Tween(
+ () => target.Rotation,
+ current => target.Rotation = current,
+ () => GTweens.Extensions.AngleExtensions.GetDestinationAngleRadiants(target.Rotation, to, rotationMode),
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenGlobalRotationDegrees(this Node2D target, float to, float duration, RotationMode rotationMode = RotationMode.ShortestDistance)
+ {
+ return GTweenExtensions.Tween(
+ () => target.GlobalRotationDegrees,
+ current => target.GlobalRotationDegrees = current,
+ () => GTweens.Extensions.AngleExtensions.GetDestinationAngleDegrees(target.GlobalRotationDegrees, to, rotationMode),
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenRotationDegrees(this Node2D target, float to, float duration, RotationMode rotationMode = RotationMode.ShortestDistance)
+ {
+ return GTweenExtensions.Tween(
+ () => target.RotationDegrees,
+ current => target.RotationDegrees = current,
+ () => GTweens.Extensions.AngleExtensions.GetDestinationAngleDegrees(target.RotationDegrees, to, rotationMode),
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenGlobalScale(this Node2D target, Vector2 to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.GlobalScale,
+ current => target.GlobalScale = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenGlobalScaleX(this Node2D target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.GlobalScale.X,
+ current => target.GlobalScale = new Vector2(current, target.GlobalScale.Y),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenGlobalScaleY(this Node2D target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.GlobalScale.Y,
+ current => target.GlobalScale = new Vector2(target.GlobalScale.X, current),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenScale(this Node2D target, Vector2 to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.Scale,
+ current => target.Scale = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenScaleX(this Node2D target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.Scale.X,
+ current => target.Scale = new Vector2(current, target.Scale.Y),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenScaleY(this Node2D target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.Scale.Y,
+ current => target.Scale = new Vector2(target.Scale.X, current),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenGlobalSkew(this Node2D target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.GlobalSkew,
+ current => target.GlobalSkew = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenSkew(this Node2D target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.Skew,
+ current => target.Skew = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/Godot/Source/Extensions/Node2DExtensions.cs.uid b/GTweensGodot/Godot/Source/Extensions/Node2DExtensions.cs.uid
new file mode 100644
index 00000000..6f46b92c
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/Node2DExtensions.cs.uid
@@ -0,0 +1 @@
+uid://d0b1fftj7h4h3
diff --git a/GTweensGodot/Godot/Source/Extensions/Node3DExtensions.cs b/GTweensGodot/Godot/Source/Extensions/Node3DExtensions.cs
new file mode 100644
index 00000000..f1c24917
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/Node3DExtensions.cs
@@ -0,0 +1,383 @@
+using Godot;
+using GTweens.Enums;
+using GTweens.Extensions;
+using GTweens.Tweens;
+
+namespace GTweensGodot.Extensions;
+
+public static class Node3DExtensions
+{
+ public static GTween TweenGlobalPosition(this Node3D target, Vector3 to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.GlobalPosition,
+ current => target.GlobalPosition = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenGlobalPositionX(this Node3D target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.GlobalPosition.X,
+ current => target.GlobalPosition = new Vector3(current, target.GlobalPosition.Y, target.GlobalPosition.Z),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenGlobalPositionY(this Node3D target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.GlobalPosition.Y,
+ current => target.GlobalPosition = new Vector3(target.GlobalPosition.X, current, target.GlobalPosition.Z),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenGlobalPositionZ(this Node3D target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.GlobalPosition.Z,
+ current => target.GlobalPosition = new Vector3(target.GlobalPosition.X, target.GlobalPosition.Y, current),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenGlobalPositionXY(this Node3D target, Vector2 to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => new Vector2(target.GlobalPosition.X, target.GlobalPosition.Y),
+ current => target.GlobalPosition = new Vector3(current.X, current.Y, target.GlobalPosition.Z),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenGlobalPositionXZ(this Node3D target, Vector2 to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => new Vector2(target.GlobalPosition.X, target.GlobalPosition.Z),
+ current => target.GlobalPosition = new Vector3(current.X, target.GlobalPosition.Y, current.Y),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenGlobalPositionYZ(this Node3D target, Vector2 to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => new Vector2(target.GlobalPosition.Y, target.GlobalPosition.Z),
+ current => target.GlobalPosition = new Vector3(target.GlobalPosition.X, current.X, current.Y),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenPosition(this Node3D target, Vector3 to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.Position,
+ current => target.Position = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenPositionX(this Node3D target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.Position.X,
+ current => target.Position = new Vector3(current, target.Position.Y, target.Position.Z),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenPositionY(this Node3D target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.Position.Y,
+ current => target.Position = new Vector3(target.Position.X, current, target.Position.Z),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenPositionZ(this Node3D target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.Position.Z,
+ current => target.Position = new Vector3(target.Position.X, target.Position.Y, current),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenPositionXY(this Node3D target, Vector2 to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => new Vector2(target.Position.X, target.Position.Y),
+ current => target.Position = new Vector3(current.X, current.Y, target.Position.Z),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenPositionXZ(this Node3D target, Vector2 to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => new Vector2(target.Position.X, target.Position.Z),
+ current => target.Position = new Vector3(current.X, target.Position.Y, current.Y),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenPositionYZ(this Node3D target, Vector2 to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => new Vector2(target.Position.Y, target.Position.Z),
+ current => target.Position = new Vector3(target.Position.X, current.X, current.Y),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenGlobalRotation(this Node3D target, Vector3 to, float duration, RotationMode rotationMode = RotationMode.ShortestDistance)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.GlobalRotation,
+ current => target.GlobalRotation = current,
+ () => AngleExtensions.GetDestinationAngleRadiants(target.GlobalRotation, to, rotationMode),
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenGlobalRotationX(this Node3D target, float to, float duration, RotationMode rotationMode = RotationMode.ShortestDistance)
+ {
+ return GTweenExtensions.Tween(
+ () => target.GlobalRotation.X,
+ current => target.GlobalRotation = new Vector3(current, target.GlobalRotation.Y, target.GlobalRotation.Z),
+ () => GTweens.Extensions.AngleExtensions.GetDestinationAngleRadiants(target.GlobalRotation.X, to, rotationMode),
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenGlobalRotationY(this Node3D target, float to, float duration, RotationMode rotationMode = RotationMode.ShortestDistance)
+ {
+ return GTweenExtensions.Tween(
+ () => target.GlobalRotation.Y,
+ current => target.GlobalRotation = new Vector3(target.GlobalRotation.X, current, target.GlobalRotation.Z),
+ () => GTweens.Extensions.AngleExtensions.GetDestinationAngleRadiants(target.GlobalRotation.Y, to, rotationMode),
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenGlobalRotationZ(this Node3D target, float to, float duration, RotationMode rotationMode = RotationMode.ShortestDistance)
+ {
+ return GTweenExtensions.Tween(
+ () => target.GlobalRotation.Z,
+ current => target.GlobalRotation = new Vector3(target.GlobalRotation.X, target.GlobalRotation.Y, current),
+ () => GTweens.Extensions.AngleExtensions.GetDestinationAngleRadiants(target.GlobalRotation.Z, to, rotationMode),
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenRotation(this Node3D target, Vector3 to, float duration, RotationMode rotationMode = RotationMode.ShortestDistance)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.Rotation,
+ current => target.Rotation = current,
+ () => AngleExtensions.GetDestinationAngleRadiants(target.Rotation, to, rotationMode),
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenRotationX(this Node3D target, float to, float duration, RotationMode rotationMode = RotationMode.ShortestDistance)
+ {
+ return GTweenExtensions.Tween(
+ () => target.Rotation.X,
+ current => target.Rotation = new Vector3(current, target.Rotation.Y, target.Rotation.Z),
+ () => GTweens.Extensions.AngleExtensions.GetDestinationAngleRadiants(target.Rotation.X, to, rotationMode),
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenRotationY(this Node3D target, float to, float duration, RotationMode rotationMode = RotationMode.ShortestDistance)
+ {
+ return GTweenExtensions.Tween(
+ () => target.Rotation.Y,
+ current => target.Rotation = new Vector3(target.Rotation.X, current, target.Rotation.Z),
+ () => GTweens.Extensions.AngleExtensions.GetDestinationAngleRadiants(target.Rotation.Y, to, rotationMode),
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenRotationZ(this Node3D target, float to, float duration, RotationMode rotationMode = RotationMode.ShortestDistance)
+ {
+ return GTweenExtensions.Tween(
+ () => target.Rotation.Z,
+ current => target.Rotation = new Vector3(target.Rotation.X, target.Rotation.Y, current),
+ () => GTweens.Extensions.AngleExtensions.GetDestinationAngleRadiants(target.Rotation.X, to, rotationMode),
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenGlobalRotationDegrees(this Node3D target, Vector3 to, float duration, RotationMode rotationMode = RotationMode.ShortestDistance)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.GlobalRotationDegrees,
+ current => target.GlobalRotationDegrees = current,
+ () => AngleExtensions.GetDestinationAngleDegrees(target.GlobalRotationDegrees, to, rotationMode),
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenGlobalRotationDegreesX(this Node3D target, float to, float duration, RotationMode rotationMode = RotationMode.ShortestDistance)
+ {
+ return GTweenExtensions.Tween(
+ () => target.GlobalRotationDegrees.X,
+ current => target.GlobalRotationDegrees = new Vector3(current, target.GlobalRotationDegrees.Y, target.GlobalRotationDegrees.Z),
+ () => GTweens.Extensions.AngleExtensions.GetDestinationAngleDegrees(target.GlobalRotationDegrees.X, to, rotationMode),
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenGlobalRotationDegreesY(this Node3D target, float to, float duration, RotationMode rotationMode = RotationMode.ShortestDistance)
+ {
+ return GTweenExtensions.Tween(
+ () => target.GlobalRotationDegrees.Y,
+ current => target.GlobalRotationDegrees = new Vector3(target.GlobalRotationDegrees.X, current, target.GlobalRotationDegrees.Z),
+ () => GTweens.Extensions.AngleExtensions.GetDestinationAngleDegrees(target.GlobalRotationDegrees.Y, to, rotationMode),
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenGlobalRotationDegreesZ(this Node3D target, float to, float duration, RotationMode rotationMode = RotationMode.ShortestDistance)
+ {
+ return GTweenExtensions.Tween(
+ () => target.GlobalRotationDegrees.Z,
+ current => target.GlobalRotationDegrees = new Vector3(target.GlobalRotationDegrees.X, target.GlobalRotationDegrees.Y, current),
+ () => GTweens.Extensions.AngleExtensions.GetDestinationAngleDegrees(target.GlobalRotationDegrees.Z, to, rotationMode),
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenRotationDegrees(this Node3D target, Vector3 to, float duration, RotationMode rotationMode = RotationMode.ShortestDistance)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.RotationDegrees,
+ current => target.RotationDegrees = current,
+ () => AngleExtensions.GetDestinationAngleDegrees(target.RotationDegrees, to, rotationMode),
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenRotationDegreesX(this Node3D target, float to, float duration, RotationMode rotationMode = RotationMode.ShortestDistance)
+ {
+ return GTweenExtensions.Tween(
+ () => target.RotationDegrees.X,
+ current => target.RotationDegrees = new Vector3(current, target.RotationDegrees.Y, target.RotationDegrees.Z),
+ () => GTweens.Extensions.AngleExtensions.GetDestinationAngleDegrees(target.RotationDegrees.X, to, rotationMode),
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenRotationDegreesY(this Node3D target, float to, float duration, RotationMode rotationMode = RotationMode.ShortestDistance)
+ {
+ return GTweenExtensions.Tween(
+ () => target.RotationDegrees.Y,
+ current => target.RotationDegrees = new Vector3(target.RotationDegrees.X, current, target.RotationDegrees.Z),
+ () => GTweens.Extensions.AngleExtensions.GetDestinationAngleDegrees(target.RotationDegrees.Y, to, rotationMode),
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenRotationDegreesZ(this Node3D target, float to, float duration, RotationMode rotationMode = RotationMode.ShortestDistance)
+ {
+ return GTweenExtensions.Tween(
+ () => target.RotationDegrees.Z,
+ current => target.RotationDegrees = new Vector3(target.RotationDegrees.X, target.RotationDegrees.Y, current),
+ () => GTweens.Extensions.AngleExtensions.GetDestinationAngleDegrees(target.RotationDegrees.Z, to, rotationMode),
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenScale(this Node3D target, Vector3 to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.Scale,
+ current => target.Scale = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenScaleX(this Node3D target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.Scale.X,
+ current => target.Scale = new Vector3(current, target.Scale.Y, target.Scale.Z),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenScaleY(this Node3D target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.Scale.Y,
+ current => target.Scale = new Vector3(target.Scale.X, current, target.Scale.Z),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenScaleZ(this Node3D target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.Scale.Z,
+ current => target.Scale = new Vector3(target.Scale.X, target.Scale.Y, current),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/Godot/Source/Extensions/Node3DExtensions.cs.uid b/GTweensGodot/Godot/Source/Extensions/Node3DExtensions.cs.uid
new file mode 100644
index 00000000..9caa1205
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/Node3DExtensions.cs.uid
@@ -0,0 +1 @@
+uid://bkfgnrba5v3dx
diff --git a/GTweensGodot/Godot/Source/Extensions/RichTextLabelExtensions.cs b/GTweensGodot/Godot/Source/Extensions/RichTextLabelExtensions.cs
new file mode 100644
index 00000000..4ea0bf8a
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/RichTextLabelExtensions.cs
@@ -0,0 +1,19 @@
+using Godot;
+using GTweens.Extensions;
+using GTweens.Tweens;
+
+namespace GTweensGodot.Extensions;
+
+public static class RichTextLabelExtensions
+{
+ public static GTween TweenDisplayedTextVisibleRatio(this RichTextLabel target, float value, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.VisibleRatio,
+ current => target.VisibleRatio = current,
+ value,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/Godot/Source/Extensions/RichTextLabelExtensions.cs.uid b/GTweensGodot/Godot/Source/Extensions/RichTextLabelExtensions.cs.uid
new file mode 100644
index 00000000..d9e3d3b8
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/RichTextLabelExtensions.cs.uid
@@ -0,0 +1 @@
+uid://xxwaq6v8ryyd
diff --git a/GTweensGodot/Godot/Source/Extensions/ShaderMaterialExtensions.cs b/GTweensGodot/Godot/Source/Extensions/ShaderMaterialExtensions.cs
new file mode 100644
index 00000000..8b3a63b6
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/ShaderMaterialExtensions.cs
@@ -0,0 +1,92 @@
+using Godot;
+using GTweens.Extensions;
+using GTweens.Tweens;
+
+namespace GTweensGodot.Extensions;
+
+public static class ShaderMaterialExtensions
+{
+ public static GTween TweenPropertyInt(this ShaderMaterial target, StringName property, int to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.GetShaderParameter(property).AsInt32(),
+ current => target.SetShaderParameter(property, current),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenPropertyFloat(this ShaderMaterial target, StringName property, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.GetShaderParameter(property).AsSingle(),
+ current => target.SetShaderParameter(property, current),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenPropertyVector2(this ShaderMaterial target, StringName property, Vector2 to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.GetShaderParameter(property).AsVector2(),
+ current => target.SetShaderParameter(property, current),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenPropertyVector2I(this ShaderMaterial target, StringName property, Vector2I to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.GetShaderParameter(property).AsVector2I(),
+ current => target.SetShaderParameter(property, current),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenPropertyColor(this ShaderMaterial target, StringName property, Color to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.GetShaderParameter(property).AsColor(),
+ current => target.SetShaderParameter(property, current),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenPropertyColorRgb(this ShaderMaterial target, StringName property, Color to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.GetShaderParameter(property).AsColor(),
+ current => target.SetShaderParameter(
+ property,
+ new Color(current.R, current.G, current.B, target.GetShaderParameter(property).AsColor().A)
+ ),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenPropertyColorAlpha(this ShaderMaterial target, StringName property, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.GetShaderParameter(property).AsColor().A,
+ current =>
+ {
+ Color previous = target.GetShaderParameter(property).AsColor();
+ target.SetShaderParameter(property, new Color(previous.R, previous.G, previous.B, current));
+ },
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/Godot/Source/Extensions/ShaderMaterialExtensions.cs.uid b/GTweensGodot/Godot/Source/Extensions/ShaderMaterialExtensions.cs.uid
new file mode 100644
index 00000000..f1350feb
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/ShaderMaterialExtensions.cs.uid
@@ -0,0 +1 @@
+uid://c365bexkpc7oj
diff --git a/GTweensGodot/Godot/Source/Extensions/Sprite2DExtensions.cs b/GTweensGodot/Godot/Source/Extensions/Sprite2DExtensions.cs
new file mode 100644
index 00000000..f0bf4ed0
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/Sprite2DExtensions.cs
@@ -0,0 +1,41 @@
+using Godot;
+using GTweens.Extensions;
+using GTweens.Tweens;
+
+namespace GTweensGodot.Extensions;
+
+public static class Sprite2DExtensions
+{
+ public static GTween TweenOffset(this Sprite2D target, Vector2 to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.Offset,
+ current => target.Offset = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenOffsetX(this Sprite2D 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 Sprite2D 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)
+ );
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/Godot/Source/Extensions/Sprite2DExtensions.cs.uid b/GTweensGodot/Godot/Source/Extensions/Sprite2DExtensions.cs.uid
new file mode 100644
index 00000000..c6bc0ad9
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/Sprite2DExtensions.cs.uid
@@ -0,0 +1 @@
+uid://bo20q0wd8k2pv
diff --git a/GTweensGodot/Godot/Source/Extensions/SpriteBase3DExtensions.cs b/GTweensGodot/Godot/Source/Extensions/SpriteBase3DExtensions.cs
new file mode 100644
index 00000000..9ce52eb6
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/SpriteBase3DExtensions.cs
@@ -0,0 +1,74 @@
+using Godot;
+using GTweens.Extensions;
+using GTweens.Tweens;
+
+namespace GTweensGodot.Extensions;
+
+public static class SpriteBase3DExtensions
+{
+ public static GTween TweenModulate(this SpriteBase3D target, Color to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.Modulate,
+ current => target.Modulate = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenModulateRgb(this SpriteBase3D target, Color to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.Modulate,
+ current => target.Modulate = new Color(current.R, current.G, current.B, target.Modulate.A),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenModulateAlpha(this SpriteBase3D target, float to, float duration)
+ {
+ return GTweenExtensions.Tween(
+ () => target.Modulate.A,
+ current => target.Modulate = new Color(target.Modulate.R, target.Modulate.G, target.Modulate.B, current),
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenOffset(this SpriteBase3D target, Vector2 to, float duration)
+ {
+ return GTweenGodotExtensions.Tween(
+ () => target.Offset,
+ current => target.Offset = current,
+ to,
+ duration,
+ GodotObjectExtensions.GetGodotObjectValidationFunction(target)
+ );
+ }
+
+ public static GTween TweenOffsetX(this SpriteBase3D 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 SpriteBase3D 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)
+ );
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/Godot/Source/Extensions/SpriteBase3DExtensions.cs.uid b/GTweensGodot/Godot/Source/Extensions/SpriteBase3DExtensions.cs.uid
new file mode 100644
index 00000000..a5a81403
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Extensions/SpriteBase3DExtensions.cs.uid
@@ -0,0 +1 @@
+uid://c14wi0i2utc1e
diff --git a/GTweensGodot/Godot/Source/Interpolators/GodotColorInterpolator.cs b/GTweensGodot/Godot/Source/Interpolators/GodotColorInterpolator.cs
new file mode 100644
index 00000000..82de720b
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Interpolators/GodotColorInterpolator.cs
@@ -0,0 +1,50 @@
+using Godot;
+using GTweens.Easings;
+using GTweens.Interpolators;
+
+namespace GTweensGodot.Interpolators;
+
+public sealed class GodotColorInterpolator : IInterpolator
+{
+ public static readonly GodotColorInterpolator Instance = new();
+
+ GodotColorInterpolator()
+ {
+
+ }
+
+ public Color Evaluate(
+ Color initialValue,
+ Color finalValue,
+ float time,
+ EasingDelegate easingDelegate
+ )
+ {
+ return new Color(
+ easingDelegate(initialValue.R, finalValue.R, time),
+ easingDelegate(initialValue.G, finalValue.G, time),
+ easingDelegate(initialValue.B, finalValue.B, time),
+ easingDelegate!(initialValue.A, finalValue.A, time)
+ );
+ }
+
+ public Color Subtract(Color initialValue, Color finalValue)
+ {
+ return new Color(
+ finalValue.R - initialValue.R,
+ finalValue.G - initialValue.G,
+ finalValue.B - initialValue.B,
+ finalValue.A - initialValue.A
+ );
+ }
+
+ public Color Add(Color initialValue, Color finalValue)
+ {
+ return new Color(
+ finalValue.R + initialValue.R,
+ finalValue.G + initialValue.G,
+ finalValue.B + initialValue.B,
+ finalValue.A + initialValue.A
+ );
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/Godot/Source/Interpolators/GodotColorInterpolator.cs.uid b/GTweensGodot/Godot/Source/Interpolators/GodotColorInterpolator.cs.uid
new file mode 100644
index 00000000..4cb657d3
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Interpolators/GodotColorInterpolator.cs.uid
@@ -0,0 +1 @@
+uid://doups41b5yb7m
diff --git a/GTweensGodot/Godot/Source/Interpolators/GodotVector2IInterpolator.cs b/GTweensGodot/Godot/Source/Interpolators/GodotVector2IInterpolator.cs
new file mode 100644
index 00000000..22d86885
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Interpolators/GodotVector2IInterpolator.cs
@@ -0,0 +1,38 @@
+using Godot;
+using GTweens.Easings;
+using GTweens.Interpolators;
+
+namespace GTweensGodot.Interpolators;
+
+public sealed class GodotVector2IInterpolator : IInterpolator
+{
+ public static readonly GodotVector2IInterpolator Instance = new();
+
+ GodotVector2IInterpolator()
+ {
+
+ }
+
+ public Vector2I Evaluate(
+ Vector2I initialValue,
+ Vector2I finalValue,
+ float time,
+ EasingDelegate easingDelegate
+ )
+ {
+ return new Vector2I(
+ (int)easingDelegate(initialValue.X, finalValue.X, time),
+ (int)easingDelegate(initialValue.Y, finalValue.Y, time)
+ );
+ }
+
+ public Vector2I Subtract(Vector2I initialValue, Vector2I finalValue)
+ {
+ return finalValue - initialValue;
+ }
+
+ public Vector2I Add(Vector2I initialValue, Vector2I finalValue)
+ {
+ return finalValue + initialValue;
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/Godot/Source/Interpolators/GodotVector2IInterpolator.cs.uid b/GTweensGodot/Godot/Source/Interpolators/GodotVector2IInterpolator.cs.uid
new file mode 100644
index 00000000..de60e733
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Interpolators/GodotVector2IInterpolator.cs.uid
@@ -0,0 +1 @@
+uid://bo7xndtcu3plt
diff --git a/GTweensGodot/Godot/Source/Interpolators/GodotVector2Interpolator.cs b/GTweensGodot/Godot/Source/Interpolators/GodotVector2Interpolator.cs
new file mode 100644
index 00000000..0e82d63a
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Interpolators/GodotVector2Interpolator.cs
@@ -0,0 +1,38 @@
+using Godot;
+using GTweens.Easings;
+using GTweens.Interpolators;
+
+namespace GTweensGodot.Interpolators;
+
+public sealed class GodotVector2Interpolator : IInterpolator
+{
+ public static readonly GodotVector2Interpolator Instance = new();
+
+ GodotVector2Interpolator()
+ {
+
+ }
+
+ 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;
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/Godot/Source/Interpolators/GodotVector2Interpolator.cs.uid b/GTweensGodot/Godot/Source/Interpolators/GodotVector2Interpolator.cs.uid
new file mode 100644
index 00000000..2da083dc
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Interpolators/GodotVector2Interpolator.cs.uid
@@ -0,0 +1 @@
+uid://cirrcbdxbt6da
diff --git a/GTweensGodot/Godot/Source/Interpolators/GodotVector3Interpolator.cs b/GTweensGodot/Godot/Source/Interpolators/GodotVector3Interpolator.cs
new file mode 100644
index 00000000..9f8a6ddb
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Interpolators/GodotVector3Interpolator.cs
@@ -0,0 +1,39 @@
+using Godot;
+using GTweens.Easings;
+using GTweens.Interpolators;
+
+namespace GTweensGodot.Interpolators;
+
+public sealed class GodotVector3Interpolator : IInterpolator
+{
+ public static readonly GodotVector3Interpolator Instance = new();
+
+ GodotVector3Interpolator()
+ {
+
+ }
+
+ 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;
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/Godot/Source/Interpolators/GodotVector3Interpolator.cs.uid b/GTweensGodot/Godot/Source/Interpolators/GodotVector3Interpolator.cs.uid
new file mode 100644
index 00000000..f7b72861
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Interpolators/GodotVector3Interpolator.cs.uid
@@ -0,0 +1 @@
+uid://d36nv4qwd3pj8
diff --git a/GTweensGodot/Godot/Source/Tweeners/GodotColorTweener.cs b/GTweensGodot/Godot/Source/Tweeners/GodotColorTweener.cs
new file mode 100644
index 00000000..96490530
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Tweeners/GodotColorTweener.cs
@@ -0,0 +1,27 @@
+using Godot;
+using GTweens.Delegates;
+using GTweens.Tweeners;
+using GTweensGodot.Interpolators;
+
+namespace GTweensGodot.Tweeners;
+
+public sealed class GodotColorTweener : Tweener
+{
+ public GodotColorTweener(
+ Getter getter,
+ Setter setter,
+ Getter to,
+ float duration,
+ ValidationDelegates.Validation validation
+ )
+ : base(
+ getter,
+ setter,
+ to,
+ duration,
+ GodotColorInterpolator.Instance,
+ validation
+ )
+ {
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/Godot/Source/Tweeners/GodotColorTweener.cs.uid b/GTweensGodot/Godot/Source/Tweeners/GodotColorTweener.cs.uid
new file mode 100644
index 00000000..61e19743
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Tweeners/GodotColorTweener.cs.uid
@@ -0,0 +1 @@
+uid://c8cyqa2nc87io
diff --git a/GTweensGodot/Godot/Source/Tweeners/GodotVector2ITweener.cs b/GTweensGodot/Godot/Source/Tweeners/GodotVector2ITweener.cs
new file mode 100644
index 00000000..fc23298d
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Tweeners/GodotVector2ITweener.cs
@@ -0,0 +1,27 @@
+using Godot;
+using GTweens.Delegates;
+using GTweens.Tweeners;
+using GTweensGodot.Interpolators;
+
+namespace GTweensGodot.Tweeners;
+
+public sealed class GodotVector2ITweener : Tweener
+{
+ public GodotVector2ITweener(
+ Getter getter,
+ Setter setter,
+ Getter to,
+ float duration,
+ ValidationDelegates.Validation validation
+ )
+ : base(
+ getter,
+ setter,
+ to,
+ duration,
+ GodotVector2IInterpolator.Instance,
+ validation
+ )
+ {
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/Godot/Source/Tweeners/GodotVector2ITweener.cs.uid b/GTweensGodot/Godot/Source/Tweeners/GodotVector2ITweener.cs.uid
new file mode 100644
index 00000000..79284b9f
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Tweeners/GodotVector2ITweener.cs.uid
@@ -0,0 +1 @@
+uid://dg832ig7kf0jy
diff --git a/GTweensGodot/Godot/Source/Tweeners/GodotVector2Tweener.cs b/GTweensGodot/Godot/Source/Tweeners/GodotVector2Tweener.cs
new file mode 100644
index 00000000..32687480
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Tweeners/GodotVector2Tweener.cs
@@ -0,0 +1,27 @@
+using Godot;
+using GTweens.Delegates;
+using GTweens.Tweeners;
+using GTweensGodot.Interpolators;
+
+namespace GTweensGodot.Tweeners;
+
+public sealed class GodotVector2Tweener : Tweener
+{
+ public GodotVector2Tweener(
+ Getter getter,
+ Setter setter,
+ Getter to,
+ float duration,
+ ValidationDelegates.Validation validation
+ )
+ : base(
+ getter,
+ setter,
+ to,
+ duration,
+ GodotVector2Interpolator.Instance,
+ validation
+ )
+ {
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/Godot/Source/Tweeners/GodotVector2Tweener.cs.uid b/GTweensGodot/Godot/Source/Tweeners/GodotVector2Tweener.cs.uid
new file mode 100644
index 00000000..86204939
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Tweeners/GodotVector2Tweener.cs.uid
@@ -0,0 +1 @@
+uid://dhdwyenhxgusf
diff --git a/GTweensGodot/Godot/Source/Tweeners/GodotVector3Tweener.cs b/GTweensGodot/Godot/Source/Tweeners/GodotVector3Tweener.cs
new file mode 100644
index 00000000..411a4424
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Tweeners/GodotVector3Tweener.cs
@@ -0,0 +1,27 @@
+using Godot;
+using GTweens.Delegates;
+using GTweens.Tweeners;
+using GTweensGodot.Interpolators;
+
+namespace GTweensGodot.Tweeners;
+
+public sealed class GodotVector3Tweener : Tweener
+{
+ public GodotVector3Tweener(
+ Getter currentValueGetter,
+ Setter setter,
+ Getter to,
+ float duration,
+ ValidationDelegates.Validation validation
+ )
+ : base(
+ currentValueGetter,
+ setter,
+ to,
+ duration,
+ GodotVector3Interpolator.Instance,
+ validation
+ )
+ {
+ }
+}
\ No newline at end of file
diff --git a/GTweensGodot/Godot/Source/Tweeners/GodotVector3Tweener.cs.uid b/GTweensGodot/Godot/Source/Tweeners/GodotVector3Tweener.cs.uid
new file mode 100644
index 00000000..3a5b6a33
--- /dev/null
+++ b/GTweensGodot/Godot/Source/Tweeners/GodotVector3Tweener.cs.uid
@@ -0,0 +1 @@
+uid://bnthkuv2plwo7
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 00000000..ad4658a9
--- /dev/null
+++ b/LICENSE
@@ -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.
diff --git a/README.md b/README.md
new file mode 100644
index 00000000..db618ef6
--- /dev/null
+++ b/README.md
@@ -0,0 +1,326 @@
+[](https://opensource.org/licenses/MIT)
+[](#from-releases)
+[](#from-nuget)
+[](https://www.nuget.org/packages/GTweensGodot)
+[](https://github.com/Guillemsc/GTweens/actions/workflows/tests.yml)
+[](https://twitter.com/6uillem)
+
+[](https://github.com/Guillemsc/GTweensGodot/blob/main/CONTRIBUTING.md)
+
+
+
+GTweens-Godot is a lightweight and versatile tweening library for Godot 4 with C#.
+This library simplifies the process of creating animations and transitions in your Godot projects, allowing you to bring your game elements to life with ease.
+
+Unlike the default Godot tweening engine, which relies on nodes and their string properties to create animations, this tweening engine doesn't require the use of nodes.
+
+An extension that builds upon the [GTweens](https://github.com/Guillemsc/GTweens) library.
+
+## 🍰 Features
+- **Simple API**: GTweens-Godot provides an intuitive and easy-to-use API with C# extension methods.
+ ```csharp
+ public partial class TweenExample : Node
+ {
+ [Export] public Node2D Target;
+
+ public override void _Ready()
+ {
+ Target.TweenPosition(new Vector2(100, 0), 3)
+ .SetEasing(Easing.InOutCubic)
+ .Play();
+ }
+ }
+ ```
+
+- **Sequencing**: Easily chain multiple tweens together to create complex sequences of animations.
+ ```csharp
+ public partial class PlayTweenSequenceExample : Node
+ {
+ [Export] public Node2D Target;
+
+ public override void _Ready()
+ {
+ GTween tween = GTweenSequenceBuilder.New()
+ .Append(Target.TweenPositionX(100f, 0.5f))
+ .Join(Target.TweenScale(new Vector2(2f, 2f), 1f))
+ .AppendTime(0.5f)
+ .JoinCallback(() => GD.Print("I'm waiting some time!"))
+ .Append(Target.TweenPositionX(0f, 1f))
+ .AppendCallback(() => GD.Print("I'm finished!"))
+ .Build();
+
+ tween.SetEasing(Easing.InOutCubic);
+ tween.Play();
+ }
+ }
+ ```
+
+- **Versatile Easing Functions**: Choose from a variety of easing functions to achieve different animation effects, including linear, ease-in, ease-out, and custom curves.
+ ```csharp
+ public partial class EasingExample : Node
+ {
+ [Export] public Node2D Target1;
+ [Export] public Node2D Target2;
+
+ [Export] public Easing Easing1;
+ [Export] public Curve Easing2;
+
+ public override void _Ready()
+ {
+ GTween tween1 = Target1.TweenPositionX(100, 3);
+ tween1.SetEasing(Easing1);
+ tween1.Play();
+
+ GTween tween2 = Target2.TweenPositionX(100, 3);
+ tween2.SetEasing(Easing2);
+ tween2.Play();
+ }
+ }
+ ```
+
+- **Looping**: Create looping animations with a single line of code, and control loop count and behavior.
+ ```csharp
+ public partial class LoopingTweenExample : Node
+ {
+ [Export] public Node2D Target;
+ [Export] public int Loops;
+
+ public override void _Ready()
+ {
+ GTween tween = Target.TweenPositionX(150, 1);
+ tween.SetLoops(Loops);
+ tween.Play();
+ }
+ }
+ ```
+
+- **Delays**: Specify delays, allowing precise timing of your animations.
+ ```csharp
+ GTween tween = GTweenSequenceBuilder.New()
+ .AppendTime(0.5f)
+ .Build();
+ ```
+
+- **Callbacks**: Attach callbacks to tweens for event handling at various points in the animation timeline.
+ ```csharp
+ void Callback()
+ {
+ }
+
+ GTween tween = GTweenSequenceBuilder.New()
+ .AppendCallback(Callback)
+ .Build();
+ ```
+- **Async support**: GTweens uses the full power of C# and async tasks:
+ ```csharp
+ async Task RunSomething(CancellationToken)
+ {
+ await tween1.PlayAsync(cancellationToken);
+ await tween2.PlayAsync(cancellationToken);
+ }
+ ```
+
+- **Godot pause support**: GTweens supports changes to [GetTree().Paused](https://docs.godotengine.org/en/stable/tutorials/scripting/pausing_games.html):
+ ```csharp
+ tween.Play(); // Will be paused when GetTree().Paused is set to true
+ tween.PlayUnpausable(); // Won't be paused when GetTree().Paused is set to true
+ ```
+
+- **Safety**: When a node that's being tweened becomes invalid or gets destroyed, the tween automatically handles that on a safe manner, and kills itself.
+
+## 📦 Installation
+
+### Form Asset Library
+1. Inside Godot, open the AssetLib tab.
+
+
+
+2. Search for and select "GTweens (C#)".
+
+
+
+3. Download then install the asset.
+
+4. On the Godot editor, go to `Project/Project Settings/Autoload`, and select `GTweensGodot/Godot/Source/Contexts/GodotGTweensContextNode.cs` to be autoloaded.
+
+### From NuGet:
+1. Install the [GTweensGodot NuGet package](https://www.nuget.org/packages/GTweensGodot/) in your godot project.
+2. Create a new node script, anywhere in your project, that's going to update all the tweens. Copy and paste the code from here:
+ ```csharp
+ public partial class GTweensGodotUpdater : GodotGTweensContextNode
+ {
+
+ }
+ ```
+3. On the Godot editor, go to `Project/Project Settings/Autoload`, and select the `GTweensGodotUpdater.cs` we just created, to be autoloaded.
+
+ To quickly check if everything has been setup properly, you can create a new script with this code, and assign any `Node2D` to the `Target` export, and play it.
+ ```csharp
+ public partial class TweenExample : Node
+ {
+ [Export] public Node2D Target;
+
+ public override void _Ready()
+ {
+ Target.TweenPosition(new Vector2(100, 0), 3)
+ .SetEasing(Easing.InOutCubic)
+ .Play();
+ }
+ }
+ ```
+
+### From releases:
+1. [Download the latest GTweensGodot.zip release](https://github.com/Guillemsc/GTweensGodot/releases/latest).
+2. Unpack the `GTweensGodot.zip` folder into the Godot's project root folder.
+3. On the Godot editor, go to `Project/Project Settings/Autoload`, and select `GTweensGodot/Godot/Source/Contexts/GodotGTweensContextNode.cs` to be autoloaded.
+
+> [!WARNING]
+> If the example scenes cannot be opened, it probably means that the contents of `GTweensGodot.zip` were not placed on the root of your project,
+> or that the extracted folder has been renamed. Make sure you don't change the path nor rename any folder, since this will break scene references.
+
+
+## ✔️ After installing
+> [!NOTE]
+> (Except on NuGet installation) To quickly check if everything has been setup properly, you can go to `GTweensGodot/Godot/Examples/Scenes/` and open any of the example scenes.
+When you run any of those scenes, a simple functionality example should play.
+
+> [!NOTE]
+> If after playing an example scene, nothing moves or gets animated, this means that the `GodotGTweensContextNode.cs` has not been autoloaded. Make sure to properly follow the last installation step.
+
+## 📚 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:
+- **Tween**: prefix for all tween shortcuts (operations that can be started directly from a known object, like a Node2D or a Control).
+ ```csharp
+ node2D.TweenPositionX(100f, 1f);
+ control.TweenSizeY(200f, 2f);
+ ```
+- **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)
+
+// For Godot specific values (Vector2, Vector3, etc)
+GTweenGodotExtensions.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
+);
+
+// For Godot specific values
+GTween tween = GTweenGodotExtensions.Tween(
+ () => Target.Position, // Getter
+ x => Target.Position = x, // Setter
+ new Vector2(100f, 100f), // To
+ 1 // Duration
+);
+```
+
+### Shortcut tweening
+GTweem includes shortcuts for some known C# and Godot objects, like Node2D, Node3D, Control, etc. You can create a tween directly from a reference to these objects, like:
+```csharp
+node2D.TweenPositionX(100f, 1f);
+node3D.TweenScale(new Vector3(2f, 2f, 2f), 1f);
+control.TweenSizeY(200f, 2f);
+```
+See all [shortcuts you can use](#-shortcuts).
+
+### 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 with `GTweenSequenceBuilder.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(Target.TweenPositionX(100, 0.5f))
+ .Join(Target.TweenScale(new Vector2(2, 2), 1))
+ .Append(Target.TweenPositionY(100, 1))
+ .AppendTime(0.5f)
+ .Append(Target.TweenPositionX(0, 1))
+ .AppendSequence(s => s
+ .AppendTime(0.5f)
+ .Append(Target.TweenPositionX(1, 1))
+ )
+ .AppendCallback(() => GD.Print("I'm finished!"))
+ .Build();
+
+tween.SetEasing(Easing.InOutCubic);
+tween.Play();
+```
+As it can be seen on the example, you can Append/Join different things with the builder:
+- Append/Join Callback: adds a callback that will be called when this part of the sequence is executed.
+- Append/Join Time: adds a time delay (in seconds) to the sequence.
+- Append/Join Sequence: creates a new `GTweenSequenceBuilder` and provides it through the action. Then it automatically builds it and adds the resulting tween to the sequence.
+
+[Example of a complex sequence](https://github.com/Guillemsc/GTweensGodot/blob/main/Godot/Examples/Scripts/Cube3DExample.cs):
+
+
+
+### Tween controls
+- **Play**: plays the tween (will be paused if `GetTree().Paused` is set to true).
+- **PlayUnpausable**: plays the tween (won't be paused if `GetTree().Paused` is set to true).
+- **Kill**: kills the tween. This means that the tween will instantly stop playing, leaving it at its current state.
+- **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
+- **PlayAsync**: plays the tween and returns a Task that waits until the tween is killed or completed. If the parameter CancellationToken is cancelled, the tween will be killed.
+- **AwaitCompleteOrKill**: returns a Task that waits until the tween is killed or completed.
+
+## 📖 Shortcuts
+These are the currently avaliable shortcuts for Godot nodes (the list grows with time).
+- **Node2D**: GlobalPosition, Position, GlobalRotation, Rotation, GlobalRotationDegrees, RotationDegrees, GlobalScale, Scale, GlobalSkew, Skew.
+- **Node3D**: GlobalPosition, Position, GlobalRotation, Rotation, GlobalRotationDegrees, RotationDegrees, GlobalScale, Scale.
+- **Control**: GlobalPosition, Position, Rotation, RotationDegrees, Scale, Size, PivotOffset.
+- **Sprite2D**: Offset.
+- **SpriteBase3D**: Modulate, Offset.
+- **Light2D**: Color, Energy, ShadowColor.
+- **Light3D**: LightColor, LightEnergy, LightIndirectEnergy, LightVolumetricFogEnergy, LightAngularDistance, ShadowBias, ShadowNormalBias, ShadowTransmittanceBias, ShadowOpacity, ShadowBlur.
+- **Camera2D**: Offset, Zoom.
+- **Camera3D**: HOffset, VOffset, Fov.
+- **AudioStreamPlayer2D**: VolumeDb, PitchScale.
+- **AudioStreamPlayer3D**: VolumeDb, PitchScale, AttenuationFilterDb, AttenuationFilterCutoffHz.
+- **CanvasModulate**: Color.
+- **CanvasItem**: Modulate, SelfModulate.
+- **ShaderMaterial**: PropertyInt, PropertyFloat, PropertyVector2, PropertyVector2I, PropertyColor.
+- **BaseMaterial3D**: AlbedoColor, Metallic, MetallicSpecular, Roughness.
+
+ 
+
+
+
diff --git a/Scripts/Activables/Teleporter.cs b/Scripts/Activables/Teleporter.cs
index e6b3d828..db7c2d81 100644
--- a/Scripts/Activables/Teleporter.cs
+++ b/Scripts/Activables/Teleporter.cs
@@ -1,7 +1,9 @@
using System;
using System.Collections;
+using System.Threading;
using System.Threading.Tasks;
using Godot;
+using GTweensGodot.Extensions;
namespace Cirno.Scripts.Activables;
@@ -148,13 +150,15 @@ public partial class Teleporter : Activable
protected async Task TweenPlayer(PlayerMovement player)
{
+ await player.TweenGlobalPosition(GlobalPosition + new Vector2(0, -4f), TeleportAnimationLength).PlayAsync(CancellationToken.None);
+
// Create a Tween for the teleport animation
- Tween tween = GetTree().CreateTween();
- tween.SetEase(Tween.EaseType.InOut);
- tween.SetTrans(Tween.TransitionType.Sine);
- tween.TweenProperty(player, "global_position", GlobalPosition + new Vector2(0,-4f), TeleportAnimationLength);
-
- // Wait for the tween to finish
- await ToSignal(tween, "finished");
+ // Tween tween = GetTree().CreateTween();
+ // tween.SetEase(Tween.EaseType.InOut);
+ // tween.SetTrans(Tween.TransitionType.Sine);
+ // tween.TweenProperty(player, "global_position", GlobalPosition + new Vector2(0,-4f), TeleportAnimationLength);
+ //
+ // // Wait for the tween to finish
+ // await ToSignal(tween, "finished");
}
}
\ No newline at end of file
diff --git a/project.godot b/project.godot
index c8669e29..b98c82ba 100644
--- a/project.godot
+++ b/project.godot
@@ -31,6 +31,7 @@ DebugStats="res://Scenes/debug_stats.tscn"
DebugGUI="*res://addons/DebugGUI/DebugGUI.cs"
Dialogic="*res://addons/dialogic/Core/DialogicGameHandler.gd"
GlobalState="*res://Scripts/GlobalState.cs"
+GodotGTweensContextNode="*res://GTweensGodot/Godot/Source/Contexts/GodotGTweensContextNode.cs"
[dialogic]