extends RefCounted
## Keeps the scroll position of every list in the HUD windows across rebuilds (Boss bug: the shop /
## skill lists jumped back to the top). hud.gd rebuilds a window's body on every refresh(); this saves
## each ScrollContainer's position per window (in tree order) before and puts it back after, first at
## once, then again after the containers sorted (deferred) and one frame later (a list that grows
## this frame only knows its new length then).


## window key -> [Vector2i(h, v), ...] of its ScrollContainers, in tree order.
static func save(hud) -> Dictionary:
	var out := {}
	for k in hud.bodies:
		var body: Control = hud.bodies[k]
		if not body.is_visible_in_tree():
			continue
		var arr: Array = []
		for sc in body.find_children("*", "ScrollContainer", true, false):
			arr.append(Vector2i((sc as ScrollContainer).scroll_horizontal, (sc as ScrollContainer).scroll_vertical))
		if not arr.is_empty():
			out[k] = arr
	return out


static func restore(hud, saved: Dictionary) -> void:
	for k in saved:
		if not hud.bodies.has(k):
			continue
		var scs: Array = hud.bodies[k].find_children("*", "ScrollContainer", true, false)
		var arr: Array = saved[k]
		for i in mini(scs.size(), arr.size()):
			var v: Vector2i = arr[i]
			if v == Vector2i.ZERO:
				continue
			var sc: ScrollContainer = scs[i]
			_apply(sc, v)
			_apply.call_deferred(sc, v)
			sc.get_tree().process_frame.connect(_apply.bind(sc, v), CONNECT_ONE_SHOT)


static func _apply(sc: ScrollContainer, v: Vector2i) -> void:
	if not is_instance_valid(sc) or not sc.is_inside_tree():
		return
	# the list may be shorter now: the container clamps
	sc.scroll_horizontal = v.x
	sc.scroll_vertical = v.y
