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
|
class_name IntRange extends RefCounted
|
||||||
|
|
||||||
|
static var Zero = IntRange.new(0, 0)
|
||||||
|
|
||||||
var minmax: PackedInt32Array
|
var minmax: PackedInt32Array
|
||||||
|
|
||||||
var min: int:
|
var min: int:
|
||||||
get: return minmax[0]
|
get: return minmax[0]
|
||||||
|
|
||||||
var max: int:
|
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:
|
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:
|
func length() -> int:
|
||||||
return absi(max - min)
|
return absi(max - min)
|
||||||
|
@ -20,16 +29,16 @@ func is_zero() -> bool:
|
||||||
return min == 0 and max == 0
|
return min == 0 and max == 0
|
||||||
|
|
||||||
func is_empty() -> bool:
|
func is_empty() -> bool:
|
||||||
return is_zero()
|
return length() == 0
|
||||||
|
|
||||||
func iter(step: int = 1) -> RangeIterator:
|
func iter(step: int = 1) -> RangeIterator:
|
||||||
return RangeIterator.new(self, min, step)
|
return RangeIterator.new(self, min, step)
|
||||||
|
|
||||||
func clamp(value: int) -> int:
|
func clamp(value: int) -> int:
|
||||||
return clampi(value, min, max)
|
return clampi(value, minmax[0], minmax[1])
|
||||||
|
|
||||||
func wrap(value: int) -> int:
|
func wrap(value: int) -> int:
|
||||||
return wrapi(value, min, max)
|
return wrapi(value, minmax[0], minmax[1])
|
||||||
|
|
||||||
func contains(value: int) -> bool:
|
func contains(value: int) -> bool:
|
||||||
return value >= min and value < max
|
return value >= min and value < max
|
||||||
|
|
|
@ -1,29 +1,35 @@
|
||||||
class_name BoundedRangeIterator extends Iterator
|
class_name BoundedRangeIterator extends Iterator
|
||||||
|
|
||||||
var range: IntRange
|
var _range: IntRange
|
||||||
var bounds: IntRange
|
var _bounds: IntRange
|
||||||
var step: int
|
var _count: int
|
||||||
var limit: int
|
var _step: int
|
||||||
var index: int
|
var _items_yielded: int = 0
|
||||||
|
|
||||||
func _init(range: IntRange, bounds: IntRange, step: int = 1, limit: int = 1, start_index: int = range.min) -> void:
|
func _init(range: IntRange, bounds: IntRange, step: int = 1) -> void:
|
||||||
self.range = range
|
self._range = range
|
||||||
self.bounds = bounds
|
self._count = range.length()
|
||||||
self.step = step
|
self._bounds = bounds
|
||||||
self.limit = limit
|
self._step = step
|
||||||
self.index = start_index
|
|
||||||
|
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:
|
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:
|
func next() -> Option:
|
||||||
if bounds.contains(index):
|
if _items_yielded >= _count:
|
||||||
var current_value = Option.some(index)
|
return Option.none
|
||||||
index += step
|
|
||||||
return current_value
|
var index = _range.min + (_items_yielded * _step)
|
||||||
elif limit > 0:
|
var wrapped_index = _bounds.wrap(index)
|
||||||
limit -= 1
|
_items_yielded += 1
|
||||||
var current_value = bounds.wrap(index)
|
|
||||||
index = current_value + 1
|
return Option.some(wrapped_index)
|
||||||
return Option.some(current_value)
|
|
||||||
else: return Option.none
|
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
class_name Iterator extends RefCounted
|
class_name Iterator extends RefCounted
|
||||||
|
|
||||||
|
func _to_string() -> String:
|
||||||
|
return "Iterator"
|
||||||
|
|
||||||
func clone() -> Iterator:
|
func clone() -> Iterator:
|
||||||
assert(false, "can't clone a abstract base class")
|
assert(false, "can't clone a abstract base class")
|
||||||
return null
|
return null
|
||||||
|
|
|
@ -4,6 +4,7 @@ var index: int
|
||||||
var range: IntRange
|
var range: IntRange
|
||||||
var step: int
|
var step: int
|
||||||
var descending: bool
|
var descending: bool
|
||||||
|
var _done: bool = false
|
||||||
|
|
||||||
func _init(range: IntRange, start_index: int = range.min, step: int = 1) -> void:
|
func _init(range: IntRange, start_index: int = range.min, step: int = 1) -> void:
|
||||||
assert(step != 0, "step cannot be zero")
|
assert(step != 0, "step cannot be zero")
|
||||||
|
@ -23,8 +24,12 @@ func clone() -> RangeIterator:
|
||||||
return RangeIterator.new(range, index)
|
return RangeIterator.new(range, index)
|
||||||
|
|
||||||
func next() -> Option:
|
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)
|
var current_value = Option.some(index)
|
||||||
index += step
|
index += step
|
||||||
return current_value
|
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 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:
|
static func collect_some(options: Array[Option], ignore_none: bool = false) -> Option:
|
||||||
var result = []
|
var result = []
|
||||||
for option in options:
|
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"
|
action = "inventory"
|
||||||
|
|
||||||
[node name="ColorRect" type="ColorRect" parent="."]
|
[node name="ColorRect" type="ColorRect" parent="."]
|
||||||
visible = false
|
|
||||||
layout_mode = 1
|
layout_mode = 1
|
||||||
anchors_preset = 15
|
anchors_preset = 15
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
|
@ -43,18 +42,6 @@ layout_mode = 2
|
||||||
script = ExtResource("4_yyk2a")
|
script = ExtResource("4_yyk2a")
|
||||||
item_scene = ExtResource("5_uae8j")
|
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"]
|
[node name="Details" type="HBoxContainer" parent="VBoxContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
[gd_scene load_steps=3 format=3 uid="uid://gn8k2ir47n1m"]
|
[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="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")]
|
[node name="Item" type="BoxContainer" node_paths=PackedStringArray("name_label", "icon_texture")]
|
||||||
offset_right = 128.0
|
offset_right = 128.0
|
||||||
|
@ -18,8 +20,8 @@ layout_mode = 2
|
||||||
|
|
||||||
[node name="Name" type="Label" parent="VBoxContainer"]
|
[node name="Name" type="Label" parent="VBoxContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "Test Item"
|
text = "Empty"
|
||||||
|
|
||||||
[node name="Icon" type="TextureRect" parent="VBoxContainer"]
|
[node name="Icon" type="TextureRect" parent="VBoxContainer"]
|
||||||
layout_mode = 2
|
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
|
var ring_buffer: RingBuffer
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
ring_buffer = RingBuffer.new(items.size(), buffer_size, 1, -buffered_items)
|
ring_buffer = RingBuffer.new(items.size(), buffer_size, buffer_size - 1)
|
||||||
ring_buffer.updated.connect(_on_updated)
|
ring_buffer.rotated.connect(_on_rotated)
|
||||||
|
|
||||||
for _i in range(buffer_size):
|
for _i in range(buffer_size):
|
||||||
add_child(create_item.call())
|
add_child(create_item.call())
|
||||||
|
@ -30,21 +30,35 @@ func _hide_buffered_items():
|
||||||
func _create_item() -> Node:
|
func _create_item() -> Node:
|
||||||
return item_scene.instantiate()
|
return item_scene.instantiate()
|
||||||
|
|
||||||
func _bind_item(node: Node, item: Item):
|
func _bind_item(node: Node, item: Option):
|
||||||
if node.has_method('bind'):
|
if node.has_method('bind'):
|
||||||
node.call('bind', item)
|
node.call('bind', item)
|
||||||
|
|
||||||
func _on_updated(_current_range: IntRange, _previous_range: IntRange):
|
func _on_rotated(_direction: int):
|
||||||
_update_display()
|
_update_display()
|
||||||
|
|
||||||
func _update_display():
|
func _get_item(index: int) -> Option:
|
||||||
var indices: Array = ring_buffer.range().collect()
|
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 node = get_child(i)
|
||||||
var item = items[indices[i]]
|
var item_index_from_ring_buffer = indices[i]
|
||||||
if item != null:
|
var item_option = _get_item(item_index_from_ring_buffer)
|
||||||
bind_item.call(node, item)
|
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):
|
func add_item(item: Variant):
|
||||||
items.append(item)
|
items.append(item)
|
||||||
|
@ -55,3 +69,9 @@ func add_items(new_items: Array):
|
||||||
items.append_array(new_items)
|
items.append_array(new_items)
|
||||||
ring_buffer.source_size = items.size()
|
ring_buffer.source_size = items.size()
|
||||||
_update_display()
|
_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 name_label: Label
|
||||||
@export var icon_texture: TextureRect
|
@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
|
name_label.text = item.name
|
||||||
icon_texture.texture = item.icon
|
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 updated(new_range: IntRange, previous_range: IntRange)
|
||||||
|
signal rotated(direction: int)
|
||||||
|
|
||||||
var _source_size: int
|
var _source_size: int
|
||||||
var source_size: int:
|
var source_size: int:
|
||||||
|
@ -39,13 +40,16 @@ var selected_index: int:
|
||||||
set(value): set_selected(value)
|
set(value): set_selected(value)
|
||||||
|
|
||||||
func set_selected(value: int) -> void:
|
func set_selected(value: int) -> void:
|
||||||
|
var previous = self.get_range()
|
||||||
_index = self.index(value)
|
_index = self.index(value)
|
||||||
|
var current = self.get_range()
|
||||||
|
updated.emit(current, previous)
|
||||||
|
|
||||||
var start_index: int:
|
var start_index: int:
|
||||||
get: return self.index(_offset + _index)
|
get: return _index
|
||||||
|
|
||||||
var end_index: int:
|
var end_index: int:
|
||||||
get: return self.index(_offset + _index + _capacity - 1)
|
get: return start_index + capacity
|
||||||
|
|
||||||
@warning_ignore("shadowed_variable")
|
@warning_ignore("shadowed_variable")
|
||||||
func _init(source_size: int, capacity: int, start_index: int = 0, offset: int = 0) -> void:
|
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:
|
else:
|
||||||
return value % _source_size
|
return value % _source_size
|
||||||
|
|
||||||
func range() -> BoundedRangeIterator:
|
func get_range() -> IntRange:
|
||||||
return BoundedRangeIterator.new(IntRange.new(start_index, end_index), IntRange.new(0, capacity))
|
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:
|
func move(direction: Direction) -> Result:
|
||||||
if _source_size <= _capacity:
|
if _source_size <= _capacity:
|
||||||
return Result.err("source size is smaller than buffer capacity")
|
push_warning("source size is smaller than buffer capacity")
|
||||||
var previous = range()
|
|
||||||
_index = self.index(_index + direction)
|
_index = self.index(_index + direction)
|
||||||
updated.emit(range(), previous)
|
rotated.emit(direction)
|
||||||
return Result.Unit
|
return Result.Unit
|
||||||
|
|
||||||
func move_right() -> Result:
|
func move_right() -> Result:
|
||||||
|
|
Loading…
Add table
Reference in a new issue