Files
tekton/scripts/tekton_fishing_autoplay.gd
T
2026-06-18 14:04:06 +08:00

70 lines
2.4 KiB
GDScript

extends Node3D
## Merges every animation in the AnimationPlayer into a single looping clip and
## plays it, so meshes driven by different animations (e.g. ted_bones and
## fishing_acc) all animate simultaneously instead of overwriting each other.
## Attach to any node that has an AnimationPlayer child.
@onready var anim_player: AnimationPlayer = $AnimationPlayer
const MERGED_LIB := "merged"
const MERGED_NAME := "merged/all"
func _ready() -> void:
if not anim_player:
push_warning("tekton_fishing_autoplay: No AnimationPlayer found")
return
# Wait one frame for the scene tree to settle
await get_tree().process_frame
var source_names := anim_player.get_animation_list()
if source_names.is_empty():
return
var merged := _build_merged_animation(source_names)
if not merged:
return
var lib := AnimationLibrary.new()
lib.add_animation("all", merged)
if anim_player.has_animation_library(MERGED_LIB):
anim_player.remove_animation_library(MERGED_LIB)
anim_player.add_animation_library(MERGED_LIB, lib)
anim_player.play(MERGED_NAME)
## Combines the tracks of every source animation into one Animation. The source
## animations target disjoint node sets, so simply concatenating their tracks
## drives all meshes at once.
func _build_merged_animation(source_names: Array) -> Animation:
var merged := Animation.new()
merged.loop_mode = Animation.LOOP_LINEAR
var max_length := 0.0
for anim_name in source_names:
var src: Animation = anim_player.get_animation(anim_name)
if not src:
continue
max_length = max(max_length, src.length)
for t in src.get_track_count():
_copy_track(src, t, merged)
merged.length = max_length
return merged
func _copy_track(src: Animation, src_track: int, dst: Animation) -> void:
var new_track := dst.add_track(src.track_get_type(src_track))
dst.track_set_path(new_track, src.track_get_path(src_track))
dst.track_set_interpolation_type(new_track, src.track_get_interpolation_type(src_track))
dst.track_set_interpolation_loop_wrap(new_track, src.track_get_interpolation_loop_wrap(src_track))
dst.track_set_enabled(new_track, src.track_is_enabled(src_track))
for k in src.track_get_key_count(src_track):
var time := src.track_get_key_time(src_track, k)
var value = src.track_get_key_value(src_track, k)
var transition := src.track_get_key_transition(src_track, k)
dst.track_insert_key(new_track, time, value, transition)