Complete rewrite of Tweens

* Tweens were changed from Node to RefCounted. New API is inspired by DOTween.
* Tweens are created and managed by SceneTree, similar to SceneTreeTimer, which makes them ultra cheap to use a lot.
* Animating with Tweens is done by creating sequences of Tweeners. You create them from code and they autostart by default (fire-and-forget).
* There are 4 Tweeners that cover the former Tween functionality: PropertyTweener, IntervalTweener, CallbackTweener and MethodTweener.
* The methods were simplified a lot. Long argument lists are replaced with chained calls on Tweens and Tweeners.
* Tweeners by default execute in sequence, so it's easy to create complex chained animations.
* You can bind a Tween to a node. Tween will be removed automatically when the bound node is freed.
This commit is contained in:
Tomasz Chabora 2020-09-05 03:05:30 +02:00 committed by kobewi
parent 12e0f10c74
commit 900b2e0fdc
16 changed files with 1399 additions and 2005 deletions

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="CallbackTweener" inherits="Tweener" version="4.0">
<brief_description>
Calls the specified method after optional delay.
</brief_description>
<description>
[CallbackTweener] is used to call a method in a tweening sequence. See [method Tween.tween_callback] for more usage information.
[b]Note:[/b] [method Tween.tween_callback] is the only correct way to create [CallbackTweener]. Any [CallbackTweener] created manually will not function correctly.
</description>
<tutorials>
</tutorials>
<methods>
<method name="set_delay">
<return type="CallbackTweener">
</return>
<argument index="0" name="delay" type="float">
</argument>
<description>
Makes the callback call delayed by given time in seconds. Example:
[codeblock]
var tween = get_tree().create_tween()
tween.tween_callback(queue_free).set_delay(2) #this will call queue_free() after 2 seconds
[/codeblock]
</description>
</method>
</methods>
<constants>
</constants>
</class>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="IntervalTweener" inherits="Tweener" version="4.0">
<brief_description>
Creates an idle interval in a [Tween] animation.
</brief_description>
<description>
[IntervalTweener] is used to make delays in a tweening sequence. See [method Tween.tween_interval] for more usage information.
[b]Note:[/b] [method Tween.tween_interval] is the only correct way to create [IntervalTweener]. Any [IntervalTweener] created manually will not function correctly.
</description>
<tutorials>
</tutorials>
<methods>
</methods>
<constants>
</constants>
</class>

View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="MethodTweener" inherits="Tweener" version="4.0">
<brief_description>
Interpolates an abstract value and supplies it to a method called over time.
</brief_description>
<description>
[MethodTweener] is similar to a combination of [CallbackTweener] and [PropertyTweener]. It calls a method providing an interpolated value as a paramater. See [method Tween.tween_method] for more usage information.
[b]Note:[/b] [method Tween.tween_method] is the only correct way to create [MethodTweener]. Any [MethodTweener] created manually will not function correctly.
</description>
<tutorials>
</tutorials>
<methods>
<method name="set_delay">
<return type="MethodTweener">
</return>
<argument index="0" name="delay" type="float">
</argument>
<description>
Sets the time in seconds after which the [MethodTweener] will start interpolating. By default there's no delay.
</description>
</method>
<method name="set_ease">
<return type="MethodTweener">
</return>
<argument index="0" name="ease" type="int" enum="Tween.EaseType">
</argument>
<description>
Sets the type of used easing from [enum Tween.EaseType]. If not set, the default easing is used from the [Tween] that contains this Tweener.
</description>
</method>
<method name="set_trans">
<return type="MethodTweener">
</return>
<argument index="0" name="trans" type="int" enum="Tween.TransitionType">
</argument>
<description>
Sets the type of used transition from [enum Tween.TransitionType]. If not set, the default transition is used from the [Tween] that contains this Tweener.
</description>
</method>
</methods>
<constants>
</constants>
</class>

View File

@ -182,6 +182,16 @@
Returns [code]true[/code] if the node can process while the scene tree is paused (see [member process_mode]). Always returns [code]true[/code] if the scene tree is not paused, and [code]false[/code] if the node is not in the tree.
</description>
</method>
<method name="create_tween">
<return type="Tween">
</return>
<description>
Creates a new [Tween] and binds it to this node. This is equivalent of doing:
[codeblock]
get_tree().create_tween().bind_node(self)
[/codeblock]
</description>
</method>
<method name="duplicate" qualifiers="const">
<return type="Node">
</return>

View File

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="PropertyTweener" inherits="Tweener" version="4.0">
<brief_description>
Interpolates an [Object]'s property over time.
</brief_description>
<description>
[PropertyTweener] is used to interpolate a property in an object. See [method Tween.tween_property] for more usage information.
[b]Note:[/b] [method Tween.tween_property] is the only correct way to create [PropertyTweener]. Any [PropertyTweener] created manually will not function correctly.
</description>
<tutorials>
</tutorials>
<methods>
<method name="as_relative">
<return type="PropertyTweener">
</return>
<description>
When called, the final value will be used as a relative value instead. Example:
[codeblock]
var tween = get_tree().create_tween()
tween.tween_property(self, "position", Vector2.RIGHT * 100, 1).as_relative() #the node will move by 100 pixels to the right
[/codeblock]
</description>
</method>
<method name="from">
<return type="PropertyTweener">
</return>
<argument index="0" name="value" type="Variant">
</argument>
<description>
Sets a custom initial value to the [PropertyTweener]. Example:
[codeblock]
var tween = get_tree().create_tween()
tween.tween_property(self, "position", Vector2(200, 100), 1).from(Vector2(100, 100) #this will move the node from position (100, 100) to (200, 100)
[/codeblock]
</description>
</method>
<method name="from_current">
<return type="PropertyTweener">
</return>
<description>
Makes the [PropertyTweener] use the current property value (i.e. at the time of creating this [PropertyTweener]) as a starting point. This is equivalent of using [method from] with the current value. These two calls will do the same:
[codeblock]
tween.tween_property(self, "position", Vector2(200, 100), 1).from(position)
tween.tween_property(self, "position", Vector2(200, 100), 1).from_current()
[/codeblock]
</description>
</method>
<method name="set_delay">
<return type="PropertyTweener">
</return>
<argument index="0" name="delay" type="float">
</argument>
<description>
Sets the time in seconds after which the [PropertyTweener] will start interpolating. By default there's no delay.
</description>
</method>
<method name="set_ease">
<return type="PropertyTweener">
</return>
<argument index="0" name="ease" type="int" enum="Tween.EaseType">
</argument>
<description>
Sets the type of used easing from [enum Tween.EaseType]. If not set, the default easing is used from the [Tween] that contains this Tweener.
</description>
</method>
<method name="set_trans">
<return type="PropertyTweener">
</return>
<argument index="0" name="trans" type="int" enum="Tween.TransitionType">
</argument>
<description>
Sets the type of used transition from [enum Tween.TransitionType]. If not set, the default transition is used from the [Tween] that contains this Tweener.
</description>
</method>
</methods>
<constants>
</constants>
</class>

View File

@ -90,6 +90,13 @@
The timer will be automatically freed after its time elapses.
</description>
</method>
<method name="create_tween">
<return type="Tween">
</return>
<description>
Creates and returns a new [Tween].
</description>
</method>
<method name="get_first_node_in_group">
<return type="Node">
</return>
@ -135,6 +142,13 @@
Returns a list of all nodes assigned to the given group.
</description>
</method>
<method name="get_processed_tweens">
<return type="Array">
</return>
<description>
Returns an array of currently exising [Tween]s in the [SceneTree] (both running and paused).
</description>
</method>
<method name="get_rpc_sender_id" qualifiers="const">
<return type="int">
</return>

View File

@ -1,453 +1,398 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Tween" inherits="Node" version="4.0">
<class name="Tween" inherits="RefCounted" version="4.0">
<brief_description>
Smoothly animates a node's properties over time.
Lightweight object used for general-purpose animation via script, using [Tweener]s.
</brief_description>
<description>
Tweens are useful for animations requiring a numerical property to be interpolated over a range of values. The name [i]tween[/i] comes from [i]in-betweening[/i], an animation technique where you specify [i]keyframes[/i] and the computer interpolates the frames that appear between them.
[Tween] is more suited than [AnimationPlayer] for animations where you don't know the final values in advance. For example, interpolating a dynamically-chosen camera zoom value is best done with a [Tween] node; it would be difficult to do the same thing with an [AnimationPlayer] node.
Here is a brief usage example that makes a 2D node move smoothly between two positions:
[codeblocks]
[gdscript]
var tween = get_node("Tween")
tween.interpolate_property($Node2D, "position",
Vector2(0, 0), Vector2(100, 100), 1,
Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
tween.start()
[/gdscript]
[csharp]
var tween = GetNode&lt;Tween&gt;("Tween");
tween.InterpolateProperty(GetNode&lt;Node2D&gt;("Node2D"), "position",
new Vector2(0, 0), new Vector2(100, 100), 1,
Tween.TransitionType.Linear, Tween.EaseType.InOut);
tween.Start();
[/csharp]
[/codeblocks]
Many methods require a property name, such as [code]"position"[/code] above. You can find the correct property name by hovering over the property in the Inspector. You can also provide the components of a property directly by using [code]"property:component"[/code] (e.g. [code]position:x[/code]), where it would only apply to that particular component.
Many of the methods accept [code]trans_type[/code] and [code]ease_type[/code]. The first accepts an [enum TransitionType] constant, and refers to the way the timing of the animation is handled (see [url=https://easings.net/]easings.net[/url] for some examples). The second accepts an [enum EaseType] constant, and controls where the [code]trans_type[/code] is applied to the interpolation (in the beginning, the end, or both). If you don't know which transition and easing to pick, you can try different [enum TransitionType] constants with [constant EASE_IN_OUT], and use the one that looks best.
Tweens are mostly useful for animations requiring a numerical property to be interpolated over a range of values. The name [i]tween[/i] comes from [i]in-betweening[/i], an animation technique where you specify [i]keyframes[/i] and the computer interpolates the frames that appear between them.
[Tween] is more suited than [AnimationPlayer] for animations where you don't know the final values in advance. For example, interpolating a dynamically-chosen camera zoom value is best done with a [Tween]; it would be difficult to do the same thing with an [AnimationPlayer] node. Tweens are also more light-weight than [AnimationPlayer], so they are very much suited for simple animations or general tasks that don't require visual tweaking provided by the editor. They can be used in a fire-and-forget manner for some logic that normally would be done by code. You can e.g. make something shoot periodically by using a looped [CallbackTweener] with a delay.
A [Tween] can be created by using either [method SceneTree.create_tween] or [method Node.create_tween]. [Tween]s created manually (i.e. by using [code]Tween.new()[/code]) are invalid. They can't be used for tweening values, but you can do manual interpolation with [method interpolate_value].
A [Tween] animation is composed of a sequence of [Tweener]s, which by default are executed one after another. You can create a sequence by appending [Tweener]s to the [Tween]. Animating something with a [Tweener] is called tweening. Example tweening sequence looks like this:
[codeblock]
var tween = get_tree().create_tween()
tween.tween_property($Sprite, "modulate", Color.red, 1)
tween.tween_property($Sprite, "scale", Vector2(), 1)
tween.tween_callback($Sprite.queue_free)
[/codeblock]
This sequence will make the [code]$Sprite[/code] node turn red, then shrink and finally the [method Node.queue_free] is called to remove the sprite. See methods [method tween_property], [method tween_interval], [method tween_callback] and [method tween_method] for more usage information.
When a [Tweener] is created with one of the [code]tween_*[/code] methods, a chained method call can be used to tweak the properties of this [Tweener]. For example, if you want to set different transition type in the above example, you can do:
[codeblock]
var tween = get_tree().create_tween()
tween.tween_property($Sprite, "modulate", Color.red, 1).set_trans(Tween.TRANS_SINE)
tween.tween_property($Sprite, "scale", Vector2(), 1).set_trans(Tween.TRANS_BOUNCE)
tween.tween_callback($Sprite.queue_free)
[/codeblock]
Most of the [Tween] methods can be chained this way too. In this example the [Tween] is bound and have set a default transition:
[codeblock]
var tween = get_tree().create_tween().bind_node(self).set_trans(Tween.TRANS_ELASTIC)
tween.tween_property($Sprite, "modulate", Color.red, 1)
tween.tween_property($Sprite, "scale", Vector2(), 1)
tween.tween_callback($Sprite.queue_free)
[/codeblock]
Another interesting use for [Tween]s is animating arbitrary set of objects:
[codeblock]
var tween = create_tween()
for sprite in get_children():
tween.tween_property(sprite, "position", Vector2(), 1)
[/codeblock]
In the example above, all children of a node are moved one after another to position (0, 0).
Some [Tweener]s use transitions and eases. The first accepts an [enum TransitionType] constant, and refers to the way the timing of the animation is handled (see [url=https://easings.net/]easings.net[/url] for some examples). The second accepts an [enum EaseType] constant, and controls where the [code]trans_type[/code] is applied to the interpolation (in the beginning, the end, or both). If you don't know which transition and easing to pick, you can try different [enum TransitionType] constants with [constant EASE_IN_OUT], and use the one that looks best.
[url=https://raw.githubusercontent.com/godotengine/godot-docs/master/img/tween_cheatsheet.png]Tween easing and transition types cheatsheet[/url]
[b]Note:[/b] All [Tween]s will automatically start by default. To prevent a [Tween] from autostarting, you can call [method stop] immediately after it was created.
</description>
<tutorials>
</tutorials>
<methods>
<method name="follow_method">
<return type="void">
<method name="bind_node">
<return type="Tween">
</return>
<argument index="0" name="object" type="Object">
</argument>
<argument index="1" name="method" type="StringName">
</argument>
<argument index="2" name="initial_val" type="Variant">
</argument>
<argument index="3" name="target" type="Object">
</argument>
<argument index="4" name="target_method" type="StringName">
</argument>
<argument index="5" name="duration" type="float">
</argument>
<argument index="6" name="trans_type" type="int" enum="Tween.TransitionType" default="0">
</argument>
<argument index="7" name="ease_type" type="int" enum="Tween.EaseType" default="2">
</argument>
<argument index="8" name="delay" type="float" default="0">
<argument index="0" name="node" type="Node">
</argument>
<description>
Follows [code]method[/code] of [code]object[/code] and applies the returned value on [code]target_method[/code] of [code]target[/code], beginning from [code]initial_val[/code] for [code]duration[/code] seconds, [code]delay[/code] later. Methods are called with consecutive values.
Use [enum TransitionType] for [code]trans_type[/code] and [enum EaseType] for [code]ease_type[/code] parameters. These values control the timing and direction of the interpolation. See the class description for more information.
Binds this [Tween] with the given [code]node[/code]. [Tween]s are processed directly by the [SceneTree], so they run independently of the animated nodes. When you bind a [Node] with the [Tween], the [Tween] will halt the animation when the object is not inside tree and the [Tween] will be automatically killed when the bound object is freed. Also [constant TWEEN_PAUSE_BOUND] will make the pausing behavior dependent on the bound node.
For a shorter way to create and bind a [Tween], you can use [method Node.create_tween].
</description>
</method>
<method name="follow_property">
<return type="void">
</return>
<argument index="0" name="object" type="Object">
</argument>
<argument index="1" name="property" type="NodePath">
</argument>
<argument index="2" name="initial_val" type="Variant">
</argument>
<argument index="3" name="target" type="Object">
</argument>
<argument index="4" name="target_property" type="NodePath">
</argument>
<argument index="5" name="duration" type="float">
</argument>
<argument index="6" name="trans_type" type="int" enum="Tween.TransitionType" default="0">
</argument>
<argument index="7" name="ease_type" type="int" enum="Tween.EaseType" default="2">
</argument>
<argument index="8" name="delay" type="float" default="0">
</argument>
<description>
Follows [code]property[/code] of [code]object[/code] and applies it on [code]target_property[/code] of [code]target[/code], beginning from [code]initial_val[/code] for [code]duration[/code] seconds, [code]delay[/code] seconds later.
Use [enum TransitionType] for [code]trans_type[/code] and [enum EaseType] for [code]ease_type[/code] parameters. These values control the timing and direction of the interpolation. See the class description for more information.
</description>
</method>
<method name="get_runtime" qualifiers="const">
<return type="float">
<method name="chain">
<return type="Tween">
</return>
<description>
Returns the total time needed for all tweens to end. If you have two tweens, one lasting 10 seconds and the other 20 seconds, it would return 20 seconds, as by that time all tweens would have finished.
Used to chain two [Tweener]s after [method set_parallel] is called with [code]true[/code].
[codeblock]
var tween = create_tween().set_parallel(true)
tween.tween_property(...)
tween.tween_property(...) #will run parallelly with above
tween.chain().tween_property(...) #will run after two above are finished
[/codeblock]
</description>
</method>
<method name="interpolate_callback">
<return type="void">
<method name="custom_step">
<return type="bool">
</return>
<argument index="0" name="object" type="Object">
</argument>
<argument index="1" name="duration" type="float">
</argument>
<argument index="2" name="callback" type="String">
</argument>
<argument index="3" name="arg1" type="Variant" default="null">
</argument>
<argument index="4" name="arg2" type="Variant" default="null">
</argument>
<argument index="5" name="arg3" type="Variant" default="null">
</argument>
<argument index="6" name="arg4" type="Variant" default="null">
</argument>
<argument index="7" name="arg5" type="Variant" default="null">
<argument index="0" name="delta" type="float">
</argument>
<description>
Calls [code]callback[/code] of [code]object[/code] after [code]duration[/code]. [code]arg1[/code]-[code]arg5[/code] are arguments to be passed to the callback.
Processes the [Tween] by given [code]delta[/code] value, in seconds. Mostly useful when the [Tween] is paused, for controlling it manually.
Returns [code]true[/code] if the [Tween] still has [Tweener]s that haven't finished.
[b]Note:[/b] The [Tween] will become invalid after finished, but you can call [method stop] after the step, to keep it and reset.
[b]Note:[/b] [method custom_step] will process only one step of the [Tween]. If the [code]delta[/code] is greater than the remaining time, the excessive time will not have any effect.
</description>
</method>
<method name="interpolate_deferred_callback">
<return type="void">
<method name="interpolate_value">
<return type="Variant">
</return>
<argument index="0" name="object" type="Object">
<argument index="0" name="trans_type" type="Variant">
</argument>
<argument index="1" name="duration" type="float">
<argument index="1" name="ease_type" type="Variant">
</argument>
<argument index="2" name="callback" type="String">
<argument index="2" name="elapsed_time" type="float">
</argument>
<argument index="3" name="arg1" type="Variant" default="null">
<argument index="3" name="initial_value" type="float">
</argument>
<argument index="4" name="arg2" type="Variant" default="null">
<argument index="4" name="delta_value" type="int" enum="Tween.TransitionType">
</argument>
<argument index="5" name="arg3" type="Variant" default="null">
</argument>
<argument index="6" name="arg4" type="Variant" default="null">
</argument>
<argument index="7" name="arg5" type="Variant" default="null">
<argument index="5" name="duration" type="int" enum="Tween.EaseType">
</argument>
<description>
Calls [code]callback[/code] of [code]object[/code] after [code]duration[/code] on the main thread (similar to [method Object.call_deferred]). [code]arg1[/code]-[code]arg5[/code] are arguments to be passed to the callback.
This method can be used for manual interpolation of a value, when you don't want [Tween] to do animating for you. It's similar to [method @GlobalScope.lerp], but with support for custom transition and easing.
[code]elapsed_time[/code] is the time in seconds that passed after the interping started and it's used to control the position of the interpolation. E.g. when it's equal to half of the [code]duration[/code], the interpolated value will be halfway between initial and final values. This value can also be greater than [code]duration[/code] or lower than 0, which will extrapolate the value.
[code]initial_value[/code] is the starting value of the interpolation.
[code]delta_value[/code] is the change of the value in the interpolation, i.e. it's equal to [code]final_value - initial_value[/code].
[code]duration[/code] is the total time of the interpolation.
</description>
</method>
<method name="interpolate_method">
<return type="void">
</return>
<argument index="0" name="object" type="Object">
</argument>
<argument index="1" name="method" type="StringName">
</argument>
<argument index="2" name="initial_val" type="Variant">
</argument>
<argument index="3" name="final_val" type="Variant">
</argument>
<argument index="4" name="duration" type="float">
</argument>
<argument index="5" name="trans_type" type="int" enum="Tween.TransitionType" default="0">
</argument>
<argument index="6" name="ease_type" type="int" enum="Tween.EaseType" default="2">
</argument>
<argument index="7" name="delay" type="float" default="0">
</argument>
<description>
Animates [code]method[/code] of [code]object[/code] from [code]initial_val[/code] to [code]final_val[/code] for [code]duration[/code] seconds, [code]delay[/code] seconds later. Methods are called with consecutive values.
Use [enum TransitionType] for [code]trans_type[/code] and [enum EaseType] for [code]ease_type[/code] parameters. These values control the timing and direction of the interpolation. See the class description for more information.
</description>
</method>
<method name="interpolate_property">
<return type="void">
</return>
<argument index="0" name="object" type="Object">
</argument>
<argument index="1" name="property" type="NodePath">
</argument>
<argument index="2" name="initial_val" type="Variant">
</argument>
<argument index="3" name="final_val" type="Variant">
</argument>
<argument index="4" name="duration" type="float">
</argument>
<argument index="5" name="trans_type" type="int" enum="Tween.TransitionType" default="0">
</argument>
<argument index="6" name="ease_type" type="int" enum="Tween.EaseType" default="2">
</argument>
<argument index="7" name="delay" type="float" default="0">
</argument>
<description>
Animates [code]property[/code] of [code]object[/code] from [code]initial_val[/code] to [code]final_val[/code] for [code]duration[/code] seconds, [code]delay[/code] seconds later. Setting the initial value to [code]null[/code] uses the current value of the property.
Use [enum TransitionType] for [code]trans_type[/code] and [enum EaseType] for [code]ease_type[/code] parameters. These values control the timing and direction of the interpolation. See the class description for more information.
</description>
</method>
<method name="is_active" qualifiers="const">
<method name="is_running">
<return type="bool">
</return>
<description>
Returns [code]true[/code] if any tweens are currently running.
[b]Note:[/b] This method doesn't consider tweens that have ended.
Returns whether the [Tween] is currently running, i.e. it wasn't paused and it's not finished.
</description>
</method>
<method name="remove">
<method name="is_valid">
<return type="bool">
</return>
<description>
Returns whether the [Tween] is valid. A valid [Tween] is a [Tween] contained by the scene tree (i.e. the array from [method SceneTree.get_processed_tweens] will contain this [Tween]). [Tween] might become invalid when it has finished tweening or was killed, also when created with [code]Tween.new()[/code]. Invalid [Tween] can't have [Tweener]s appended, because it can't animate them. You can however still use [method interpolate_value].
</description>
</method>
<method name="kill">
<return type="void">
</return>
<argument index="0" name="object" type="Object">
</argument>
<argument index="1" name="key" type="StringName" default="&quot;&quot;">
<description>
Aborts all tweening operations and invalidates the [Tween].
</description>
</method>
<method name="parallel">
<return type="Tween">
</return>
<description>
Makes the next [Tweener] run parallely to the previous one. Example:
[codeblock]
var tween = create_tween()
tween.tween_property(...)
tween.parallel().tween_property(...)
tween.parallel().tween_property(...)
[/codeblock]
All [Tweener]s in the example will run at the same time.
You can make the [Tween] parallel by default by using [method set_parallel].
</description>
</method>
<method name="pause">
<return type="void">
</return>
<description>
Pauses the tweening. The animation can be resumed by using [method play].
</description>
</method>
<method name="play">
<return type="void">
</return>
<description>
Resumes a paused or stopped [Tween].
</description>
</method>
<method name="set_ease">
<return type="Tween">
</return>
<argument index="0" name="ease" type="int" enum="Tween.EaseType">
</argument>
<description>
Stops animation and removes a tween, given its object and property/method pair. By default, all tweens are removed, unless [code]key[/code] is specified.
Sets the default ease type for [PropertyTweener]s and [MethodTweener]s animated by this [Tween].
</description>
</method>
<method name="remove_all">
<return type="void">
<method name="set_loops">
<return type="Tween">
</return>
<description>
Stops animation and removes all tweens.
</description>
</method>
<method name="reset">
<return type="void">
</return>
<argument index="0" name="object" type="Object">
</argument>
<argument index="1" name="key" type="StringName" default="&quot;&quot;">
<argument index="0" name="loops" type="int" default="0">
</argument>
<description>
Resets a tween to its initial value (the one given, not the one before the tween), given its object and property/method pair. By default, all tweens are removed, unless [code]key[/code] is specified.
Sets the number of times the tweening sequence will be repeated, i.e. [code]set_loops(2)[/code] will run the animation twice.
Calling this method without arguments will make the [Tween] run infinitely, until it is either killed by [method kill] or by freeing bound node, or all the animated objects have been freed (which makes further animation impossible).
</description>
</method>
<method name="reset_all">
<return type="void">
<method name="set_parallel">
<return type="Tween">
</return>
<description>
Resets all tweens to their initial values (the ones given, not those before the tween).
</description>
</method>
<method name="resume">
<return type="void">
</return>
<argument index="0" name="object" type="Object">
</argument>
<argument index="1" name="key" type="StringName" default="&quot;&quot;">
<argument index="0" name="parallel" type="bool" default="true">
</argument>
<description>
Continues animating a stopped tween, given its object and property/method pair. By default, all tweens are resumed, unless [code]key[/code] is specified.
If [code]parallel[/code] is [code]true[/code], the [Tweener]s appended after this method will by default run simultanously, as opposed to sequentially.
</description>
</method>
<method name="resume_all">
<return type="void">
<method name="set_pause_mode">
<return type="Tween">
</return>
<description>
Continues animating all stopped tweens.
</description>
</method>
<method name="seek">
<return type="void">
</return>
<argument index="0" name="time" type="float">
<argument index="0" name="mode" type="int" enum="Tween.TweenPauseMode">
</argument>
<description>
Sets the interpolation to the given [code]time[/code] in seconds.
Determines the behavior of the [Tween] when the [SceneTree] is paused. Check [enum TweenPauseMode] for options.
Default value is [constant TWEEN_PAUSE_BOUND].
</description>
</method>
<method name="set_active">
<return type="void">
<method name="set_process_mode">
<return type="Tween">
</return>
<argument index="0" name="active" type="bool">
<argument index="0" name="mode" type="int" enum="Tween.TweenProcessMode">
</argument>
<description>
Activates/deactivates the tween. See also [method stop_all] and [method resume_all].
Determines whether the [Tween] should run during idle frame (see [method Node._process]) or physics frame (see [method Node._physics_process].
Default value is [constant TWEEN_PROCESS_IDLE].
</description>
</method>
<method name="start">
<return type="void">
<method name="set_speed_scale">
<return type="Tween">
</return>
<argument index="0" name="speed" type="float">
</argument>
<description>
Starts the tween. You can define animations both before and after this.
Scales the speed of tweening. This affects all [Tweener]s and their delays.
</description>
</method>
<method name="set_trans">
<return type="Tween">
</return>
<argument index="0" name="trans" type="int" enum="Tween.TransitionType">
</argument>
<description>
Sets the default transition type for [PropertyTweener]s and [MethodTweener]s animated by this [Tween].
</description>
</method>
<method name="stop">
<return type="void">
</return>
<argument index="0" name="object" type="Object">
</argument>
<argument index="1" name="key" type="StringName" default="&quot;&quot;">
</argument>
<description>
Stops a tween, given its object and property/method pair. By default, all tweens are stopped, unless [code]key[/code] is specified.
Stops the tweening and resets the [Tween] to its initial state. This will not remove any appended [Tweener]s.
</description>
</method>
<method name="stop_all">
<return type="void">
<method name="tween_callback">
<return type="CallbackTweener">
</return>
<argument index="0" name="callback" type="Callable">
</argument>
<description>
Stops animating all tweens.
Creates and appends a [CallbackTweener]. This method can be used to call an arbitrary method in any object. Use [method Callable.bind] to bind additional arguments for the call.
Example: object that keeps shooting every 1 second.
[codeblock]
var tween = get_tree().create_tween().set_loops()
tween.tween_callback(shoot).set_delay(1)
[/codeblock]
Example: turning a sprite red and then blue, with 2 second delay.
[codeblock]
var tween = get_tree().create_tween()
tween.tween_callback($Sprite.set_modulate.bind(Color.red)).set_delay(2)
tween.tween_callback($Sprite.set_modulate.bind(Color.blue)).set_delay(2)
[/codeblock]
</description>
</method>
<method name="targeting_method">
<return type="void">
<method name="tween_interval">
<return type="IntervalTweener">
</return>
<argument index="0" name="object" type="Object">
</argument>
<argument index="1" name="method" type="StringName">
</argument>
<argument index="2" name="initial" type="Object">
</argument>
<argument index="3" name="initial_method" type="StringName">
</argument>
<argument index="4" name="final_val" type="Variant">
</argument>
<argument index="5" name="duration" type="float">
</argument>
<argument index="6" name="trans_type" type="int" enum="Tween.TransitionType" default="0">
</argument>
<argument index="7" name="ease_type" type="int" enum="Tween.EaseType" default="2">
</argument>
<argument index="8" name="delay" type="float" default="0">
<argument index="0" name="time" type="float">
</argument>
<description>
Animates [code]method[/code] of [code]object[/code] from the value returned by [code]initial_method[/code] to [code]final_val[/code] for [code]duration[/code] seconds, [code]delay[/code] seconds later. Methods are animated by calling them with consecutive values.
Use [enum TransitionType] for [code]trans_type[/code] and [enum EaseType] for [code]ease_type[/code] parameters. These values control the timing and direction of the interpolation. See the class description for more information.
Creates and appends an [IntervalTweener]. This method can be used to create delays in the tween animation, as an alternative for using the delay in other [Tweener]s or when there's no animation (in which case the [Tween] acts as a timer). [code]time[/code] is the length of the interval, in seconds.
Example: creating an interval in code execution.
[codeblock]
#... some code
var tween = create_tween()
tween.tween_interval(2)
await tween.finished
#... more code
[/codeblock]
Example: creating an object that moves back and forth and jumps every few seconds.
[codeblock]
var tween = create_tween().set_loops()
tween.tween_property("position:x", 200, 1).as_relative()
tween.tween_callback(jump)
tween.tween_interval(2)
tween.tween_property("position:x", -200, 1).as_relative()
tween.tween_callback(jump)
tween.tween_interval(2)
[/codeblock]
</description>
</method>
<method name="targeting_property">
<return type="void">
<method name="tween_method">
<return type="MethodTweener">
</return>
<argument index="0" name="method" type="Callable">
</argument>
<argument index="1" name="from" type="float">
</argument>
<argument index="2" name="to" type="float">
</argument>
<argument index="3" name="duration" type="float">
</argument>
<description>
Creates and appends a [MethodTweener]. This method is similar to a combination of [method tween_callback] and [method tween_property]. It calls a method over time with a tweened value provided as an argument. The value is tweened between [code]from[/code] and [code]to[/code] over the time specified by [code]duration[/code], in seconds. Use [method Callable.bind] to bind additional arguments for the call. You can use [method MethodTweener.set_ease] and [method MethodTweener.set_trans] to tweak the easing and transition of the value or [method MethodTweener.set_delay] to delay the tweening.
Example: making a 3D object look from one point to another point.
[codeblock]
var tween = create_tween()
tween.tween_method(look_at.bind(Vector3.UP), Vector3(-1, 0, -1), Vector3(1, 0, -1), 1) #the look_at() method takes up vector as second argument
[/codeblock]
Example: setting a text of a [Label], using an intermediate method and after a delay.
[codeblock]
func _ready():
var tween = create_tween()
tween.tween_method(set_label_text, 0, 10, 1).set_delay(1)
func set_label_text(value: int):
$Label.text = "Counting " + str(value)
[/codeblock]
</description>
</method>
<method name="tween_property">
<return type="PropertyTweener">
</return>
<argument index="0" name="object" type="Object">
</argument>
<argument index="1" name="property" type="NodePath">
</argument>
<argument index="2" name="initial" type="Object">
<argument index="2" name="final_val" type="Variant">
</argument>
<argument index="3" name="initial_val" type="NodePath">
</argument>
<argument index="4" name="final_val" type="Variant">
</argument>
<argument index="5" name="duration" type="float">
</argument>
<argument index="6" name="trans_type" type="int" enum="Tween.TransitionType" default="0">
</argument>
<argument index="7" name="ease_type" type="int" enum="Tween.EaseType" default="2">
</argument>
<argument index="8" name="delay" type="float" default="0">
<argument index="3" name="duration" type="float">
</argument>
<description>
Animates [code]property[/code] of [code]object[/code] from the current value of the [code]initial_val[/code] property of [code]initial[/code] to [code]final_val[/code] for [code]duration[/code] seconds, [code]delay[/code] seconds later.
Use [enum TransitionType] for [code]trans_type[/code] and [enum EaseType] for [code]ease_type[/code] parameters. These values control the timing and direction of the interpolation. See the class description for more information.
</description>
</method>
<method name="tell" qualifiers="const">
<return type="float">
</return>
<description>
Returns the current time of the tween.
Creates and appends a [PropertyTweener]. This method tweens a [code]property[/code] of an [code]object[/code] between an initial value and [code]final_val[/code] in a span of time equal to [code]duration[/code], in seconds. The initial value by default is a value at the time the tweening of the [PropertyTweener] start. For example:
[codeblock]
var tween = create_tween()
tween.tween_property($Sprite, "position", Vector2(100, 200)
tween.tween_property($Sprite, "position", Vector2(200, 300)
[/codeblock]
will move the sprite to position (100, 200) and then to (200, 300). If you use [method PropertyTweener.from] or [method PropertyTweener.from_current], the starting position will be overwritten by the given value instead. See other methods in [PropertyTweener] to see how the tweening can be tweaked further.
[b]Note:[/b] You can find the correct property name by hovering over the property in the Inspector. You can also provide the components of a property directly by using [code]"property:component"[/code] (eg. [code]position:x[/code]), where it would only apply to that particular component.
Example: moving object twice from the same position, with different transition types.
[codeblock]
var tween = create_tween()
tween.tween_property($Sprite, "position", Vector2.RIGHT * 300).as_relative().set_trans(Tween.TRANS_SINE)
tween.tween_property($Sprite, "position", Vector2.RIGHT * 300).as_relative().from_current().set_trans(Tween.TRANS_EXPO)
[/codeblock]
</description>
</method>
</methods>
<members>
<member name="playback_process_mode" type="int" setter="set_tween_process_mode" getter="get_tween_process_mode" enum="Tween.TweenProcessMode" default="1">
The tween's animation process thread. See [enum TweenProcessMode].
</member>
<member name="playback_speed" type="float" setter="set_speed_scale" getter="get_speed_scale" default="1.0">
The tween's speed multiplier. For example, set it to [code]1.0[/code] for normal speed, [code]2.0[/code] for two times normal speed, or [code]0.5[/code] for half of the normal speed. A value of [code]0[/code] pauses the animation, but see also [method set_active] or [method stop_all] for this.
</member>
<member name="repeat" type="bool" setter="set_repeat" getter="is_repeat" default="false">
If [code]true[/code], the tween loops.
</member>
</members>
<signals>
<signal name="tween_all_completed">
<signal name="finished">
<description>
Emitted when all processes in a tween end.
Emitted when the [Tween] has finished all tweening. Never emitted when the [Tween] is set to infinite looping (see [method set_loops]).
[b]Note:[/b] The [Tween] is removed (invalidated) after this signal is emitted, but it doesn't happen immediately, but on the next processing frame. Calling [method stop] inside the signal callback will preserve the [Tween].
</description>
</signal>
<signal name="tween_completed">
<argument index="0" name="object" type="Object">
</argument>
<argument index="1" name="key" type="NodePath">
<signal name="loop_finished">
<argument index="0" name="loop_count" type="int">
</argument>
<description>
Emitted when a tween ends.
Emitted when a full loop is complete (see [method set_loops]), providing the loop index. This signal is not emitted after final loop, use [signal finished] instead for this case.
</description>
</signal>
<signal name="tween_started">
<argument index="0" name="object" type="Object">
</argument>
<argument index="1" name="key" type="NodePath">
<signal name="step_finished">
<argument index="0" name="idx" type="int">
</argument>
<description>
Emitted when a tween starts.
</description>
</signal>
<signal name="tween_step">
<argument index="0" name="object" type="Object">
</argument>
<argument index="1" name="key" type="NodePath">
</argument>
<argument index="2" name="elapsed" type="float">
</argument>
<argument index="3" name="value" type="Object">
</argument>
<description>
Emitted at each step of the animation.
Emitted when one step of the [Tween] is complete, providing the step index. One step is either a single [Tweener] or a group of [Tweener]s running parallelly.
</description>
</signal>
</signals>
<constants>
<constant name="TWEEN_PROCESS_PHYSICS" value="0" enum="TweenProcessMode">
The tween updates with the [code]_physics_process[/code] callback.
The [Tween] updates during physics frame.
</constant>
<constant name="TWEEN_PROCESS_IDLE" value="1" enum="TweenProcessMode">
The tween updates with the [code]_process[/code] callback.
The [Tween] updates during idle
</constant>
<constant name="TWEEN_PAUSE_BOUND" value="0" enum="TweenPauseMode">
</constant>
<constant name="TWEEN_PAUSE_STOP" value="1" enum="TweenPauseMode">
</constant>
<constant name="TWEEN_PAUSE_PROCESS" value="2" enum="TweenPauseMode">
</constant>
<constant name="TRANS_LINEAR" value="0" enum="TransitionType">
The animation is interpolated linearly.
</constant>
<constant name="TRANS_SINE" value="1" enum="TransitionType">
The animation is interpolated using a sine function.
</constant>
<constant name="TRANS_QUINT" value="2" enum="TransitionType">
The animation is interpolated with a quintic (to the power of 5) function.
</constant>
<constant name="TRANS_QUART" value="3" enum="TransitionType">
The animation is interpolated with a quartic (to the power of 4) function.
</constant>
<constant name="TRANS_QUAD" value="4" enum="TransitionType">
The animation is interpolated with a quadratic (to the power of 2) function.
</constant>
<constant name="TRANS_EXPO" value="5" enum="TransitionType">
The animation is interpolated with an exponential (to the power of x) function.
</constant>
<constant name="TRANS_ELASTIC" value="6" enum="TransitionType">
The animation is interpolated with elasticity, wiggling around the edges.
</constant>
<constant name="TRANS_CUBIC" value="7" enum="TransitionType">
The animation is interpolated with a cubic (to the power of 3) function.
</constant>
<constant name="TRANS_CIRC" value="8" enum="TransitionType">
The animation is interpolated with a function using square roots.
</constant>
<constant name="TRANS_BOUNCE" value="9" enum="TransitionType">
The animation is interpolated by bouncing at the end.
</constant>
<constant name="TRANS_BACK" value="10" enum="TransitionType">
The animation is interpolated backing out at ends.
</constant>
<constant name="EASE_IN" value="0" enum="EaseType">
The interpolation starts slowly and speeds up towards the end.
</constant>
<constant name="EASE_OUT" value="1" enum="EaseType">
The interpolation starts quickly and slows down towards the end.
</constant>
<constant name="EASE_IN_OUT" value="2" enum="EaseType">
A combination of [constant EASE_IN] and [constant EASE_OUT]. The interpolation is slowest at both ends.
</constant>
<constant name="EASE_OUT_IN" value="3" enum="EaseType">
A combination of [constant EASE_IN] and [constant EASE_OUT]. The interpolation is fastest at both ends.
</constant>
</constants>
</class>

22
doc/classes/Tweener.xml Normal file
View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Tweener" inherits="RefCounted" version="4.0">
<brief_description>
Abstract class for all Tweeners used by [Tween].
</brief_description>
<description>
Tweeners are objects that perform a specific animating task, e.g. interpolating a property or calling a method at a given time. A [Tweener] can't be created manually, you need to use a dedicated method from [Tween] or [Node].
</description>
<tutorials>
</tutorials>
<methods>
</methods>
<signals>
<signal name="finished">
<description>
Emited when the [Tweener] has just finished its job.
</description>
</signal>
</signals>
<constants>
</constants>
</class>

File diff suppressed because it is too large Load Diff

View File

@ -31,10 +31,33 @@
#ifndef TWEEN_H
#define TWEEN_H
#include "scene/main/node.h"
#include "core/object/ref_counted.h"
class Tween : public Node {
GDCLASS(Tween, Node);
class Tween;
class Node;
class Tweener : public RefCounted {
GDCLASS(Tweener, RefCounted);
public:
virtual void set_tween(Ref<Tween> p_tween);
virtual void start() = 0;
virtual bool step(float &r_delta) = 0;
protected:
static void _bind_methods();
Ref<Tween> tween;
float elapsed_time = 0;
bool finished = false;
};
class PropertyTweener;
class IntervalTweener;
class CallbackTweener;
class MethodTweener;
class Tween : public RefCounted {
GDCLASS(Tween, RefCounted);
public:
enum TweenProcessMode {
@ -42,6 +65,12 @@ public:
TWEEN_PROCESS_IDLE,
};
enum TweenPauseMode {
TWEEN_PAUSE_BOUND,
TWEEN_PAUSE_STOP,
TWEEN_PAUSE_PROCESS,
};
enum TransitionType {
TRANS_LINEAR,
TRANS_SINE,
@ -54,8 +83,7 @@ public:
TRANS_CIRC,
TRANS_BOUNCE,
TRANS_BACK,
TRANS_COUNT,
TRANS_MAX
};
enum EaseType {
@ -63,130 +91,187 @@ public:
EASE_OUT,
EASE_IN_OUT,
EASE_OUT_IN,
EASE_COUNT,
EASE_MAX
};
private:
enum InterpolateType {
INTER_PROPERTY,
INTER_METHOD,
FOLLOW_PROPERTY,
FOLLOW_METHOD,
TARGETING_PROPERTY,
TARGETING_METHOD,
INTER_CALLBACK,
};
TweenProcessMode process_mode = TweenProcessMode::TWEEN_PROCESS_IDLE;
TweenPauseMode pause_mode = TweenPauseMode::TWEEN_PAUSE_STOP;
TransitionType default_transition = TransitionType::TRANS_LINEAR;
EaseType default_ease = EaseType::EASE_IN_OUT;
ObjectID bound_node;
struct InterpolateData {
bool active = false;
InterpolateType type = INTER_CALLBACK;
bool finish = false;
bool call_deferred = false;
real_t elapsed = 0.0;
ObjectID id;
Vector<StringName> key;
StringName concatenated_key;
Variant initial_val;
Variant delta_val;
Variant final_val;
ObjectID target_id;
Vector<StringName> target_key;
real_t duration = 0.0;
TransitionType trans_type = TransitionType::TRANS_BACK;
EaseType ease_type = EaseType::EASE_COUNT;
real_t delay = 0.0;
int args = 0;
Variant arg[5];
int uid = 0;
};
Vector<List<Ref<Tweener>>> tweeners;
int current_step = -1;
int loops = 1;
int loops_done = 0;
float speed_scale = 1;
String autoplay;
TweenProcessMode tween_process_mode = TWEEN_PROCESS_IDLE;
bool repeat = false;
float speed_scale = 1.0;
mutable int pending_update = 0;
int uid = 0;
bool was_stopped = false;
List<InterpolateData> interpolates;
struct PendingCommand {
StringName key;
int args = 0;
Variant arg[10];
};
List<PendingCommand> pending_commands;
void _add_pending_command(StringName p_key, const Variant &p_arg1 = Variant(), const Variant &p_arg2 = Variant(), const Variant &p_arg3 = Variant(), const Variant &p_arg4 = Variant(), const Variant &p_arg5 = Variant(), const Variant &p_arg6 = Variant(), const Variant &p_arg7 = Variant(), const Variant &p_arg8 = Variant(), const Variant &p_arg9 = Variant(), const Variant &p_arg10 = Variant());
void _process_pending_commands();
bool is_bound = false;
bool started = false;
bool running = true;
bool dead = false;
bool invalid = true;
bool default_parallel = false;
bool parallel_enabled = false;
typedef real_t (*interpolater)(real_t t, real_t b, real_t c, real_t d);
static interpolater interpolaters[TRANS_COUNT][EASE_COUNT];
static interpolater interpolaters[TRANS_MAX][EASE_MAX];
real_t _run_equation(TransitionType p_trans_type, EaseType p_ease_type, real_t t, real_t b, real_t c, real_t d);
Variant &_get_delta_val(InterpolateData &p_data);
Variant _get_initial_val(const InterpolateData &p_data) const;
Variant _get_final_val(const InterpolateData &p_data) const;
Variant _run_equation(InterpolateData &p_data);
bool _calc_delta_val(const Variant &p_initial_val, const Variant &p_final_val, Variant &p_delta_val);
bool _apply_tween_value(InterpolateData &p_data, Variant &value);
void _tween_process(float p_delta);
void _remove_by_uid(int uid);
void _push_interpolate_data(InterpolateData &p_data);
void _build_interpolation(InterpolateType p_interpolation_type, Object *p_object, NodePath *p_property, StringName *p_method, Variant p_initial_val, Variant p_final_val, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay);
void start_tweeners();
protected:
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
void _notification(int p_what);
static void _bind_methods();
public:
bool is_active() const;
void set_active(bool p_active);
Ref<PropertyTweener> tween_property(Object *p_target, NodePath p_property, Variant p_to, float p_duration);
Ref<IntervalTweener> tween_interval(float p_time);
Ref<CallbackTweener> tween_callback(Callable p_callback);
Ref<MethodTweener> tween_method(Callable p_callback, float p_from, float p_to, float p_duration);
Ref<Tween> append(Ref<Tweener> p_tweener);
bool is_repeat() const;
void set_repeat(bool p_repeat);
bool custom_step(float p_delta);
void stop();
void pause();
void play();
void kill();
void set_tween_process_mode(TweenProcessMode p_mode);
TweenProcessMode get_tween_process_mode() const;
bool is_running();
void set_valid(bool p_valid);
bool is_valid();
void set_speed_scale(float p_speed);
float get_speed_scale() const;
Ref<Tween> bind_node(Node *p_node);
Ref<Tween> set_process_mode(TweenProcessMode p_mode);
TweenProcessMode get_process_mode();
Ref<Tween> set_pause_mode(TweenPauseMode p_mode);
TweenPauseMode get_pause_mode();
void start();
void reset(Object *p_object, StringName p_key);
void reset_all();
void stop(Object *p_object, StringName p_key);
void stop_all();
void resume(Object *p_object, StringName p_key);
void resume_all();
void remove(Object *p_object, StringName p_key);
void remove_all();
Ref<Tween> set_parallel(bool p_parallel);
Ref<Tween> set_loops(int p_loops);
Ref<Tween> set_speed_scale(float p_speed);
Ref<Tween> set_trans(TransitionType p_trans);
TransitionType get_trans();
Ref<Tween> set_ease(EaseType p_ease);
EaseType get_ease();
void seek(real_t p_time);
real_t tell() const;
real_t get_runtime() const;
Ref<Tween> parallel();
Ref<Tween> chain();
void interpolate_property(Object *p_object, NodePath p_property, Variant p_initial_val, Variant p_final_val, real_t p_duration, TransitionType p_trans_type = TRANS_LINEAR, EaseType p_ease_type = EASE_IN_OUT, real_t p_delay = 0);
void interpolate_method(Object *p_object, StringName p_method, Variant p_initial_val, Variant p_final_val, real_t p_duration, TransitionType p_trans_type = TRANS_LINEAR, EaseType p_ease_type = EASE_IN_OUT, real_t p_delay = 0);
void interpolate_callback(Object *p_object, real_t p_duration, String p_callback, VARIANT_ARG_DECLARE);
void interpolate_deferred_callback(Object *p_object, real_t p_duration, String p_callback, VARIANT_ARG_DECLARE);
void follow_property(Object *p_object, NodePath p_property, Variant p_initial_val, Object *p_target, NodePath p_target_property, real_t p_duration, TransitionType p_trans_type = TRANS_LINEAR, EaseType p_ease_type = EASE_IN_OUT, real_t p_delay = 0);
void follow_method(Object *p_object, StringName p_method, Variant p_initial_val, Object *p_target, StringName p_target_method, real_t p_duration, TransitionType p_trans_type = TRANS_LINEAR, EaseType p_ease_type = EASE_IN_OUT, real_t p_delay = 0);
void targeting_property(Object *p_object, NodePath p_property, Object *p_initial, NodePath p_initial_property, Variant p_final_val, real_t p_duration, TransitionType p_trans_type = TRANS_LINEAR, EaseType p_ease_type = EASE_IN_OUT, real_t p_delay = 0);
void targeting_method(Object *p_object, StringName p_method, Object *p_initial, StringName p_initial_method, Variant p_final_val, real_t p_duration, TransitionType p_trans_type = TRANS_LINEAR, EaseType p_ease_type = EASE_IN_OUT, real_t p_delay = 0);
real_t run_equation(TransitionType p_trans_type, EaseType p_ease_type, real_t t, real_t b, real_t c, real_t d);
Variant interpolate_variant(Variant p_initial_val, Variant p_delta_val, float p_time, float p_duration, Tween::TransitionType p_trans, Tween::EaseType p_ease);
Variant calculate_delta_value(Variant p_intial_val, Variant p_final_val);
Tween();
~Tween();
bool step(float p_delta);
bool should_pause();
Tween() {}
};
VARIANT_ENUM_CAST(Tween::TweenPauseMode);
VARIANT_ENUM_CAST(Tween::TweenProcessMode);
VARIANT_ENUM_CAST(Tween::TransitionType);
VARIANT_ENUM_CAST(Tween::EaseType);
class PropertyTweener : public Tweener {
GDCLASS(PropertyTweener, Tweener);
public:
Ref<PropertyTweener> from(Variant p_value);
Ref<PropertyTweener> from_current();
Ref<PropertyTweener> as_relative();
Ref<PropertyTweener> set_trans(Tween::TransitionType p_trans);
Ref<PropertyTweener> set_ease(Tween::EaseType p_ease);
Ref<PropertyTweener> set_delay(float p_delay);
void set_tween(Ref<Tween> p_tween) override;
void start() override;
bool step(float &r_delta) override;
PropertyTweener(Object *p_target, NodePath p_property, Variant p_to, float p_duration);
PropertyTweener();
protected:
static void _bind_methods();
private:
ObjectID target;
Vector<StringName> property;
Variant initial_val;
Variant base_final_val;
Variant final_val;
Variant delta_val;
float duration = 0;
Tween::TransitionType trans_type = Tween::TRANS_MAX; // This is set inside set_tween();
Tween::EaseType ease_type = Tween::EASE_MAX;
float delay = 0;
bool do_continue = true;
bool relative = false;
};
class IntervalTweener : public Tweener {
GDCLASS(IntervalTweener, Tweener);
public:
void start() override;
bool step(float &r_delta) override;
IntervalTweener(float p_time);
IntervalTweener();
private:
float duration = 0;
};
class CallbackTweener : public Tweener {
GDCLASS(CallbackTweener, Tweener);
public:
Ref<CallbackTweener> set_delay(float p_delay);
void start() override;
bool step(float &r_delta) override;
CallbackTweener(Callable p_callback);
CallbackTweener();
protected:
static void _bind_methods();
private:
Callable callback;
float delay = 0;
};
class MethodTweener : public Tweener {
GDCLASS(MethodTweener, Tweener);
public:
Ref<MethodTweener> set_trans(Tween::TransitionType p_trans);
Ref<MethodTweener> set_ease(Tween::EaseType p_ease);
Ref<MethodTweener> set_delay(float p_delay);
void set_tween(Ref<Tween> p_tween) override;
void start() override;
bool step(float &r_delta) override;
MethodTweener(Callable p_callback, float p_from, float p_to, float p_duration);
MethodTweener();
protected:
static void _bind_methods();
private:
float duration = 0;
float delay = 0;
Tween::TransitionType trans_type = Tween::TRANS_MAX;
Tween::EaseType ease_type = Tween::EASE_MAX;
Ref<Tween> tween;
Variant initial_val;
Variant delta_val;
Callable callback;
};
#endif

View File

@ -35,6 +35,7 @@
#include "core/object/message_queue.h"
#include "core/string/print_string.h"
#include "instance_placeholder.h"
#include "scene/animation/tween.h"
#include "scene/debugger/scene_debugger.h"
#include "scene/resources/packed_scene.h"
#include "scene/scene_string_names.h"
@ -1683,6 +1684,13 @@ int Node::get_index() const {
return data.pos;
}
Ref<Tween> Node::create_tween() {
ERR_FAIL_COND_V_MSG(!data.tree, nullptr, "Can't create Tween when not inside scene tree.");
Ref<Tween> tween = get_tree()->create_tween();
tween->bind_node(this);
return tween;
}
void Node::remove_and_skip() {
ERR_FAIL_COND(!data.parent);
@ -2552,6 +2560,7 @@ void Node::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_physics_processing_internal"), &Node::is_physics_processing_internal);
ClassDB::bind_method(D_METHOD("get_tree"), &Node::get_tree);
ClassDB::bind_method(D_METHOD("create_tween"), &Node::create_tween);
ClassDB::bind_method(D_METHOD("duplicate", "flags"), &Node::duplicate, DEFVAL(DUPLICATE_USE_INSTANCING | DUPLICATE_SIGNALS | DUPLICATE_GROUPS | DUPLICATE_SCRIPTS));
ClassDB::bind_method(D_METHOD("replace_by", "node", "keep_groups"), &Node::replace_by, DEFVAL(false));

View File

@ -41,6 +41,9 @@
class Viewport;
class SceneState;
class Tween;
class PropertyTweener;
class Node : public Object {
GDCLASS(Node, Object);
OBJ_CATEGORY("Nodes");
@ -308,6 +311,8 @@ public:
void remove_and_skip();
int get_index() const;
Ref<Tween> create_tween();
void print_tree();
void print_tree_pretty();

View File

@ -41,6 +41,7 @@
#include "core/os/os.h"
#include "core/string/print_string.h"
#include "node.h"
#include "scene/animation/tween.h"
#include "scene/debugger/scene_debugger.h"
#include "scene/resources/font.h"
#include "scene/resources/material.h"
@ -412,6 +413,9 @@ bool SceneTree::physics_process(float p_time) {
_notify_group_pause("physics_process", Node::NOTIFICATION_PHYSICS_PROCESS);
_flush_ugc();
MessageQueue::get_singleton()->flush(); //small little hack
process_tweens(p_time, true);
flush_transform_notifications();
call_group_flags(GROUP_CALL_REALTIME, "_viewports", "update_worlds");
root_lock--;
@ -478,6 +482,8 @@ bool SceneTree::process(float p_time) {
E = N;
}
process_tweens(p_time, false);
flush_transform_notifications(); //additional transforms after timers update
_call_idle_callbacks();
@ -512,6 +518,32 @@ bool SceneTree::process(float p_time) {
return _quit;
}
void SceneTree::process_tweens(float p_delta, bool p_physics) {
// This methods works similarly to how SceneTreeTimers are handled.
List<Ref<Tween>>::Element *L = tweens.back();
for (List<Ref<Tween>>::Element *E = tweens.front(); E;) {
List<Ref<Tween>>::Element *N = E->next();
// Don't process if paused or process mode doesn't match.
if ((paused && E->get()->should_pause()) || (p_physics == (E->get()->get_process_mode() == Tween::TWEEN_PROCESS_IDLE))) {
if (E == L) {
break;
}
E = N;
continue;
}
if (!E->get()->step(p_delta)) {
E->get()->set_valid(false);
tweens.erase(E);
}
if (E == L) {
break;
}
E = N;
}
}
void SceneTree::finalize() {
_flush_delete_queue();
@ -1091,6 +1123,27 @@ Ref<SceneTreeTimer> SceneTree::create_timer(float p_delay_sec, bool p_process_al
return stt;
}
Ref<Tween> SceneTree::create_tween() {
Ref<Tween> tween;
tween.instance();
tween->set_valid(true);
tweens.push_back(tween);
return tween;
}
Array SceneTree::get_processed_tweens() {
Array ret;
ret.resize(tweens.size());
int i = 0;
for (List<Ref<Tween>>::Element *E = tweens.front(); E; E = E->next()) {
ret[i] = E->get();
i++;
}
return ret;
}
void SceneTree::_network_peer_connected(int p_id) {
emit_signal("network_peer_connected", p_id);
}
@ -1199,6 +1252,8 @@ void SceneTree::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_paused"), &SceneTree::is_paused);
ClassDB::bind_method(D_METHOD("create_timer", "time_sec", "process_always"), &SceneTree::create_timer, DEFVAL(true));
ClassDB::bind_method(D_METHOD("create_tween"), &SceneTree::create_tween);
ClassDB::bind_method(D_METHOD("get_processed_tweens"), &SceneTree::get_processed_tweens);
ClassDB::bind_method(D_METHOD("get_node_count"), &SceneTree::get_node_count);
ClassDB::bind_method(D_METHOD("get_frame"), &SceneTree::get_frame);

View File

@ -47,6 +47,7 @@ class Window;
class Material;
class Mesh;
class SceneDebugger;
class Tween;
class SceneTreeTimer : public RefCounted {
GDCLASS(SceneTreeTimer, RefCounted);
@ -151,6 +152,7 @@ private:
//void _call_group(uint32_t p_call_flags,const StringName& p_group,const StringName& p_function,const Variant& p_arg1,const Variant& p_arg2);
List<Ref<SceneTreeTimer>> timers;
List<Ref<Tween>> tweens;
///network///
@ -171,6 +173,7 @@ private:
void node_added(Node *p_node);
void node_removed(Node *p_node);
void node_renamed(Node *p_node);
void process_tweens(float p_delta, bool p_physics_frame);
Group *add_to_group(const StringName &p_group, Node *p_node);
void remove_from_group(const StringName &p_group, Node *p_node);
@ -318,6 +321,8 @@ public:
Error reload_current_scene();
Ref<SceneTreeTimer> create_timer(float p_delay_sec, bool p_process_always = true);
Ref<Tween> create_tween();
Array get_processed_tweens();
//used by Main::start, don't use otherwise
void add_current_scene(Node *p_current);

View File

@ -407,6 +407,11 @@ void register_scene_types() {
ClassDB::register_class<AnimationPlayer>();
ClassDB::register_class<Tween>();
ClassDB::register_virtual_class<Tweener>();
ClassDB::register_class<PropertyTweener>();
ClassDB::register_class<IntervalTweener>();
ClassDB::register_class<CallbackTweener>();
ClassDB::register_class<MethodTweener>();
ClassDB::register_class<AnimationTree>();
ClassDB::register_class<AnimationNode>();

View File

@ -297,7 +297,7 @@ static real_t out_in(real_t t, real_t b, real_t c, real_t d) {
}
}; // namespace back
Tween::interpolater Tween::interpolaters[Tween::TRANS_COUNT][Tween::EASE_COUNT] = {
Tween::interpolater Tween::interpolaters[Tween::TRANS_MAX][Tween::EASE_MAX] = {
{ &linear::in, &linear::out, &linear::in_out, &linear::out_in },
{ &sine::in, &sine::out, &sine::in_out, &sine::out_in },
{ &quint::in, &quint::out, &quint::in_out, &quint::out_in },
@ -311,7 +311,7 @@ Tween::interpolater Tween::interpolaters[Tween::TRANS_COUNT][Tween::EASE_COUNT]
{ &back::in, &back::out, &back::in_out, &back::out_in },
};
real_t Tween::_run_equation(TransitionType p_trans_type, EaseType p_ease_type, real_t t, real_t b, real_t c, real_t d) {
real_t Tween::run_equation(TransitionType p_trans_type, EaseType p_ease_type, real_t t, real_t b, real_t c, real_t d) {
interpolater cb = interpolaters[p_trans_type][p_ease_type];
ERR_FAIL_COND_V(cb == NULL, b);