add more iterators; add item pickups
This commit is contained in:
parent
262928664a
commit
d48e068a00
38 changed files with 488 additions and 142 deletions
|
@ -18,13 +18,22 @@ func _init(start: int, end: int, inclusive: bool = false) -> void:
|
||||||
minmax = PackedInt32Array([start, end])
|
minmax = PackedInt32Array([start, end])
|
||||||
self.inclusive = inclusive
|
self.inclusive = inclusive
|
||||||
|
|
||||||
|
static func from_sized(value: Variant) -> Result:
|
||||||
|
match KCUtils.get_size(value):
|
||||||
|
var len when len.is_ok():
|
||||||
|
return Result.ok(IntRange.new(0, len.unwrap()))
|
||||||
|
var e: return e
|
||||||
|
|
||||||
func _to_string() -> String:
|
func _to_string() -> String:
|
||||||
var ch = "]" if inclusive else ")"
|
var ch = "]" if inclusive else ")"
|
||||||
return "IntRange [%s, %s%s" % [min, max, ch]
|
return "IntRange [%s, %s%s" % [min, max, ch]
|
||||||
|
|
||||||
func length() -> int:
|
func size() -> int:
|
||||||
return absi(max - min)
|
return absi(max - min)
|
||||||
|
|
||||||
|
func length() -> int:
|
||||||
|
return size()
|
||||||
|
|
||||||
func is_zero() -> bool:
|
func is_zero() -> bool:
|
||||||
return min == 0 and max == 0
|
return min == 0 and max == 0
|
||||||
|
|
||||||
|
|
15
godot/addons/collections/tuple.gd
Normal file
15
godot/addons/collections/tuple.gd
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
class_name Tuple extends RefCounted
|
||||||
|
|
||||||
|
var _items: Array
|
||||||
|
|
||||||
|
func _init(items: Array) -> void:
|
||||||
|
_items = items
|
||||||
|
|
||||||
|
static func from_iter(iter: Iterator):
|
||||||
|
Tuple.new(iter.collect())
|
||||||
|
|
||||||
|
func iter() -> Iterator:
|
||||||
|
return ListIterator.from_array(_items)
|
||||||
|
|
||||||
|
func _get(property) -> Variant:
|
||||||
|
return _items[property]
|
1
godot/addons/collections/tuple.gd.uid
Normal file
1
godot/addons/collections/tuple.gd.uid
Normal file
|
@ -0,0 +1 @@
|
||||||
|
uid://crc57r28p8aem
|
23
godot/addons/iterator/dict.gd
Normal file
23
godot/addons/iterator/dict.gd
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
class_name DictionaryIterator extends Iterator
|
||||||
|
|
||||||
|
class Entry extends RefCounted:
|
||||||
|
var key
|
||||||
|
var value
|
||||||
|
|
||||||
|
func _init(key: Variant, value: Variant) -> void:
|
||||||
|
self.key = key
|
||||||
|
self.value = value
|
||||||
|
|
||||||
|
var dict: Dictionary
|
||||||
|
var keys: Iterator
|
||||||
|
|
||||||
|
func _init(dict: Dictionary) -> void:
|
||||||
|
self.dict = dict
|
||||||
|
self.keys = ListIterator.from_array(dict.keys())
|
||||||
|
|
||||||
|
func next() -> Option:
|
||||||
|
match keys.next():
|
||||||
|
var _key when _key.is_some():
|
||||||
|
var key = _key.unwrap()
|
||||||
|
return Option.some(Entry.new(key, dict[key]))
|
||||||
|
return Option.none
|
1
godot/addons/iterator/dict.gd.uid
Normal file
1
godot/addons/iterator/dict.gd.uid
Normal file
|
@ -0,0 +1 @@
|
||||||
|
uid://bvt4ktq7etavr
|
4
godot/addons/iterator/empty.gd
Normal file
4
godot/addons/iterator/empty.gd
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
class_name EmptyIterator extends Iterator
|
||||||
|
|
||||||
|
func next() -> Option:
|
||||||
|
return Option.none
|
1
godot/addons/iterator/empty.gd.uid
Normal file
1
godot/addons/iterator/empty.gd.uid
Normal file
|
@ -0,0 +1 @@
|
||||||
|
uid://dqbfj2kctxnwp
|
14
godot/addons/iterator/filter.gd
Normal file
14
godot/addons/iterator/filter.gd
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
class_name FilterIterator extends Iterator
|
||||||
|
|
||||||
|
var iterator: Iterator
|
||||||
|
var predicate: Callable
|
||||||
|
|
||||||
|
func _init(iterator: Iterator, predicate: Callable) -> void:
|
||||||
|
self.iterator = iterator
|
||||||
|
self.predicate = predicate
|
||||||
|
|
||||||
|
func next() -> Option:
|
||||||
|
var value = iterator.next()
|
||||||
|
while value.is_some() and not predicate.call(value.unwrap()):
|
||||||
|
value = iterator.next()
|
||||||
|
return value
|
1
godot/addons/iterator/filter.gd.uid
Normal file
1
godot/addons/iterator/filter.gd.uid
Normal file
|
@ -0,0 +1 @@
|
||||||
|
uid://bmt0rqpkd5ugi
|
15
godot/addons/iterator/inspect.gd
Normal file
15
godot/addons/iterator/inspect.gd
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
class_name InspectIterator extends Iterator
|
||||||
|
|
||||||
|
var iterator: Iterator
|
||||||
|
var fn: Callable
|
||||||
|
|
||||||
|
func _init(iterator: Iterator, fn: Callable) -> void:
|
||||||
|
self.iterator = iterator
|
||||||
|
self.fn = fn
|
||||||
|
|
||||||
|
func next() -> Option:
|
||||||
|
match iterator.next():
|
||||||
|
var x when x.is_some():
|
||||||
|
fn.call(x.unwrap())
|
||||||
|
return x
|
||||||
|
var x: return x
|
1
godot/addons/iterator/inspect.gd.uid
Normal file
1
godot/addons/iterator/inspect.gd.uid
Normal file
|
@ -0,0 +1 @@
|
||||||
|
uid://bvnn2llh6fmo0
|
|
@ -1,33 +1,114 @@
|
||||||
class_name Iterator extends RefCounted
|
class_name Iterator extends RefCounted
|
||||||
|
|
||||||
|
static func repeat(value: Variant) -> RepeatIterator:
|
||||||
|
return RepeatIterator.new(value)
|
||||||
|
|
||||||
func _to_string() -> String:
|
func _to_string() -> String:
|
||||||
return "Iterator"
|
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
|
||||||
|
|
||||||
func next() -> Option:
|
func next() -> Option:
|
||||||
return Option.none
|
return Option.none
|
||||||
|
|
||||||
|
static func empty() -> Iterator:
|
||||||
|
return EmptyIterator.new()
|
||||||
|
|
||||||
|
func advance_by(amount: int) -> Iterator:
|
||||||
|
for _i in range(amount):
|
||||||
|
if self.next().is_none():
|
||||||
|
return empty()
|
||||||
|
return self
|
||||||
|
|
||||||
|
func all(predicate: Callable) -> bool:
|
||||||
|
for value in self:
|
||||||
|
if not predicate.call(value):
|
||||||
|
return false
|
||||||
|
return true
|
||||||
|
|
||||||
|
func any(predicate: Callable) -> bool:
|
||||||
|
for value in self:
|
||||||
|
if predicate.call(value):
|
||||||
|
return true
|
||||||
|
return false
|
||||||
|
|
||||||
func collect() -> Array:
|
func collect() -> Array:
|
||||||
var result = []
|
var result = []
|
||||||
for item in self:
|
for item in self:
|
||||||
result.append(item)
|
result.append(item)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
func into_peekable() -> PeekableIter:
|
func count() -> int:
|
||||||
return PeekableIter.new(self)
|
var length = 0
|
||||||
|
for _value in self:
|
||||||
|
length += 1
|
||||||
|
return length
|
||||||
|
|
||||||
func into_indexed() -> IndexedIterator:
|
func enumerate() -> IndexedIterator:
|
||||||
return IndexedIterator.new(self)
|
return IndexedIterator.new(self)
|
||||||
|
|
||||||
|
func filter(predicate: Callable) -> FilterIterator:
|
||||||
|
return FilterIterator.new(self, predicate)
|
||||||
|
|
||||||
|
func find(predicate: Callable) -> Option:
|
||||||
|
for value in self:
|
||||||
|
if predicate.call(value):
|
||||||
|
return Option.some(value)
|
||||||
|
return Option.none
|
||||||
|
|
||||||
|
func fuse(other: Iterator) -> FusedIterator:
|
||||||
|
return FusedIterator.new([self, other])
|
||||||
|
|
||||||
|
func inspect(fn: Callable) -> Iterator:
|
||||||
|
return InspectIterator.new(self, fn)
|
||||||
|
|
||||||
|
func last() -> Option:
|
||||||
|
var last = Option.none
|
||||||
|
for value in self:
|
||||||
|
last = Option.some(value)
|
||||||
|
return last
|
||||||
|
|
||||||
|
func map(fn: Callable) -> MapIterator:
|
||||||
|
return MapIterator.new(self, fn)
|
||||||
|
|
||||||
|
func peekable() -> PeekableIter:
|
||||||
|
return PeekableIter.new(self)
|
||||||
|
|
||||||
|
func position(predicate: Callable) -> Option:
|
||||||
|
for indexed_value in self.enumerate():
|
||||||
|
if predicate.call(indexed_value.value):
|
||||||
|
return Option.some(indexed_value.index)
|
||||||
|
return Option.none
|
||||||
|
|
||||||
|
func reduce(reducer: Callable, initial_value: Variant) -> Option:
|
||||||
|
return scan(reducer, initial_value).last()
|
||||||
|
|
||||||
|
func scan(reducer: Callable, initial_value: Variant) -> ReduceIterator:
|
||||||
|
return ReduceIterator.new(self, reducer, initial_value)
|
||||||
|
|
||||||
|
func skip(amount: int) -> SkipIterator:
|
||||||
|
return SkipIterator.new(self, amount)
|
||||||
|
|
||||||
|
func skip_while(predicate: Callable) -> SkipWhileIterator:
|
||||||
|
return SkipWhileIterator.new(self, predicate)
|
||||||
|
|
||||||
|
func take(limit: int) -> TakeIterator:
|
||||||
|
return TakeIterator.new(self, limit)
|
||||||
|
|
||||||
|
func take_while(predicate: Callable) -> TakeWhileIter:
|
||||||
|
return TakeWhileIter.new(self, predicate)
|
||||||
|
|
||||||
|
func zip(a: Iterator, b: Iterator) -> ZipIterator:
|
||||||
|
return ZipIterator.new(a, b)
|
||||||
|
|
||||||
func _iter_init(iter: Array) -> bool:
|
func _iter_init(iter: Array) -> bool:
|
||||||
return _iter_next(iter)
|
return _iter_next(iter)
|
||||||
|
|
||||||
func _iter_next(iter: Array) -> bool:
|
func _iter_next(iter: Array) -> bool:
|
||||||
iter[0] = next()
|
iter[0] = next()
|
||||||
return iter[0].is_some()
|
return iter[0].is_some()
|
||||||
|
|
||||||
func _iter_get(iter: Variant) -> Variant:
|
func _iter_get(iter: Variant) -> Variant:
|
||||||
return iter.unwrap()
|
return iter.unwrap()
|
||||||
|
|
|
@ -7,6 +7,9 @@ func _init(value: Variant, iter: RangeIterator) -> void:
|
||||||
_value = value
|
_value = value
|
||||||
_iter = iter
|
_iter = iter
|
||||||
|
|
||||||
|
static func from_array(array: Array) -> ListIterator:
|
||||||
|
return ListIterator.new(array, RangeIterator.from_array(array))
|
||||||
|
|
||||||
func _at(index: int) -> Variant:
|
func _at(index: int) -> Variant:
|
||||||
return _value[index]
|
return _value[index]
|
||||||
|
|
||||||
|
|
14
godot/addons/iterator/map.gd
Normal file
14
godot/addons/iterator/map.gd
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
class_name MapIterator extends Iterator
|
||||||
|
|
||||||
|
var iterator: Iterator
|
||||||
|
var morphism: Callable
|
||||||
|
|
||||||
|
func _init(iterator: Iterator, fn: Callable) -> void:
|
||||||
|
self.iterator = iterator
|
||||||
|
self.morphism = fn
|
||||||
|
|
||||||
|
func next() -> Option:
|
||||||
|
match iterator.next():
|
||||||
|
var x when x.is_some():
|
||||||
|
return Option.some(morphism.call(x.unwrap()))
|
||||||
|
_: return Option.none
|
1
godot/addons/iterator/map.gd.uid
Normal file
1
godot/addons/iterator/map.gd.uid
Normal file
|
@ -0,0 +1 @@
|
||||||
|
uid://y6345wflhmr1
|
|
@ -17,6 +17,18 @@ func _init(range: IntRange, start_index: int = range.min, step: int = 1) -> void
|
||||||
func from_values(from: int, to: int, start_index: int = range.min, step: int = 1) -> RangeIterator:
|
func from_values(from: int, to: int, start_index: int = range.min, step: int = 1) -> RangeIterator:
|
||||||
return RangeIterator.new(IntRange.new(from, to), start_index, step)
|
return RangeIterator.new(IntRange.new(from, to), start_index, step)
|
||||||
|
|
||||||
|
static func from_sized(value: Variant) -> Result:
|
||||||
|
match IntRange.from_sized(value):
|
||||||
|
var range when range.is_ok():
|
||||||
|
return Result.ok(RangeIterator.new(range.unwrap()))
|
||||||
|
var e: return e
|
||||||
|
|
||||||
|
static func from_array(array: Array) -> RangeIterator:
|
||||||
|
return RangeIterator.from_sized(array).unwrap()
|
||||||
|
|
||||||
|
func size() -> int:
|
||||||
|
return range.size()
|
||||||
|
|
||||||
func length() -> int:
|
func length() -> int:
|
||||||
return range.length()
|
return range.length()
|
||||||
|
|
||||||
|
|
21
godot/addons/iterator/reduce.gd
Normal file
21
godot/addons/iterator/reduce.gd
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
class_name ReduceIterator extends Iterator
|
||||||
|
|
||||||
|
var iterator: Iterator
|
||||||
|
var reducer: Callable
|
||||||
|
var accumulator: Variant
|
||||||
|
|
||||||
|
func _init(iterator: Iterator, reducer: Callable, initial_value: Variant) -> void:
|
||||||
|
self.iterator = iterator
|
||||||
|
self.reducer = reducer
|
||||||
|
accumulator = initial_value
|
||||||
|
|
||||||
|
func next() -> Option:
|
||||||
|
var value = iterator.next()
|
||||||
|
if value.is_none(): return value
|
||||||
|
|
||||||
|
if accumulator == null:
|
||||||
|
accumulator = value
|
||||||
|
else:
|
||||||
|
accumulator = reducer.call(accumulator, value)
|
||||||
|
|
||||||
|
return Option.some(accumulator)
|
1
godot/addons/iterator/reduce.gd.uid
Normal file
1
godot/addons/iterator/reduce.gd.uid
Normal file
|
@ -0,0 +1 @@
|
||||||
|
uid://d1nuo4gmvw6gb
|
9
godot/addons/iterator/repeat.gd
Normal file
9
godot/addons/iterator/repeat.gd
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
class_name RepeatIterator extends Iterator
|
||||||
|
|
||||||
|
var value: Variant
|
||||||
|
|
||||||
|
func _init(value: Variant) -> void:
|
||||||
|
self.value = value
|
||||||
|
|
||||||
|
func next() -> Option:
|
||||||
|
return Option.some(value)
|
1
godot/addons/iterator/repeat.gd.uid
Normal file
1
godot/addons/iterator/repeat.gd.uid
Normal file
|
@ -0,0 +1 @@
|
||||||
|
uid://bmfuvpufiq7fl
|
15
godot/addons/iterator/skip.gd
Normal file
15
godot/addons/iterator/skip.gd
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
class_name SkipIterator extends Iterator
|
||||||
|
|
||||||
|
var iterator: Iterator
|
||||||
|
var amount: int
|
||||||
|
var _skipped: bool = false
|
||||||
|
|
||||||
|
func _init(iterator: Iterator, amount: int) -> void:
|
||||||
|
self.iterator = iterator
|
||||||
|
self.amount = amount
|
||||||
|
|
||||||
|
func next() -> Option:
|
||||||
|
if not _skipped:
|
||||||
|
iterator.advance_by(amount)
|
||||||
|
_skipped = true
|
||||||
|
return iterator.next()
|
1
godot/addons/iterator/skip.gd.uid
Normal file
1
godot/addons/iterator/skip.gd.uid
Normal file
|
@ -0,0 +1 @@
|
||||||
|
uid://mg6bs321701m
|
18
godot/addons/iterator/skip_while.gd
Normal file
18
godot/addons/iterator/skip_while.gd
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
class_name SkipWhileIterator extends Iterator
|
||||||
|
|
||||||
|
var iterator: Iterator
|
||||||
|
var predicate: Callable
|
||||||
|
var _skipped: bool = false
|
||||||
|
|
||||||
|
func _init(iterator: Iterator, predicate: Callable) -> void:
|
||||||
|
self.iterator = iterator
|
||||||
|
self.predicate = predicate
|
||||||
|
|
||||||
|
func next() -> Option:
|
||||||
|
if not _skipped:
|
||||||
|
var value = iterator.next()
|
||||||
|
while value.is_some() and predicate.call(value):
|
||||||
|
value = iterator.next()
|
||||||
|
_skipped = true
|
||||||
|
return value
|
||||||
|
return iterator.next()
|
1
godot/addons/iterator/skip_while.gd.uid
Normal file
1
godot/addons/iterator/skip_while.gd.uid
Normal file
|
@ -0,0 +1 @@
|
||||||
|
uid://i2jri31g6mam
|
15
godot/addons/iterator/take.gd
Normal file
15
godot/addons/iterator/take.gd
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
class_name TakeIterator extends Iterator
|
||||||
|
|
||||||
|
var iter: Iterator
|
||||||
|
var limit: int
|
||||||
|
|
||||||
|
func _init(iter: Iterator, limit: int) -> void:
|
||||||
|
self.iter = iter
|
||||||
|
self.limit = limit
|
||||||
|
|
||||||
|
func next() -> Option:
|
||||||
|
if limit < 0:
|
||||||
|
return Option.none
|
||||||
|
|
||||||
|
limit -= 1
|
||||||
|
return iter.next()
|
1
godot/addons/iterator/take.gd.uid
Normal file
1
godot/addons/iterator/take.gd.uid
Normal file
|
@ -0,0 +1 @@
|
||||||
|
uid://dnxnj6qn8fqrq
|
14
godot/addons/iterator/zip.gd
Normal file
14
godot/addons/iterator/zip.gd
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
class_name ZipIterator extends Iterator
|
||||||
|
|
||||||
|
var iter1: Iterator
|
||||||
|
var iter2: Iterator
|
||||||
|
|
||||||
|
func _init(a: Iterator, b: Iterator) -> void:
|
||||||
|
iter1 = a
|
||||||
|
iter2 = b
|
||||||
|
|
||||||
|
func next() -> Option:
|
||||||
|
match [iter1.next(), iter2.next()]:
|
||||||
|
[var a, var b] when a.is_some() and b.is_some():
|
||||||
|
return Option.some(Tuple.new([a.unwrap(), b.unwrap()]))
|
||||||
|
_: return Option.none
|
1
godot/addons/iterator/zip.gd.uid
Normal file
1
godot/addons/iterator/zip.gd.uid
Normal file
|
@ -0,0 +1 @@
|
||||||
|
uid://bu2orcurqmml1
|
|
@ -1,49 +1,63 @@
|
||||||
class_name KCUtils
|
class_name KCUtils
|
||||||
|
|
||||||
static func remove_children(node: Node):
|
static func remove_children(node: Node, delete: bool = true):
|
||||||
for i in range(node.get_child_count()):
|
for i in range(node.get_child_count() - 1, -1, -1):
|
||||||
node.remove_child(node.get_child(i))
|
var child = node.get_child(i)
|
||||||
|
node.remove_child(child)
|
||||||
|
if delete:
|
||||||
|
child.queue_free()
|
||||||
|
|
||||||
static func get_class_name(value: Object) -> String:
|
static func get_class_name(value: Object) -> String:
|
||||||
match value.get_script():
|
match value.get_script():
|
||||||
var script when script != null:
|
var script when script != null:
|
||||||
match script.get_global_name():
|
match script.get_global_name():
|
||||||
var name when name != null: return name
|
var name when name != null: return name
|
||||||
_: return script.get_instance_base_type()
|
_: return script.get_instance_base_type()
|
||||||
_: return value.get_class()
|
_: return value.get_class()
|
||||||
|
|
||||||
static func is_string_like(value: Variant) -> bool:
|
static func is_string_like(value: Variant) -> bool:
|
||||||
match typeof(value):
|
match typeof(value):
|
||||||
TYPE_STRING: return true
|
TYPE_STRING: return true
|
||||||
TYPE_STRING_NAME: return true
|
TYPE_STRING_NAME: return true
|
||||||
TYPE_NODE_PATH: return true
|
TYPE_NODE_PATH: return true
|
||||||
_: return false
|
_: return false
|
||||||
|
|
||||||
static func to_str(value: Variant) -> String:
|
static func to_str(value: Variant) -> String:
|
||||||
match typeof(value):
|
match typeof(value):
|
||||||
TYPE_OBJECT:
|
TYPE_OBJECT:
|
||||||
if value.has_method('_to_string'):
|
if value.has_method('_to_string'):
|
||||||
return value.to_string()
|
return value.to_string()
|
||||||
else:
|
else:
|
||||||
var name = get_class_name(value)
|
var name = get_class_name(value)
|
||||||
value = value as Object
|
value = value as Object
|
||||||
var props: Dictionary = inst_to_dict(value)
|
var props: Dictionary = inst_to_dict(value)
|
||||||
return "%s %s" % [name, to_str(props)]
|
return "%s %s" % [name, to_str(props)]
|
||||||
_: return str(value)
|
_: return str(value)
|
||||||
|
|
||||||
static func propagate(node: Node, fn: StringName, args: Array, call_on_self: bool = true):
|
static func propagate(node: Node, fn: StringName, args: Array, call_on_self: bool = true):
|
||||||
if call_on_self and node.has_method(fn):
|
if call_on_self and node.has_method(fn):
|
||||||
node.callv(fn, args)
|
node.callv(fn, args)
|
||||||
|
|
||||||
for child in node.get_children():
|
for child in node.get_children():
|
||||||
propagate(child, fn, args)
|
propagate(child, fn, args)
|
||||||
|
|
||||||
static func propagate_input_event(node: Node, fn: StringName, event: InputEvent, call_on_self: bool = true):
|
static func propagate_input_event(node: Node, fn: StringName, event: InputEvent, call_on_self: bool = true):
|
||||||
if node.get_viewport().is_input_handled() or event.is_canceled():
|
if node.get_viewport().is_input_handled() or event.is_canceled():
|
||||||
return
|
return
|
||||||
|
|
||||||
if call_on_self and node.has_method(fn):
|
if call_on_self and node.has_method(fn):
|
||||||
node.callv(fn, [event])
|
node.callv(fn, [event])
|
||||||
|
|
||||||
for child in node.get_children():
|
for child in node.get_children():
|
||||||
propagate_input_event(child, fn, event)
|
propagate_input_event(child, fn, event)
|
||||||
|
|
||||||
|
static func get_size(value: Variant) -> Result:
|
||||||
|
match typeof(value):
|
||||||
|
TYPE_STRING | TYPE_VECTOR2 | TYPE_VECTOR2I | TYPE_VECTOR3 | TYPE_VECTOR3I | TYPE_VECTOR4 | TYPE_VECTOR4I | TYPE_QUATERNION:
|
||||||
|
return Result.ok(value.length())
|
||||||
|
var x when x >= 27 and x <= 38:
|
||||||
|
return Result.ok(value.size())
|
||||||
|
_: return Result.err(Error.NotImplemented.new('"length" or "size"'))
|
||||||
|
|
||||||
|
static func len(value: Variant) -> int:
|
||||||
|
return get_size(value).unwrap()
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
[gd_resource type="Resource" script_class="Equipment" load_steps=3 format=3 uid="uid://cxm3s081hnw8l"]
|
[gd_resource type="Resource" script_class="Equipment" load_steps=2 format=3 uid="uid://cxm3s081hnw8l"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://bff1tgf3sn855" path="res://src/equipment.gd" id="1_ajqsy"]
|
[ext_resource type="Script" uid="uid://bff1tgf3sn855" path="res://src/equipment.gd" id="1_ajqsy"]
|
||||||
[ext_resource type="Resource" uid="uid://crgwey6ibaf2h" path="res://resources/items/pistol.tres" id="1_hds1i"]
|
|
||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
script = ExtResource("1_ajqsy")
|
script = ExtResource("1_ajqsy")
|
||||||
_primary = ExtResource("1_hds1i")
|
|
||||||
metadata/_custom_type_script = "uid://bff1tgf3sn855"
|
metadata/_custom_type_script = "uid://bff1tgf3sn855"
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
[gd_scene load_steps=10 format=3 uid="uid://cn7tgd4y67wnd"]
|
[gd_scene load_steps=12 format=3 uid="uid://cn7tgd4y67wnd"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://qvoqvonnxwfc" path="res://src/inventory_ui.gd" id="1_a0rpf"]
|
[ext_resource type="Script" uid="uid://qvoqvonnxwfc" path="res://src/inventory_ui.gd" id="1_a0rpf"]
|
||||||
[ext_resource type="Script" uid="uid://bx4wxlm5mv268" path="res://src/root_control.gd" id="1_as33y"]
|
[ext_resource type="Script" uid="uid://bx4wxlm5mv268" path="res://src/root_control.gd" id="1_as33y"]
|
||||||
[ext_resource type="Resource" uid="uid://bllq6ri54q3ne" path="res://resources/player_inventory.tres" id="2_as33y"]
|
[ext_resource type="Resource" uid="uid://bllq6ri54q3ne" path="res://resources/player_inventory.tres" id="2_as33y"]
|
||||||
[ext_resource type="PackedScene" uid="uid://gn8k2ir47n1m" path="res://scenes/inventory_item.tscn" id="3_tg4gd"]
|
[ext_resource type="PackedScene" uid="uid://gn8k2ir47n1m" path="res://scenes/inventory_item.tscn" id="3_tg4gd"]
|
||||||
[ext_resource type="Script" uid="uid://13lxe4c4fmrp" path="res://addons/FreeControl/src/CustomClasses/Carousel/Carousel.gd" id="4_usnyx"]
|
[ext_resource type="Script" uid="uid://bpwbaanf6w65h" path="res://src/index_carousel.gd" id="5_uae8j"]
|
||||||
|
[ext_resource type="Script" uid="uid://c8m7eq6a3tpgu" path="res://src/item_details_ui.gd" id="6_s887n"]
|
||||||
|
[ext_resource type="Resource" uid="uid://cxm3s081hnw8l" path="res://resources/player_equipment.tres" id="7_s887n"]
|
||||||
|
|
||||||
[sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_as33y"]
|
[sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_as33y"]
|
||||||
size = Vector2(128, 128)
|
size = Vector2(128, 128)
|
||||||
|
@ -66,14 +68,21 @@ anchor_right = 1.0
|
||||||
anchor_bottom = 1.0
|
anchor_bottom = 1.0
|
||||||
grow_horizontal = 2
|
grow_horizontal = 2
|
||||||
grow_vertical = 2
|
grow_vertical = 2
|
||||||
script = ExtResource("4_usnyx")
|
script = ExtResource("5_uae8j")
|
||||||
|
with_drag = true
|
||||||
|
with_clamp = true
|
||||||
display_range = 5
|
display_range = 5
|
||||||
snap_behavior = 2
|
snap_behavior = 2
|
||||||
paging_requirement = 100
|
paging_requirement = 100
|
||||||
|
metadata/_custom_type_script = "uid://bpwbaanf6w65h"
|
||||||
|
|
||||||
[node name="ItemDetails" type="HBoxContainer" parent="Contents"]
|
[node name="ItemDetails" type="HBoxContainer" parent="Contents" node_paths=PackedStringArray("icon_image", "description_label")]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
size_flags_vertical = 3
|
size_flags_vertical = 3
|
||||||
|
script = ExtResource("6_s887n")
|
||||||
|
equipment = ExtResource("7_s887n")
|
||||||
|
icon_image = NodePath("Display/TextureRect")
|
||||||
|
description_label = NodePath("Description/Label")
|
||||||
|
|
||||||
[node name="PlayerInfo" type="VBoxContainer" parent="Contents/ItemDetails"]
|
[node name="PlayerInfo" type="VBoxContainer" parent="Contents/ItemDetails"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
@ -110,3 +119,5 @@ size_flags_horizontal = 3
|
||||||
[node name="Label" type="Label" parent="Contents/ItemDetails/Description"]
|
[node name="Label" type="Label" parent="Contents/ItemDetails/Description"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "a description"
|
text = "a description"
|
||||||
|
|
||||||
|
[connection signal="item_selected" from="Contents/InventoryUI" to="Contents/ItemDetails" method="_on_updated"]
|
||||||
|
|
18
godot/src/index_carousel.gd
Normal file
18
godot/src/index_carousel.gd
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
@tool
|
||||||
|
class_name IndexCarousel extends Carousel
|
||||||
|
|
||||||
|
signal index_changed(index: int)
|
||||||
|
|
||||||
|
@export var with_drag: bool = false
|
||||||
|
@export var with_clamp: bool = false
|
||||||
|
|
||||||
|
var current_index: int = 0
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
current_index = get_carousel_index(with_drag, with_clamp)
|
||||||
|
|
||||||
|
func _on_progress(_scroll: int) -> void:
|
||||||
|
var next_index = get_carousel_index(with_drag, with_clamp)
|
||||||
|
if current_index != next_index:
|
||||||
|
current_index = next_index
|
||||||
|
index_changed.emit(current_index)
|
1
godot/src/index_carousel.gd.uid
Normal file
1
godot/src/index_carousel.gd.uid
Normal file
|
@ -0,0 +1 @@
|
||||||
|
uid://bpwbaanf6w65h
|
|
@ -1,75 +1,60 @@
|
||||||
class_name Inventory extends Resource
|
class_name Inventory extends Resource
|
||||||
|
|
||||||
class InventoryIterator extends Iterator:
|
|
||||||
var values: Array[ItemInstance]
|
|
||||||
var size: int
|
|
||||||
var index: int = 0
|
|
||||||
|
|
||||||
@warning_ignore("shadowed_variable")
|
|
||||||
func _init(values: Array[ItemInstance], size: int = values.size()) -> void:
|
|
||||||
self.values = values
|
|
||||||
self.size = size
|
|
||||||
|
|
||||||
func next() -> Option:
|
|
||||||
if index < size:
|
|
||||||
var value = Option.some(values[index])
|
|
||||||
index += 1
|
|
||||||
return value
|
|
||||||
else:
|
|
||||||
return Option.none
|
|
||||||
|
|
||||||
@export var initial_items: Array[ItemInstance]
|
|
||||||
@export var max_capacity: int = 6
|
|
||||||
|
|
||||||
var items: Dictionary[int, ItemInstance]
|
|
||||||
var size: int:
|
|
||||||
get: return items.size()
|
|
||||||
|
|
||||||
signal item_added(item: Item, quantity: int)
|
signal item_added(item: Item, quantity: int)
|
||||||
signal item_removed(item: Item, remaining: int)
|
signal item_removed(item: Item, remaining: int)
|
||||||
signal updated
|
signal updated
|
||||||
|
|
||||||
|
@export var initial_items: Array[ItemInstance]
|
||||||
|
@export var max_capacity: int = 6
|
||||||
|
|
||||||
|
var items: Dictionary[int, ItemInstance]
|
||||||
|
var empty_slots: int:
|
||||||
|
get: return max_capacity - size()
|
||||||
|
|
||||||
func _init():
|
func _init():
|
||||||
call_deferred("_ready")
|
call_deferred("_ready")
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
for item in initial_items:
|
for item in initial_items:
|
||||||
items[_get_id(item.item)] = item
|
items[_get_id(item.item)] = item
|
||||||
updated.emit()
|
updated.emit()
|
||||||
|
|
||||||
|
func size() -> int:
|
||||||
|
return items.size()
|
||||||
|
|
||||||
func _get_id(item: Item) -> int:
|
func _get_id(item: Item) -> int:
|
||||||
return item.get_instance_id()
|
return item.get_instance_id()
|
||||||
|
|
||||||
func _item_eq(a: Item, b: ItemInstance) -> bool:
|
func _item_eq(a: Item, b: ItemInstance) -> bool:
|
||||||
return a.item == b
|
return a.item == b
|
||||||
|
|
||||||
func has_item(item: Item) -> bool:
|
func has_item(item: Item) -> bool:
|
||||||
return items.has(_get_id(item))
|
return items.has(_get_id(item))
|
||||||
|
|
||||||
func find(item: Item) -> Option:
|
func find(item: Item) -> Option:
|
||||||
match items.get(_get_id(item)):
|
match items.get(_get_id(item)):
|
||||||
null: return Option.none
|
null: return Option.none
|
||||||
var found: return Option.some(found)
|
var found: return Option.some(found)
|
||||||
|
|
||||||
func add_item(item: Item, quantity: int = 1):
|
func add_item(item: Item, quantity: int = 1):
|
||||||
var id = _get_id(item)
|
var id = _get_id(item)
|
||||||
var updated_quantity = quantity
|
var updated_quantity = quantity
|
||||||
if items.has(id):
|
if items.has(id):
|
||||||
items[id].quantity += quantity
|
items[id].quantity += quantity
|
||||||
updated_quantity = items[id].quantity
|
updated_quantity = items[id].quantity
|
||||||
else:
|
else:
|
||||||
items[id] = ItemInstance.new(item, quantity)
|
items[id] = ItemInstance.new(item, quantity)
|
||||||
|
|
||||||
item_added.emit(item, updated_quantity)
|
item_added.emit(item, updated_quantity)
|
||||||
updated.emit()
|
updated.emit()
|
||||||
|
|
||||||
func remove_item(item: Item, quantity: int = 1):
|
func remove_item(item: Item, quantity: int = 1):
|
||||||
if find(item):
|
if find(item):
|
||||||
item.quantity -= quantity
|
item.quantity -= quantity
|
||||||
if item.quantity <= 0:
|
if item.quantity <= 0:
|
||||||
items.erase(_get_id(item))
|
items.erase(_get_id(item))
|
||||||
item_removed.emit(item, item.quantity)
|
item_removed.emit(item, item.quantity)
|
||||||
updated.emit()
|
updated.emit()
|
||||||
|
|
||||||
func iter() -> InventoryIterator:
|
func iter() -> Iterator:
|
||||||
return InventoryIterator.new(items.values(), max_capacity)
|
return DictionaryIterator.new(items)
|
||||||
|
|
|
@ -1,44 +1,68 @@
|
||||||
class_name InventoryUI extends Control
|
class_name InventoryUI extends Control
|
||||||
|
|
||||||
|
signal item_selected(item: Option)
|
||||||
|
|
||||||
@export var inventory: Inventory
|
@export var inventory: Inventory
|
||||||
@export var item_scene: PackedScene
|
@export var item_scene: PackedScene
|
||||||
@export var carousel: Carousel
|
@export var carousel: IndexCarousel
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
inventory.updated.connect(_build_carousel)
|
inventory.updated.connect(_build_carousel)
|
||||||
|
carousel.index_changed.connect(_on_item_changed)
|
||||||
|
|
||||||
func _build_carousel():
|
func _on_item_changed(index: int) -> void:
|
||||||
KCUtils.remove_children(carousel)
|
var found: bool = false
|
||||||
|
for indexed_value in IndexedIterator.new(inventory.iter()):
|
||||||
|
if indexed_value.index == index:
|
||||||
|
found = true
|
||||||
|
item_selected.emit(Option.from(indexed_value.value.value.item))
|
||||||
|
break
|
||||||
|
|
||||||
var items = inventory.items.values()
|
if not found:
|
||||||
var count = items.size()
|
item_selected.emit(Option.none)
|
||||||
for i in range(inventory.max_capacity):
|
|
||||||
var scene = create_item()
|
func _build_carousel() -> void:
|
||||||
var value = Option.none
|
KCUtils.remove_children(carousel)
|
||||||
if i < count:
|
|
||||||
value = Option.some(items[i].item)
|
var empty_iter = Iterator.repeat(null).take(inventory.empty_slots)
|
||||||
bind_item(scene, value)
|
var item_iter = ListIterator.from_array(inventory.items.values().map(func(x): return x.item))
|
||||||
carousel.add_child(scene)
|
var items = FusedIterator.new([item_iter, empty_iter])
|
||||||
|
|
||||||
|
for item in items:
|
||||||
|
var scene = create_item()
|
||||||
|
var option = Option.from(item)
|
||||||
|
bind_item(scene, option)
|
||||||
|
carousel.add_child(scene)
|
||||||
|
|
||||||
|
#var items = inventory.items.values()
|
||||||
|
#var count = items.size()
|
||||||
|
#for i in range(inventory.max_capacity):
|
||||||
|
# var scene = create_item()
|
||||||
|
# var value = Option.none
|
||||||
|
# if i < count:
|
||||||
|
# value = Option.some(items[i].item)
|
||||||
|
# bind_item(scene, value)
|
||||||
|
# carousel.add_child(scene)
|
||||||
|
|
||||||
func create_item() -> Node:
|
func create_item() -> Node:
|
||||||
return item_scene.instantiate()
|
return item_scene.instantiate()
|
||||||
|
|
||||||
func bind_item(node: Node, item: Option):
|
func bind_item(node: Node, item: Option) -> void:
|
||||||
if node.has_method('bind'):
|
if node.has_method('bind'):
|
||||||
node.bind(item)
|
node.bind(item)
|
||||||
|
|
||||||
func _gui_input(event: InputEvent) -> void:
|
func _gui_input(event: InputEvent) -> void:
|
||||||
if event.is_action_pressed(PlayerInput.UIAction.Right):
|
if event.is_action_pressed(PlayerInput.UIAction.Right):
|
||||||
move_right()
|
move_right()
|
||||||
elif event.is_action_pressed(PlayerInput.UIAction.Left):
|
elif event.is_action_pressed(PlayerInput.UIAction.Left):
|
||||||
move_left()
|
move_left()
|
||||||
|
|
||||||
func move_by(delta: int):
|
func move_by(delta: int):
|
||||||
var next_index = carousel.get_carousel_index() + delta
|
var next_index = carousel.get_carousel_index() + delta
|
||||||
carousel.go_to_index(next_index)
|
carousel.go_to_index(next_index)
|
||||||
|
|
||||||
func move_right():
|
func move_right():
|
||||||
move_by(1)
|
move_by(1)
|
||||||
|
|
||||||
func move_left():
|
func move_left():
|
||||||
move_by(-1)
|
move_by(-1)
|
||||||
|
|
|
@ -14,5 +14,5 @@ func add_item(item: Item, quantity: int = 1):
|
||||||
func remove_item(item: Item, quantity: int = 1):
|
func remove_item(item: Item, quantity: int = 1):
|
||||||
return inventory.remove_item(item, quantity)
|
return inventory.remove_item(item, quantity)
|
||||||
|
|
||||||
func iter() -> Inventory.InventoryIterator:
|
func iter() -> Iterator:
|
||||||
return inventory.iter()
|
return inventory.iter()
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
class_name ItemDetailsUI extends HBoxContainer
|
class_name ItemDetailsUI extends HBoxContainer
|
||||||
|
|
||||||
|
@export var equipment: Equipment
|
||||||
@export var icon_image: TextureRect
|
@export var icon_image: TextureRect
|
||||||
@export var description_label: Label
|
@export var description_label: Label
|
||||||
|
|
||||||
|
@ -14,10 +15,10 @@ func _set_default():
|
||||||
icon_image.texture = _default_icon
|
icon_image.texture = _default_icon
|
||||||
description_label.text = _default_description
|
description_label.text = _default_description
|
||||||
|
|
||||||
func _on_updated(_item: Option):
|
func _on_updated(item: Option):
|
||||||
if _item.is_some():
|
if item.is_some():
|
||||||
var item: Item = _item.unwrap()
|
var _item: Item = item.unwrap()
|
||||||
icon_image.texture = item.icon
|
icon_image.texture = _item.icon
|
||||||
description_label.text = item.description
|
description_label.text = _item.description
|
||||||
else:
|
else:
|
||||||
_set_default()
|
_set_default()
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
uid://dfvvqpgu8r5v6
|
uid://c8m7eq6a3tpgu
|
||||||
|
|
Loading…
Add table
Reference in a new issue