Created
June 15, 2026 16:33
-
-
Save etodd/3fbc8224005b9e6dd8b8a2aed3efdf01 to your computer and use it in GitHub Desktop.
My GDScript utility functions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class_name Util | |
| extends Node | |
| ## Call this function every frame to move the given value toward the target in | |
| ## a smooth, springy, FRAMERATE INDEPENDENT way, such that it will take | |
| ## "duration" to reach within 1% of the target. | |
| ## | |
| ## Credit: https://x.com/FreyaHolmer/status/1757836988495847568 | |
| static func smooth_toward(current: float, target: float, duration: float, delta: float) -> float: | |
| return lerpf(current, target, 1.0 - pow(0.01, delta / duration)) | |
| ## Show or hide the given CanvasItem with a nice fade. The animation can be | |
| ## interrupted by another show_with_fade call and it will do the right thing. | |
| static func show_with_fade(control: CanvasItem, show: bool = true, duration: float = 0.25) -> void: | |
| var existing: Variant = control.get_meta("show_with_fade_tween", false) | |
| var existing_tween: Tween = existing as Tween if existing else null | |
| var tweening: bool = existing_tween and existing_tween.is_running() | |
| if tweening: | |
| var tweening_target: bool = existing_tween.get_meta("target", false) | |
| if tweening_target == show: | |
| # already tweening toward desired state | |
| return | |
| existing_tween.kill() | |
| if (not tweening) and (control.visible && control.modulate.a == 1.0) == show: | |
| # already desired state | |
| return | |
| control.visible = true | |
| var tween: Tween = control.create_tween() | |
| control.set_meta("show_with_fade_tween", tween) | |
| tween.set_meta("target", show) | |
| if show: | |
| control.modulate = Color.TRANSPARENT | |
| tween.tween_property(control, "modulate", Color.WHITE, duration) | |
| else: | |
| tween.tween_property(control, "modulate", Color.TRANSPARENT, duration) | |
| tween.tween_callback(control.hide) | |
| await tween.finished | |
| ## Await this function to load a resource asynchronously. | |
| static func load_async(requester: Node, | |
| path: String, | |
| type_hint: String = "", | |
| use_sub_threads: bool = false, | |
| cache_mode: ResourceLoader.CacheMode = ResourceLoader.CACHE_MODE_REUSE | |
| ) -> Resource: | |
| ResourceLoader.load_threaded_request(path, type_hint, use_sub_threads, cache_mode) | |
| while ResourceLoader.load_threaded_get_status(path) == ResourceLoader.THREAD_LOAD_IN_PROGRESS: | |
| await requester.get_tree().process_frame | |
| return ResourceLoader.load_threaded_get(path) | |
| ## Await this function to wait until the given function returns true. | |
| static func wait(node: Node, f: Callable) -> void: | |
| var tree: SceneTree = node.get_tree() | |
| while not f.call(): | |
| await tree.process_frame | |
| ## Clamp a value in the range [-1, 1] to 0 if it is within the given dead zone. | |
| static func dead_zone(x: float, zone: float) -> float: | |
| if x < -zone: | |
| return (x + zone) / (1.0 - zone) | |
| elif x > zone: | |
| return (x - zone) / (1.0 - zone) | |
| else: | |
| return 0.0 | |
| ## Return the angle x plus or minus some multiple of PI*2 so that it is the | |
| ## closest possible to angle y. | |
| static func closest_angle(x: float, y: float) -> float: | |
| var result: float = x | |
| while result > y + PI: | |
| result -= PI * 2.0 | |
| while result < y - PI: | |
| result += PI * 2.0 | |
| return result |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment