Last active
January 1, 2024 17:20
-
-
Save belzecue/c6625d1cf9257997fdfe16047f06dacc to your computer and use it in GitHub Desktop.
Capture an animation to a PNG sequence, e.g. to turn into an Animated Sprite.
This file contains 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
""" | |
Attach this script to the parent node of an AnimationPlayer. | |
""" | |
extends Node2D | |
export(NodePath) var anim_player_path: NodePath | |
export(String) var track_name: String | |
onready var anim_player: AnimationPlayer = get_node(anim_player_path) as AnimationPlayer | |
onready var tree: SceneTree = get_tree() | |
onready var viewport: Viewport = get_viewport() | |
var animation: Animation | |
var animation_pos_seconds: float = 0 | |
var animation_length: float | |
var img_idx: int = 0 | |
const frame_rate = 1.0 / 60 # Capture at 60 frames per second. | |
func _ready(): | |
anim_player.stop(true) # Reset animation player | |
anim_player.autoplay = "" | |
animation = anim_player.get_animation(track_name) | |
animation.loop = false | |
anim_player.current_animation = track_name | |
animation_length = anim_player.current_animation_length | |
# Trigger next save at next idle | |
tree.connect("idle_frame", self, "export_anim_frames", [], CONNECT_ONESHOT) | |
func export_anim_frames(): | |
# Save current image before advancing | |
save_img() | |
# Advance to next frame | |
animation_pos_seconds = clamp( | |
animation_pos_seconds + frame_rate, | |
0, | |
animation_length | |
) | |
anim_player.seek(animation_pos_seconds) # Seek uses absolute timeline pos in seconds | |
# Check if this is last frame | |
if animation_pos_seconds == animation_length: | |
# Save the last frame before we quit | |
save_img() # Save image | |
print("finished.") | |
else: | |
# Wait for idle then export next frame | |
tree.call_deferred("connect", "idle_frame", self, "export_anim_frames", [], CONNECT_ONESHOT) | |
func save_img(): | |
var img = viewport.get_texture().get_data() | |
img.flip_y() | |
# Saves to Godot User data folder | |
img.save_png("%s/img_%s.png" % [OS.get_user_data_dir(), img_idx]) | |
img_idx += 1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
FYI: uses AnimationPlayer 'seek' method because it needs to process the frames asyncronously. This means animation events are skipped, if you are using them. The 'advance' method uses delta time to move forward, whereas 'seek' uses the absolute timeline position.