diff options
Diffstat (limited to 'sprite.gd')
-rw-r--r-- | sprite.gd | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/sprite.gd b/sprite.gd new file mode 100644 index 0000000..3bfc961 --- /dev/null +++ b/sprite.gd @@ -0,0 +1,96 @@ +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) |