blob: 745a86d109806d88a1e8982d6e4948bafed937b7 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
class_name Sprite
extends Node2D
@export 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/sprite.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())
))
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 image = sprite_data.images[sprite_layer.sprite_index]
var sprite: Sprite2D
if has_different_layer_count:
sprite = Sprite2D.new()
sprite.centered = false # 必要!!
sprite.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST
else:
sprite = %SpriteLayers.get_child(idx)
sprite.texture = image
sprite.position = sprite_layer.get_position() - ceil(sprite_layer.get_size() / 2) # for fixing half pixel drawing
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)
|