extends SceneTree

# Офлайн-запекатель: прогоняет Spine-рантайм и снимает покадрово ЛОКАЛЬНЫЕ трансформы костей
# для выбранных анимаций -> tools/rig/<name>_anims.json (только числа, без Spine на выходе).

const BASE := "res://characters/elf1/spine/elf1_combat"
const OUT := "res://tools/rig/elf1_combat_anims.json"
const FPS := 30.0
const ANIMS := ["idle_0", "walk_0", "attack_0", "attack_1", "knockback_0", "stun_0"]

func _initialize():
	var atlas := SpineAtlasResource.new(); atlas.load_from_atlas_file(BASE + ".atlas.txt")
	var skf := SpineSkeletonFileResource.new(); skf.load_from_file(BASE + ".skel.bytes")
	var data := SpineSkeletonDataResource.new()
	data.set_atlas_res(atlas); data.set_skeleton_file_res(skf)

	var sprite := SpineSprite.new()
	sprite.set_skeleton_data_res(data)
	get_root().add_child(sprite)
	var st = sprite.get_animation_state()
	var skel = sprite.get_skeleton()

	# имена костей в порядке скелета
	var bone_names := []
	for bd in data.get_bones():
		bone_names.append(bd.get_bone_name())

	# имена слотов + индекс по имени (для draw order)
	var slot_names := []
	var slot_index := {}
	var live_slots = skel.get_slots()
	for i in live_slots.size():
		var sn = live_slots[i].get_data().get_name()
		slot_names.append(sn); slot_index[sn] = i

	var out := { "fps": FPS, "bones": bone_names, "slots": slot_names, "animations": {} }

	for anim in ANIMS:
		var sa = data.find_animation(anim)
		if sa == null:
			print("skip (нет): ", anim); continue
		var dur: float = sa.get_duration()
		var nframes := int(round(dur * FPS)) + 1
		st.clear_tracks()
		st.set_animation(anim, false, 0)

		var frames := []
		var draworder := []
		for f in nframes:
			skel.set_bones_to_setup_pose()
			skel.set_slots_to_setup_pose()
			st.apply(skel)
			var frame := []
			for name in bone_names:
				var b = skel.find_bone(name)
				frame.append([
					snappedf(b.get_x(), 0.001), snappedf(b.get_y(), 0.001),
					snappedf(b.get_rotation(), 0.001),
					snappedf(b.get_scale_x(), 0.001), snappedf(b.get_scale_y(), 0.001)
				])
			frames.append(frame)
			# порядок отрисовки: индексы слотов сзади->вперёд
			var order := []
			for s in skel.get_draw_order():
				order.append(slot_index[s.get_data().get_name()])
			draworder.append(order)
			st.update(1.0 / FPS)
		out["animations"][anim] = { "duration": dur, "frames": frames, "draworder": draworder }
		print("baked ", anim, "  frames=", nframes, "  dur=", dur)

	var fp := FileAccess.open(OUT, FileAccess.WRITE)
	fp.store_string(JSON.stringify(out))
	fp.close()
	print("SAVED ", OUT)
	quit()
