fix off-by-one in bounded range
This commit is contained in:
parent
d0310c693b
commit
143dc9d288
5 changed files with 50 additions and 23 deletions
|
@ -1,13 +1,17 @@
|
|||
class_name IntRange extends RefCounted
|
||||
|
||||
var min: int
|
||||
var max: int
|
||||
var minmax: PackedInt32Array
|
||||
|
||||
var min: int:
|
||||
get: return minmax[0]
|
||||
|
||||
var max: int:
|
||||
get: return minmax[1]
|
||||
|
||||
static var Zero = IntRange.new(0, 0)
|
||||
|
||||
func _init(start: int, end: int, inclusive: bool = false) -> void:
|
||||
min = start
|
||||
max = end if not inclusive else end + 1
|
||||
minmax = PackedInt32Array([start, end if not inclusive else end + 1])
|
||||
|
||||
func length() -> int:
|
||||
return absi(max - min)
|
||||
|
|
|
@ -23,6 +23,7 @@ func next() -> Option:
|
|||
return current_value
|
||||
elif limit > 0:
|
||||
limit -= 1
|
||||
index = bounds.wrap(index)
|
||||
return Option.some(index)
|
||||
var current_value = bounds.wrap(index)
|
||||
index = current_value + 1
|
||||
return Option.some(current_value)
|
||||
else: return Option.none
|
||||
|
|
|
@ -2,7 +2,7 @@ class_name HItemList extends HBoxContainer
|
|||
|
||||
@export var item_scene: PackedScene
|
||||
@export var max_items: int = 4
|
||||
@export var buffered_items: int = 2
|
||||
@export var buffered_items: int = 1
|
||||
@onready var buffer_size = max_items + (buffered_items * 2)
|
||||
|
||||
var items: Array = []
|
||||
|
@ -11,12 +11,22 @@ var bind_item: Callable = _bind_item
|
|||
var ring_buffer: RingBuffer
|
||||
|
||||
func _ready() -> void:
|
||||
ring_buffer = RingBuffer.new(items.size(), buffer_size)
|
||||
ring_buffer = RingBuffer.new(items.size(), buffer_size, 1, -buffered_items)
|
||||
ring_buffer.updated.connect(_on_updated)
|
||||
|
||||
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()
|
||||
|
||||
|
@ -30,10 +40,13 @@ func _on_updated(_current_range: IntRange, _previous_range: IntRange):
|
|||
func _update_display():
|
||||
var indices: Array = ring_buffer.range().collect()
|
||||
|
||||
prints(indices, ring_buffer.start_index, ring_buffer.end_index, ring_buffer.capacity)
|
||||
for i in range(min(indices.size(), max_items)):
|
||||
var node = get_child(i + 1)
|
||||
var node = get_child(i)
|
||||
prints(ring_buffer.index(i))
|
||||
var item = items[indices[i]]
|
||||
bind_item.call(node, item)
|
||||
if item != null:
|
||||
bind_item.call(node, item)
|
||||
|
||||
func add_item(item: Variant):
|
||||
items.append(item)
|
||||
|
|
|
@ -4,6 +4,4 @@ class_name InventoryUI extends VBoxContainer
|
|||
@export var item_list: HItemList
|
||||
|
||||
func _ready() -> void:
|
||||
print(inventory)
|
||||
print(inventory.items)
|
||||
item_list.add_items(inventory.items)
|
||||
|
|
|
@ -12,7 +12,7 @@ var source_size: int:
|
|||
get: return _source_size
|
||||
set(value): set_source_size(value)
|
||||
|
||||
func set_source_size(value: int):
|
||||
func set_source_size(value: int) -> void:
|
||||
assert(value >= 0, "source size must be a non-negative integer")
|
||||
_source_size = value
|
||||
|
||||
|
@ -21,44 +21,55 @@ var capacity: int:
|
|||
get: return _capacity
|
||||
set(value): set_capacity(value)
|
||||
|
||||
func set_capacity(value: int):
|
||||
func set_capacity(value: int) -> void:
|
||||
_capacity = value
|
||||
|
||||
var _offset: int
|
||||
var offset: int:
|
||||
get: return _offset
|
||||
set(value): set_offset(value)
|
||||
|
||||
func set_offset(value: int) -> void:
|
||||
_offset = value
|
||||
|
||||
var _index: int
|
||||
|
||||
var selected_index: int:
|
||||
get: return _index
|
||||
set(value): set_selected(value)
|
||||
|
||||
func set_selected(value: int):
|
||||
_index = self.wrap(value)
|
||||
func set_selected(value: int) -> void:
|
||||
_index = self.index(value)
|
||||
|
||||
var start_index: int:
|
||||
get: return _index
|
||||
get: return self.index(_offset + _index)
|
||||
|
||||
var end_index: int:
|
||||
get: return self.wrap(_index + _capacity - 1)
|
||||
get: return self.index(_offset + _index + _capacity - 1)
|
||||
|
||||
@warning_ignore("shadowed_variable")
|
||||
func _init(source_size: int, capacity: int, start_index: int = 0) -> void:
|
||||
func _init(source_size: int, capacity: int, start_index: int = 0, offset: int = 0) -> void:
|
||||
self.source_size = source_size
|
||||
self.capacity = capacity
|
||||
selected_index = start_index
|
||||
self.offset = offset
|
||||
|
||||
func wrap(value: int) -> int:
|
||||
func index(value: int) -> int:
|
||||
if _source_size == 0:
|
||||
return 0
|
||||
elif value < 0:
|
||||
return _source_size + value % _source_size
|
||||
else:
|
||||
return value % _source_size
|
||||
|
||||
func range() -> RangeIterator:
|
||||
return RangeIterator.new(IntRange.new(start_index, end_index))
|
||||
func range() -> BoundedRangeIterator:
|
||||
return BoundedRangeIterator.new(IntRange.new(start_index, end_index), IntRange.new(0, capacity))
|
||||
|
||||
func move(direction: Direction) -> Result:
|
||||
if _source_size <= _capacity:
|
||||
return Result.err("source size is smaller than buffer capacity")
|
||||
var previous = range()
|
||||
_index = self.wrap(_index + direction)
|
||||
_index = self.index(_index + direction)
|
||||
updated.emit(range(), previous)
|
||||
return Result.Unit
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue