class_name HItemList extends HBoxContainer @export var item_scene: PackedScene @export var max_items: int = 4 @export var buffered_items: int = 1 @onready var buffer_size = max_items + (buffered_items * 2) var items: Array = [] var create_item: Callable = _create_item var bind_item: Callable = _bind_item var ring_buffer: RingBuffer func _ready() -> void: ring_buffer = RingBuffer.new(items.size(), buffer_size, buffer_size - 1) ring_buffer.rotated.connect(_on_rotated) for _i in range(buffer_size): add_child(create_item.call()) _hide_buffered_items() func _hide_buffered_items(): for i in range(buffered_items): get_child(i).hide() var length = buffer_size - 1 for i in range(length, length - buffered_items, -1): get_child(i).hide() func _create_item() -> Node: return item_scene.instantiate() func _bind_item(node: Node, item: Option): if node.has_method('bind'): node.call('bind', item) func _on_rotated(_direction: int): _update_display() func _get_item(index: int) -> Option: if index < 0 or index >= len(items): return Option.none return Option.from(items[index]) func _update_display(): var iter = ring_buffer.iter() var indices = iter.collect() for i in range(buffer_size): var node = get_child(i) var item_index_from_ring_buffer = indices[i] var item_option = _get_item(item_index_from_ring_buffer) bind_item.call(node, item_option) #if item_option.is_none(): # node.hide() # Hide if no item available #else: # if i >= buffered_items and i < (buffer_size - buffered_items): # node.show() # else: # node.hide() func add_item(item: Variant): items.append(item) ring_buffer.source_size = items.size() _update_display() func add_items(new_items: Array): items.append_array(new_items) ring_buffer.source_size = items.size() _update_display() func move_right(): ring_buffer.move_right() func move_left(): ring_buffer.move_left()