class_name Sprite extends Node2D var sprite_data: SpriteResource var action_data: ActionFormat var current_action_idx := 0 var current_frame := 0 var current_start_time := 0.0 var accumulator := 0.0 var cache: Dictionary func _ready() -> void: if not sprite_data or not action_data: set_process(false) func load_file(path: String): var basename = path.get_basename() sprite_data = load("%s.tres" % basename) var act = FileAccess.open("%s.act" % basename, FileAccess.READ) action_data = ActionFormat.from_bytes(ByteStream.from_bytes( act.get_buffer(act.get_length()) )) if not sprite_data.files_exist(): sprite_data.save_to_file() # generate at "runtime" set_process(true) set_current_action(0) func set_current_action(idx: int): current_action_idx = idx current_frame = 0 current_start_time = 0 accumulator = 0 update(action_data.actions[current_action_idx].motions[current_frame].sprite_layers) func _process(delta: float) -> void: var action = action_data.actions[current_action_idx] var frame_time = ((action_data.frame_times[current_action_idx] * 24) / 1000) accumulator += delta if accumulator > current_start_time + frame_time: var motion: ActionFormat.Motion = action.motions[current_frame] update(motion.sprite_layers) current_start_time = accumulator current_frame += 1 if current_frame >= action.motions.size(): set_current_action(current_action_idx) # reset current action func update(sprite_layers: Array[ActionFormat.SpriteLayer]): if not is_processing(): return var has_different_layer_count = %SpriteLayers.get_child_count() != sprite_layers.size() if has_different_layer_count: for node in %SpriteLayers.get_children(): node.queue_free() for idx in sprite_layers.size(): var sprite_layer = sprite_layers[idx] var base_dir = sprite_data.filepath.substr(0, sprite_data.filepath.length() - 4) # cut off .spr var image = load("%s/%s.png" % [base_dir, str(sprite_layer.sprite_index).pad_zeros(3)]) var sprite: Sprite2D if has_different_layer_count: sprite = Sprite2D.new() sprite.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST else: sprite = %SpriteLayers.get_child(idx) sprite.texture = image sprite.position = sprite_layer.get_position() sprite.self_modulate = sprite_layer.get_color() sprite.scale = sprite_layer.get_scale() sprite.rotation_degrees = sprite_layer.rotation_degrees sprite.flip_h = sprite_layer.flip_h # TODO: use sprite and action together to generate AnimatedSprite2D with SpriteFrame Resources? # TODO: no. needs AnimationPlayer with config for different sprite positions in the animation if has_different_layer_count: %SpriteLayers.add_child(sprite)