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)