hitemlist working
This commit is contained in:
parent
d1956a95b3
commit
0f49097dd9
11 changed files with 155 additions and 69 deletions
|
@ -1,17 +1,26 @@
|
|||
class_name IntRange extends RefCounted
|
||||
|
||||
static var Zero = IntRange.new(0, 0)
|
||||
|
||||
var minmax: PackedInt32Array
|
||||
|
||||
var min: int:
|
||||
get: return minmax[0]
|
||||
|
||||
var max: int:
|
||||
get: return minmax[1]
|
||||
get:
|
||||
if inclusive: return minmax[1] + 1
|
||||
else: return minmax[1]
|
||||
|
||||
static var Zero = IntRange.new(0, 0)
|
||||
var inclusive: bool
|
||||
|
||||
func _init(start: int, end: int, inclusive: bool = false) -> void:
|
||||
minmax = PackedInt32Array([start, end if not inclusive else end + 1])
|
||||
minmax = PackedInt32Array([start, end])
|
||||
self.inclusive = inclusive
|
||||
|
||||
func _to_string() -> String:
|
||||
var ch = "]" if inclusive else ")"
|
||||
return "IntRange [%s, %s%s" % [min, max, ch]
|
||||
|
||||
func length() -> int:
|
||||
return absi(max - min)
|
||||
|
@ -20,16 +29,16 @@ func is_zero() -> bool:
|
|||
return min == 0 and max == 0
|
||||
|
||||
func is_empty() -> bool:
|
||||
return is_zero()
|
||||
return length() == 0
|
||||
|
||||
func iter(step: int = 1) -> RangeIterator:
|
||||
return RangeIterator.new(self, min, step)
|
||||
|
||||
func clamp(value: int) -> int:
|
||||
return clampi(value, min, max)
|
||||
return clampi(value, minmax[0], minmax[1])
|
||||
|
||||
func wrap(value: int) -> int:
|
||||
return wrapi(value, min, max)
|
||||
return wrapi(value, minmax[0], minmax[1])
|
||||
|
||||
func contains(value: int) -> bool:
|
||||
return value >= min and value < max
|
||||
|
|
|
@ -1,29 +1,35 @@
|
|||
class_name BoundedRangeIterator extends Iterator
|
||||
|
||||
var range: IntRange
|
||||
var bounds: IntRange
|
||||
var step: int
|
||||
var limit: int
|
||||
var index: int
|
||||
var _range: IntRange
|
||||
var _bounds: IntRange
|
||||
var _count: int
|
||||
var _step: int
|
||||
var _items_yielded: int = 0
|
||||
|
||||
func _init(range: IntRange, bounds: IntRange, step: int = 1, limit: int = 1, start_index: int = range.min) -> void:
|
||||
self.range = range
|
||||
self.bounds = bounds
|
||||
self.step = step
|
||||
self.limit = limit
|
||||
self.index = start_index
|
||||
func _init(range: IntRange, bounds: IntRange, step: int = 1) -> void:
|
||||
self._range = range
|
||||
self._count = range.length()
|
||||
self._bounds = bounds
|
||||
self._step = step
|
||||
|
||||
static func from_array(xs: Array, iteration_range: IntRange, step: int = 1) -> BoundedRangeIterator:
|
||||
return BoundedRangeIterator.new(iteration_range, IntRange.new(0, len(xs)), step)
|
||||
|
||||
func _to_string() -> String:
|
||||
return "BoundedRangeIterator { range: %s, count: %s, bounds: %s, step: %s, items_yielded: %s }" % \
|
||||
[_range, _count, _bounds, _step, _items_yielded]
|
||||
|
||||
func clone() -> BoundedRangeIterator:
|
||||
return BoundedRangeIterator.new(range, bounds, step, limit, index)
|
||||
var iter = BoundedRangeIterator.new(_range, _bounds, _step)
|
||||
iter._items_yielded = _items_yielded
|
||||
return iter
|
||||
|
||||
func next() -> Option:
|
||||
if bounds.contains(index):
|
||||
var current_value = Option.some(index)
|
||||
index += step
|
||||
return current_value
|
||||
elif limit > 0:
|
||||
limit -= 1
|
||||
var current_value = bounds.wrap(index)
|
||||
index = current_value + 1
|
||||
return Option.some(current_value)
|
||||
else: return Option.none
|
||||
if _items_yielded >= _count:
|
||||
return Option.none
|
||||
|
||||
var index = _range.min + (_items_yielded * _step)
|
||||
var wrapped_index = _bounds.wrap(index)
|
||||
_items_yielded += 1
|
||||
|
||||
return Option.some(wrapped_index)
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
class_name Iterator extends RefCounted
|
||||
|
||||
func _to_string() -> String:
|
||||
return "Iterator"
|
||||
|
||||
func clone() -> Iterator:
|
||||
assert(false, "can't clone a abstract base class")
|
||||
return null
|
||||
|
|
|
@ -4,6 +4,7 @@ var index: int
|
|||
var range: IntRange
|
||||
var step: int
|
||||
var descending: bool
|
||||
var _done: bool = false
|
||||
|
||||
func _init(range: IntRange, start_index: int = range.min, step: int = 1) -> void:
|
||||
assert(step != 0, "step cannot be zero")
|
||||
|
@ -23,8 +24,12 @@ func clone() -> RangeIterator:
|
|||
return RangeIterator.new(range, index)
|
||||
|
||||
func next() -> Option:
|
||||
if range.contains(index):
|
||||
if _done: return Option.none
|
||||
if index == range.max or not range.contains(index):
|
||||
_done = true
|
||||
if range.inclusive: return Option.some(index)
|
||||
else: return Option.none
|
||||
|
||||
var current_value = Option.some(index)
|
||||
index += step
|
||||
return current_value
|
||||
else: return Option.none
|
||||
|
|
|
@ -7,6 +7,11 @@ static func some(value: Variant) -> Option:
|
|||
|
||||
static var none: Option.None = None.new()
|
||||
|
||||
static func from(value: Variant) -> Option:
|
||||
if typeof(value) == TYPE_NIL:
|
||||
return Option.none
|
||||
else: return Option.some(value)
|
||||
|
||||
static func collect_some(options: Array[Option], ignore_none: bool = false) -> Option:
|
||||
var result = []
|
||||
for option in options:
|
||||
|
|
28
godot/addons/utils/utils.gd
Normal file
28
godot/addons/utils/utils.gd
Normal file
|
@ -0,0 +1,28 @@
|
|||
class_name Utils
|
||||
|
||||
static func get_class_name(value: Object) -> String:
|
||||
match value.get_script():
|
||||
var script:
|
||||
match script.get_global_name():
|
||||
var name: return name
|
||||
_: return script.get_instance_base_type()
|
||||
_: return value.get_class()
|
||||
|
||||
static func is_string_like(value: Variant) -> bool:
|
||||
match typeof(value):
|
||||
TYPE_STRING: return true
|
||||
TYPE_STRING_NAME: return true
|
||||
TYPE_NODE_PATH: return true
|
||||
_: return false
|
||||
|
||||
static func to_str(value: Variant) -> String:
|
||||
match typeof(value):
|
||||
TYPE_OBJECT:
|
||||
if value.has_method('_to_string'):
|
||||
return value.to_string()
|
||||
else:
|
||||
var name = get_class_name(value)
|
||||
value = value as Object
|
||||
var props: Dictionary = inst_to_dict(value)
|
||||
return "%s %s" % [name, to_str(props)]
|
||||
_: return str(value)
|
|
@ -17,7 +17,6 @@ script = ExtResource("1_qw0r6")
|
|||
action = "inventory"
|
||||
|
||||
[node name="ColorRect" type="ColorRect" parent="."]
|
||||
visible = false
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
|
@ -43,18 +42,6 @@ layout_mode = 2
|
|||
script = ExtResource("4_yyk2a")
|
||||
item_scene = ExtResource("5_uae8j")
|
||||
|
||||
[node name="Item" parent="VBoxContainer/HItemList" instance=ExtResource("5_uae8j")]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Item2" parent="VBoxContainer/HItemList" instance=ExtResource("5_uae8j")]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Item3" parent="VBoxContainer/HItemList" instance=ExtResource("5_uae8j")]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Item4" parent="VBoxContainer/HItemList" instance=ExtResource("5_uae8j")]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Details" type="HBoxContainer" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
[gd_scene load_steps=3 format=3 uid="uid://gn8k2ir47n1m"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://dt67n4jti376d" path="res://src/item_ui.gd" id="1_letey"]
|
||||
[ext_resource type="Texture2D" uid="uid://djmxd4580q6xs" path="res://icon.svg" id="2_y87vu"]
|
||||
|
||||
[sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_u4rwp"]
|
||||
size = Vector2(128, 128)
|
||||
|
||||
[node name="Item" type="BoxContainer" node_paths=PackedStringArray("name_label", "icon_texture")]
|
||||
offset_right = 128.0
|
||||
|
@ -18,8 +20,8 @@ layout_mode = 2
|
|||
|
||||
[node name="Name" type="Label" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Test Item"
|
||||
text = "Empty"
|
||||
|
||||
[node name="Icon" type="TextureRect" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
texture = ExtResource("2_y87vu")
|
||||
texture = SubResource("PlaceholderTexture2D_u4rwp")
|
||||
|
|
|
@ -11,8 +11,8 @@ var bind_item: Callable = _bind_item
|
|||
var ring_buffer: RingBuffer
|
||||
|
||||
func _ready() -> void:
|
||||
ring_buffer = RingBuffer.new(items.size(), buffer_size, 1, -buffered_items)
|
||||
ring_buffer.updated.connect(_on_updated)
|
||||
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())
|
||||
|
@ -30,21 +30,35 @@ func _hide_buffered_items():
|
|||
func _create_item() -> Node:
|
||||
return item_scene.instantiate()
|
||||
|
||||
func _bind_item(node: Node, item: Item):
|
||||
func _bind_item(node: Node, item: Option):
|
||||
if node.has_method('bind'):
|
||||
node.call('bind', item)
|
||||
|
||||
func _on_updated(_current_range: IntRange, _previous_range: IntRange):
|
||||
func _on_rotated(_direction: int):
|
||||
_update_display()
|
||||
|
||||
func _update_display():
|
||||
var indices: Array = ring_buffer.range().collect()
|
||||
func _get_item(index: int) -> Option:
|
||||
if index < 0 or index >= len(items):
|
||||
return Option.none
|
||||
return Option.from(items[index])
|
||||
|
||||
for i in range(min(indices.size(), max_items)):
|
||||
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 = items[indices[i]]
|
||||
if item != null:
|
||||
bind_item.call(node, item)
|
||||
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)
|
||||
|
@ -55,3 +69,9 @@ 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()
|
||||
|
|
|
@ -3,6 +3,21 @@ class_name ItemUI extends Control
|
|||
@export var name_label: Label
|
||||
@export var icon_texture: TextureRect
|
||||
|
||||
func bind(item: Item):
|
||||
var _default_text: String
|
||||
var _default_icon: Texture2D
|
||||
|
||||
func _ready() -> void:
|
||||
_default_text = name_label.text
|
||||
_default_icon = icon_texture.texture
|
||||
|
||||
func bind(_item: Option):
|
||||
if _item.is_none():
|
||||
unbind()
|
||||
else:
|
||||
var item = _item.unwrap()
|
||||
name_label.text = item.name
|
||||
icon_texture.texture = item.icon
|
||||
|
||||
func unbind():
|
||||
name_label.text = _default_text
|
||||
icon_texture.texture = _default_icon
|
||||
|
|
|
@ -6,6 +6,7 @@ enum Direction {
|
|||
}
|
||||
|
||||
signal updated(new_range: IntRange, previous_range: IntRange)
|
||||
signal rotated(direction: int)
|
||||
|
||||
var _source_size: int
|
||||
var source_size: int:
|
||||
|
@ -39,13 +40,16 @@ var selected_index: int:
|
|||
set(value): set_selected(value)
|
||||
|
||||
func set_selected(value: int) -> void:
|
||||
var previous = self.get_range()
|
||||
_index = self.index(value)
|
||||
var current = self.get_range()
|
||||
updated.emit(current, previous)
|
||||
|
||||
var start_index: int:
|
||||
get: return self.index(_offset + _index)
|
||||
get: return _index
|
||||
|
||||
var end_index: int:
|
||||
get: return self.index(_offset + _index + _capacity - 1)
|
||||
get: return start_index + capacity
|
||||
|
||||
@warning_ignore("shadowed_variable")
|
||||
func _init(source_size: int, capacity: int, start_index: int = 0, offset: int = 0) -> void:
|
||||
|
@ -62,15 +66,17 @@ func index(value: int) -> int:
|
|||
else:
|
||||
return value % _source_size
|
||||
|
||||
func range() -> BoundedRangeIterator:
|
||||
return BoundedRangeIterator.new(IntRange.new(start_index, end_index), IntRange.new(0, capacity))
|
||||
func get_range() -> IntRange:
|
||||
return IntRange.new(start_index, end_index)
|
||||
|
||||
func iter() -> BoundedRangeIterator:
|
||||
return BoundedRangeIterator.new(get_range(), IntRange.new(0, _source_size))
|
||||
|
||||
func move(direction: Direction) -> Result:
|
||||
if _source_size <= _capacity:
|
||||
return Result.err("source size is smaller than buffer capacity")
|
||||
var previous = range()
|
||||
push_warning("source size is smaller than buffer capacity")
|
||||
_index = self.index(_index + direction)
|
||||
updated.emit(range(), previous)
|
||||
rotated.emit(direction)
|
||||
return Result.Unit
|
||||
|
||||
func move_right() -> Result:
|
||||
|
|
Loading…
Add table
Reference in a new issue