Reviewed-on: #1 Co-authored-by: Bryce <bryce@brycecovertoperations.com> Co-committed-by: Bryce <bryce@brycecovertoperations.com>
205 lines
5.9 KiB
GDScript
205 lines
5.9 KiB
GDScript
extends Control
|
|
class_name InventoryOverlay
|
|
|
|
signal close_requested
|
|
signal item_confirmed(item_id: String)
|
|
signal combine_requested(item_a_id: String, item_b_id: String)
|
|
signal inspect_requested(item_id: String)
|
|
|
|
var input_active: bool = false
|
|
var _is_visible: bool = false
|
|
var _selected_slot: InventorySlot = null
|
|
var _drag_start_time: float = 0.0
|
|
var _is_dragging: bool = false
|
|
var _dragged_item: Control = null
|
|
var _hovered_slot: InventorySlot = null
|
|
var _fade_tween: Tween = null
|
|
|
|
const FADE_DURATION: float = 0.2
|
|
const LONG_PRESS_THRESHOLD: float = 0.5
|
|
const SLOTS_PER_ROW: int = 8
|
|
const SLOT_SIZE: Vector2i = Vector2i(64, 64)
|
|
|
|
@onready var background: ColorRect = $Background
|
|
@onready var panel: Control = $InventoryPanel
|
|
@onready var frame: ColorRect = $InventoryPanel/Frame
|
|
@onready var grid: GridContainer = $InventoryPanel/ItemGrid
|
|
@onready var hover_label: Label = $InventoryPanel/HoverLabel
|
|
|
|
func _ready() -> void:
|
|
hide()
|
|
background.mouse_filter = Control.MOUSE_FILTER_STOP
|
|
InventoryManager.inventory_changed.connect(_refresh_grid)
|
|
InventoryManager.combination_attempted.connect(_on_combination_attempted)
|
|
|
|
func show_overlay() -> void:
|
|
print("[OVERLAY] show_overlay called, inventory has %d items" % InventoryManager.inventory.size())
|
|
_refresh_grid()
|
|
if _fade_tween:
|
|
_fade_tween.kill()
|
|
_fade_tween = null
|
|
|
|
_is_visible = true
|
|
show()
|
|
modulate = Color(1, 1, 1, 0)
|
|
input_active = false
|
|
|
|
var tween = create_tween().bind_node(self)
|
|
_fade_tween = tween
|
|
tween.tween_property(self, "modulate", Color(1, 1, 1, 1), FADE_DURATION)
|
|
tween.tween_callback(_on_fade_in_complete)
|
|
|
|
func hide_overlay() -> void:
|
|
print("[OVERLAY] hide_overlay called")
|
|
if _fade_tween:
|
|
_fade_tween.kill()
|
|
_fade_tween = null
|
|
|
|
input_active = false
|
|
_clear_selection()
|
|
|
|
var tween = create_tween().bind_node(self)
|
|
_fade_tween = tween
|
|
tween.tween_property(self, "modulate", Color(1, 1, 1, 0), FADE_DURATION)
|
|
tween.tween_callback(_on_fade_out_complete)
|
|
|
|
func _on_fade_in_complete() -> void:
|
|
input_active = true
|
|
|
|
func _on_fade_out_complete() -> void:
|
|
_is_visible = false
|
|
hide()
|
|
input_active = false
|
|
|
|
func is_active() -> bool:
|
|
return _is_visible and input_active
|
|
|
|
func _refresh_grid() -> void:
|
|
for child in grid.get_children():
|
|
child.queue_free()
|
|
|
|
for item_id in InventoryManager.inventory:
|
|
var def = InventoryManager.get_item_definition(item_id)
|
|
if not def:
|
|
def = ItemDefinition.new()
|
|
def.id = item_id
|
|
def.name = item_id
|
|
|
|
var slot_scene = load("res://inventory/inventory_overlay/InventorySlot.tscn")
|
|
var slot: InventorySlot = slot_scene.instantiate()
|
|
grid.add_child(slot)
|
|
slot.set_item(def)
|
|
slot.clicked.connect(_on_slot_clicked)
|
|
slot.right_clicked.connect(_on_slot_right_clicked)
|
|
slot.hovered.connect(_on_slot_hovered)
|
|
slot.unhovered.connect(_on_slot_unhovered)
|
|
|
|
grid.columns = SLOTS_PER_ROW
|
|
|
|
func _on_slot_clicked(item_id: String) -> void:
|
|
print("[OVERLAY] _on_slot_clicked: '%s', input_active=%s" % [item_id, input_active])
|
|
if not input_active:
|
|
return
|
|
|
|
for child in grid.get_children():
|
|
if child is InventorySlot and child.item_id == item_id:
|
|
if _selected_slot == null:
|
|
InventoryManager.select_item(item_id)
|
|
item_confirmed.emit(item_id)
|
|
hide_overlay()
|
|
elif _selected_slot.item_id == item_id:
|
|
InventoryManager.select_item(item_id)
|
|
item_confirmed.emit(item_id)
|
|
hide_overlay()
|
|
else:
|
|
combine_requested.emit(_selected_slot.item_id, item_id)
|
|
_clear_selection()
|
|
break
|
|
|
|
func _on_slot_right_clicked(item_id: String) -> void:
|
|
if not input_active:
|
|
return
|
|
inspect_requested.emit(item_id)
|
|
hide_overlay()
|
|
|
|
func _on_slot_hovered(item_id: String) -> void:
|
|
if not input_active:
|
|
return
|
|
_hovered_slot = null
|
|
for child in grid.get_children():
|
|
if child is InventorySlot and child.item_id == item_id:
|
|
_hovered_slot = child
|
|
break
|
|
_update_hover_label()
|
|
|
|
func _on_slot_unhovered(item_id: String) -> void:
|
|
if _hovered_slot and _hovered_slot.item_id == item_id:
|
|
_hovered_slot = null
|
|
_update_hover_label()
|
|
|
|
func _create_drag_preview(slot: InventorySlot) -> void:
|
|
var preview = ColorRect.new()
|
|
preview.color = Color(1, 0.6, 0.2, 0.7)
|
|
preview.size = Vector2(48, 48)
|
|
preview.position = slot.global_position - global_position
|
|
panel.add_child(preview)
|
|
_dragged_item = preview
|
|
|
|
func _handle_release_same_item() -> void:
|
|
var elapsed = Time.get_ticks_msec() / 1000.0 - _drag_start_time
|
|
if elapsed <= LONG_PRESS_THRESHOLD:
|
|
item_confirmed.emit(_selected_slot.item_id)
|
|
hide_overlay()
|
|
else:
|
|
_clear_selection()
|
|
|
|
func _clear_selection() -> void:
|
|
_selected_slot = null
|
|
_is_dragging = false
|
|
if _dragged_item:
|
|
_dragged_item.queue_free()
|
|
_dragged_item = null
|
|
_update_hover_label()
|
|
|
|
func _update_hover_label() -> void:
|
|
if _selected_slot and _hovered_slot and _selected_slot.item_id != _hovered_slot.item_id:
|
|
var def_a = InventoryManager.get_item_definition(_selected_slot.item_id)
|
|
var def_b = InventoryManager.get_item_definition(_hovered_slot.item_id)
|
|
var name_a = _selected_slot.item_id
|
|
var name_b = _hovered_slot.item_id
|
|
if def_a:
|
|
name_a = def_a.name
|
|
if def_b:
|
|
name_b = def_b.name
|
|
hover_label.text = "Use %s with %s" % [name_a, name_b]
|
|
elif _hovered_slot:
|
|
var def = InventoryManager.get_item_definition(_hovered_slot.item_id)
|
|
if def:
|
|
hover_label.text = def.name
|
|
else:
|
|
hover_label.text = _hovered_slot.item_id
|
|
else:
|
|
hover_label.text = ""
|
|
|
|
func _on_background_gui_input(event: InputEvent) -> void:
|
|
if event is InputEventMouseButton and event.button_index == 1 and event.pressed:
|
|
hide_overlay()
|
|
close_requested.emit()
|
|
|
|
func _gui_input(event: InputEvent) -> void:
|
|
if event is InputEventMouseButton and event.button_index == 1 and event.pressed:
|
|
var panel_rect = panel.get_global_rect()
|
|
if not panel_rect.has_point(get_global_mouse_position()):
|
|
hide_overlay()
|
|
close_requested.emit()
|
|
|
|
|
|
func _on_combination_attempted(item_a_id: String, item_b_id: String) -> void:
|
|
pass
|
|
|
|
func _notification(what: int) -> void:
|
|
if what == NOTIFICATION_PREDELETE:
|
|
if _fade_tween:
|
|
_fade_tween.kill()
|
|
_fade_tween = null
|