Implemented TweenChannel.

This commit is contained in:
blujai831 2024-01-06 13:09:18 -08:00
parent 73bcc8c315
commit 1437194677
No known key found for this signature in database
GPG Key ID: DDC31A0363AA5E66
1 changed files with 62 additions and 0 deletions

62
util/TweenChannel.gd Normal file
View File

@ -0,0 +1,62 @@
class_name TweenChannel extends RefCounted
## Arbitrates between concurrent tweens, e.g. of the same property.
## Emitted when a tween finishes or is killed.
signal terminated(what: Tween)
## How to arbitrate between a tween request and an already running tween.
enum ArbitrationMode {
YIELD, ## Request yields until there is no longer any current tween.
REPLACE, ## Rather than request yielding, current tween is killed.
IGNORE ## Rather than request yielding, request is denied (returns null).
}
## How to arbitrate between a tween request and an already running tween.
var arbitration_mode := ArbitrationMode.YIELD
## Tween currently running if any, else null.
var current_tween: Tween = null
## Returns target.create_tween() if and when arbitration_mode allows.
##
## "If:" if arbitration_mode is IGNORE and there is a current tween,
## then null is returned.
## "When:" if arbitration_mode is YIELD and there is a current tween,
## then this function yields until there is not.
## (If arbitration_mode is REPLACE and there is a current tween,
## then this function returns target.create_tween() immediately,
## and the preexisting current tween is killed.)
func create_tween(target: Variant) -> Tween:
assert(target is Node or target is SceneTree)
match arbitration_mode:
ArbitrationMode.YIELD:
while current_tween:
await terminated
ArbitrationMode.REPLACE:
if current_tween and current_tween.is_valid():
current_tween.kill()
ArbitrationMode.IGNORE:
if current_tween:
return null
current_tween = target.create_tween()
_cleanup_later(current_tween)
return current_tween
## Yields until the given tween has terminated.
##
## The given tween must have been created with self.create_tween.
func sync(what: Tween) -> void:
var last_terminated: Tween = null
while last_terminated != what:
last_terminated = await terminated
## Yields until the given tween is invalid and then cleans up bookkeeping.
##
## Bookkeeping cleanup entails the following:
## - if the given tween is the current tween, clears the current tween;
## - terminated is emitted with the given tween as the argument.
func _cleanup_later(what: Tween) -> void:
while what.is_valid():
await Wait.tick()
if current_tween == what:
current_tween = null
terminated.emit(what)