109 lines
2.3 KiB
GDScript
109 lines
2.3 KiB
GDScript
class_name ComboWindow
|
|
extends Node
|
|
|
|
signal combo_updated(inputs: Array[StringName])
|
|
signal combo_cleared(reason: StringName)
|
|
|
|
@export var size := 4
|
|
@export var clear_display_time := 0.35
|
|
|
|
var slots: Array[StringName] = []
|
|
var pending_clear_reason: StringName = &""
|
|
var _timer: Timer
|
|
|
|
|
|
func _ready() -> void:
|
|
_timer = Timer.new()
|
|
_timer.one_shot = true
|
|
_timer.timeout.connect(flush_pending_clear)
|
|
add_child(_timer)
|
|
|
|
|
|
func record(input: StringName) -> void:
|
|
if input.is_empty():
|
|
return
|
|
slots.append(input)
|
|
combo_updated.emit(get_slots())
|
|
_emit_bus_signal("combo_updated", [get_slots()])
|
|
if slots.size() >= size:
|
|
queue_clear(&"full")
|
|
|
|
|
|
func get_slots() -> Array[StringName]:
|
|
return slots.duplicate()
|
|
|
|
|
|
func has_pending_clear() -> bool:
|
|
return not pending_clear_reason.is_empty()
|
|
|
|
|
|
func consume_pending_clear_reason() -> StringName:
|
|
var reason := pending_clear_reason
|
|
pending_clear_reason = &""
|
|
return reason
|
|
|
|
|
|
func get_pattern() -> String:
|
|
var pattern := ""
|
|
for slot: StringName in slots:
|
|
if slot != &"Ø":
|
|
pattern += str(slot)
|
|
return pattern
|
|
|
|
|
|
func get_contiguous_pattern() -> String:
|
|
var pattern := ""
|
|
for index: int in range(slots.size() - 1, -1, -1):
|
|
var slot := slots[index]
|
|
if slot == &"Ø":
|
|
break
|
|
pattern = str(slot) + pattern
|
|
return pattern
|
|
|
|
|
|
func queue_clear(reason: StringName, delay := -1.0) -> void:
|
|
pending_clear_reason = reason
|
|
if _timer == null:
|
|
return
|
|
_timer.stop()
|
|
_timer.wait_time = clear_display_time if delay < 0.0 else delay
|
|
_timer.start()
|
|
|
|
|
|
func cancel_pending_clear() -> void:
|
|
pending_clear_reason = &""
|
|
if _timer != null:
|
|
_timer.stop()
|
|
|
|
|
|
func flush_pending_clear() -> void:
|
|
var reason := consume_pending_clear_reason()
|
|
if reason.is_empty():
|
|
return
|
|
if _timer != null:
|
|
_timer.stop()
|
|
clear(reason)
|
|
|
|
|
|
func clear(reason: StringName = &"") -> void:
|
|
slots.clear()
|
|
pending_clear_reason = &""
|
|
combo_cleared.emit(reason)
|
|
_emit_bus_signal("combo_cleared", [reason])
|
|
combo_updated.emit(get_slots())
|
|
_emit_bus_signal("combo_updated", [get_slots()])
|
|
|
|
|
|
func _emit_bus_signal(signal_name: StringName, args: Array) -> void:
|
|
if not is_inside_tree():
|
|
return
|
|
var bus := _event_bus_or_null()
|
|
if bus != null:
|
|
bus.emit_signal(signal_name, args[0])
|
|
|
|
|
|
func _event_bus_or_null() -> Node:
|
|
if not is_inside_tree():
|
|
return null
|
|
return get_tree().root.get_node_or_null("EventBus")
|