extends Control @export var frames_config: JSON @export var frame_dir_name := "" @export var mapping_name := "" @export var frames_per_sec := 0 # empty string means no first frame mapping @export var first_frame_mapping := "" # empty string means no mirror mapping @export var mirror_mapping := "" @onready var animated_sprite := %AnimatedSprite2D as AnimatedSprite2D @onready var frames_speed_line_edit := %FramesSpeedEdit as LineEdit @onready var dir_line_edit := %DirLineEdit as LineEdit @onready var mapping_line_edit := %MappingLineEdit as LineEdit @onready var first_frame_mapping_edit = %FirstFrameMapping as LineEdit @onready var mirror_mapping_edit = %MirrorMapping as LineEdit func _ready() -> void: dir_line_edit.text = frame_dir_name mapping_line_edit.text = mapping_name frames_speed_line_edit.text = str(frames_per_sec) first_frame_mapping_edit.text = first_frame_mapping mirror_mapping_edit.text = mirror_mapping reload_frames() mapping_line_edit.text_submitted.connect(_on_mapping_submitted) frames_speed_line_edit.text_submitted.connect(_on_frames_speed_submitted) first_frame_mapping_edit.text_submitted.connect(_on_first_frame_mapping_submitted) mirror_mapping_edit.text_submitted.connect(_on_mirror_mapping_submitted) var reload_lock := Mutex.new() func reload_frames(): var sprite_frames = animated_sprite.sprite_frames as SpriteFrames # {"path": "", "frames": {}, "ids": []} var frames_data = frames_config.data.dirs[frame_dir_name] reload_lock.lock() # clear all animations with either dir or mapping name if frame_dir_name != mapping_name and sprite_frames.has_animation(frame_dir_name): sprite_frames.remove_animation(frame_dir_name) if sprite_frames.has_animation(mapping_name): sprite_frames.clear(mapping_name) else: sprite_frames.add_animation(mapping_name) # clear first frame mapping and mirror mapping if first_frame_mapping != "": if sprite_frames.has_animation(first_frame_mapping): sprite_frames.clear(first_frame_mapping) else: sprite_frames.add_animation(first_frame_mapping) # add the first frame var first_frame_path = frames_data.frames[frames_data.ids[0]] sprite_frames.add_frame(first_frame_mapping, load(first_frame_path)) if mirror_mapping != "": if sprite_frames.has_animation(mirror_mapping): sprite_frames.clear(mirror_mapping) else: sprite_frames.add_animation(mirror_mapping) for id in frames_data.ids: var frame_path = frames_data.frames[id] as String var frame_texture = load(frame_path) as Texture2D sprite_frames.add_frame(mapping_name, frame_texture) sprite_frames.set_animation_speed(mapping_name, frames_per_sec) # mirror the frame if mirror_mapping != "": # mkdir the mirror mapping var mirror_dir_path = "res://asset/art/animation/" + mirror_mapping if !DirAccess.dir_exists_absolute(mirror_dir_path): DirAccess.make_dir_absolute(mirror_dir_path) var mirrored_frame = frame_texture.duplicate() as Texture2D var flipped_image = mirrored_frame.get_image() as Image flipped_image.flip_x() var flipped_img_path = mirror_dir_path + "/" + id + ".png" flipped_image.resource_path = flipped_img_path flipped_image.save_png(flipped_img_path) sprite_frames.add_frame(mirror_mapping, load(flipped_img_path)) sprite_frames.set_animation_speed(mapping_name, frames_per_sec) animated_sprite.play(mapping_name) # scale down if the frame is too big var frame_size = sprite_frames.get_frame_texture(mapping_name, 0).get_size() if frame_size.x > 128 or frame_size.y > 128: var ratio = min(128 / frame_size.x, 128 / frame_size.y) animated_sprite.scale = Vector2(ratio, ratio) reload_lock.unlock() _save_and_update_frames_and_config() func _on_mapping_submitted(new_text: String): # clear the old mapping var sprite_frames = animated_sprite.sprite_frames as SpriteFrames if sprite_frames.has_animation(mapping_name): sprite_frames.remove_animation(mapping_name) mapping_name = new_text frames_config.data.mapping[frame_dir_name] = mapping_name reload_frames() mapping_line_edit.release_focus() _save_and_update_frames_and_config() func _on_frames_speed_submitted(new_text: String): frames_per_sec = int(new_text) if frames_per_sec < 1: frames_per_sec = 1 frames_speed_line_edit.text = str(frames_per_sec) frames_config.data.frames_per_second[frame_dir_name] = frames_per_sec reload_frames() frames_speed_line_edit.release_focus() _save_and_update_frames_and_config() func _on_first_frame_mapping_submitted(new_text: String): # clear the old first frame mapping if first_frame_mapping != "": var sprite_frames = animated_sprite.sprite_frames as SpriteFrames sprite_frames.remove_animation(first_frame_mapping) first_frame_mapping = new_text frames_config.data.first_frame_mapping[frame_dir_name] = first_frame_mapping reload_frames() first_frame_mapping_edit.release_focus() _save_and_update_frames_and_config() func _on_mirror_mapping_submitted(new_text: String): # clear the old mirror mapping if mirror_mapping != "": var sprite_frames = animated_sprite.sprite_frames as SpriteFrames sprite_frames.remove_animation(mirror_mapping) mirror_mapping = new_text frames_config.data.mirror_mapping[frame_dir_name] = mirror_mapping reload_frames() mirror_mapping_edit.release_focus() _save_and_update_frames_and_config() func _save_and_update_frames_and_config(): # save the sprite_frames if animated_sprite: ResourceSaver.save(animated_sprite.sprite_frames) ResourceSaver.save(frames_config) #EditorInterface.get_resource_filesystem().update_file(frames_config.resource_path)