2025-01-03 08:07:35 +00:00
|
|
|
@tool
|
2025-01-07 10:54:50 +00:00
|
|
|
class_name PropHud extends Control
|
2024-12-26 13:58:37 +00:00
|
|
|
|
2025-01-03 08:07:35 +00:00
|
|
|
@export_group("DebugItem")
|
2025-01-12 06:02:00 +00:00
|
|
|
@export var enable_item := false:
|
2025-01-03 08:07:35 +00:00
|
|
|
set(value):
|
|
|
|
if value:
|
2025-01-12 06:02:00 +00:00
|
|
|
enable_item = false
|
|
|
|
enable_prop_item(item_key)
|
2025-01-10 07:43:55 +00:00
|
|
|
@export var item_key: String
|
2025-01-03 08:07:35 +00:00
|
|
|
@export_group("Inventory")
|
|
|
|
@export var inventory: PropInventory
|
2025-01-03 13:29:22 +00:00
|
|
|
@export_group("UI-UX")
|
2025-01-10 07:43:55 +00:00
|
|
|
@export var display_time := 1.5 # 不包含渐入渐出(约 0.6s)的时长
|
2025-01-03 08:07:35 +00:00
|
|
|
@export var locked := false
|
|
|
|
@export var selected := false:
|
|
|
|
set(value):
|
|
|
|
selected = value
|
|
|
|
if value:
|
|
|
|
%Mark.visible = true
|
|
|
|
else:
|
|
|
|
%Mark.visible = false
|
2024-12-26 13:58:37 +00:00
|
|
|
|
2025-01-03 08:07:35 +00:00
|
|
|
@onready var sfx = %Sfx as Sfx
|
|
|
|
@onready var left_btn = %LeftButton as TextureButton
|
|
|
|
@onready var right_btn = %RightButton as TextureButton
|
|
|
|
@onready var panel = %HudPanel as TextureButton
|
|
|
|
@onready var prop = %Prop as TextureRect
|
|
|
|
@onready var prop_container = %PropContainer as Container
|
2024-12-26 13:58:37 +00:00
|
|
|
@onready var mark = %Mark as TextureRect
|
2025-01-03 08:07:35 +00:00
|
|
|
@onready var title_label = %TitleLabel as Label
|
2024-12-26 13:58:37 +00:00
|
|
|
|
2025-01-12 06:02:00 +00:00
|
|
|
var items_dict := {}
|
|
|
|
var item_config_res = preload("res://asset/dialogue/item_description.dialogue")
|
|
|
|
var item_config_title = "PropItems"
|
|
|
|
var texture_path_prefix = "res://asset/art/prop/"
|
2025-01-03 08:07:35 +00:00
|
|
|
var cached_inventory_textures := {}
|
2024-12-26 13:58:37 +00:00
|
|
|
|
2025-01-03 08:07:35 +00:00
|
|
|
var listen_mouse = false
|
|
|
|
var displaying = false
|
|
|
|
var timer := Timer.new()
|
|
|
|
var display_tween: Tween
|
|
|
|
var container_tween: Tween
|
2024-12-26 13:58:37 +00:00
|
|
|
|
|
|
|
|
2025-01-03 08:07:35 +00:00
|
|
|
func _ready() -> void:
|
2025-01-12 06:02:00 +00:00
|
|
|
_load_items()
|
2025-01-03 08:07:35 +00:00
|
|
|
_load_from_archive()
|
|
|
|
if Engine.is_editor_hint():
|
|
|
|
return
|
|
|
|
ArchiveManager.archive_loaded.connect(_load_from_archive)
|
|
|
|
# tween timer
|
|
|
|
timer.wait_time = display_time
|
|
|
|
timer.one_shot = true
|
|
|
|
timer.autostart = false
|
|
|
|
timer.timeout.connect(toggle_details.bind(false))
|
|
|
|
add_child(timer)
|
|
|
|
# connect signals
|
|
|
|
left_btn.pressed.connect(on_left_pressed)
|
|
|
|
right_btn.pressed.connect(on_right_pressed)
|
|
|
|
panel.pressed.connect(_on_panel_pressed)
|
|
|
|
mark.modulate.a = 0.0
|
|
|
|
title_label.modulate.a = 0.0
|
|
|
|
# _toggle_btn_ability(false)
|
|
|
|
left_btn.modulate.a = 0.5
|
|
|
|
right_btn.modulate.a = 0.5
|
2025-01-07 10:54:50 +00:00
|
|
|
mouse_entered.connect(_on_mouse_entered)
|
|
|
|
mouse_exited.connect(_on_mouse_exited)
|
2025-01-03 08:07:35 +00:00
|
|
|
selected = selected
|
2024-12-26 13:58:37 +00:00
|
|
|
|
2025-01-03 08:07:35 +00:00
|
|
|
|
2025-01-12 06:02:00 +00:00
|
|
|
func _load_items():
|
|
|
|
var current_line = await item_config_res.get_next_dialogue_line(item_config_title)
|
|
|
|
while current_line:
|
|
|
|
var texture_path = current_line.get_tag_value("texture")
|
|
|
|
if texture_path:
|
|
|
|
var item = PropItem.new()
|
|
|
|
item.key = current_line.translation_key
|
|
|
|
item.texture_path = texture_path_prefix + texture_path
|
|
|
|
items_dict[item.key] = item
|
|
|
|
if current_line.next_id == "end":
|
|
|
|
break
|
|
|
|
current_line = await item_config_res.get_next_dialogue_line(current_line.next_id)
|
|
|
|
|
|
|
|
|
2025-01-03 08:07:35 +00:00
|
|
|
func _load_from_archive() -> void:
|
|
|
|
if ArchiveManager.archive:
|
|
|
|
inventory = ArchiveManager.archive.prop_inventory
|
|
|
|
_load_texture_cache()
|
|
|
|
_update_prop_display_with_texture()
|
|
|
|
|
|
|
|
|
|
|
|
func _load_texture_cache() -> void:
|
|
|
|
if not inventory:
|
|
|
|
return
|
|
|
|
cached_inventory_textures.clear()
|
2025-01-12 06:02:00 +00:00
|
|
|
for key in inventory.enabled_items:
|
|
|
|
# 以 items_dict 为准,如果 enabled_items 中的 key 不存在,则删除
|
|
|
|
if not key in items_dict:
|
|
|
|
inventory.enabled_items.erase(key)
|
|
|
|
continue
|
|
|
|
var texture = load(items_dict[key].texture_path) as Texture2D
|
|
|
|
if texture:
|
|
|
|
cached_inventory_textures[key] = texture
|
|
|
|
# wrap index
|
|
|
|
inventory.current_index = wrapi(inventory.current_index, 0, inventory.enabled_items.size())
|
2025-01-03 08:07:35 +00:00
|
|
|
|
|
|
|
|
|
|
|
func _update_prop_display_with_texture():
|
|
|
|
if not inventory:
|
|
|
|
return
|
2025-01-12 06:02:00 +00:00
|
|
|
if inventory.enabled_items.size() == 0:
|
2025-01-03 08:07:35 +00:00
|
|
|
prop.texture = null
|
|
|
|
return
|
2025-01-12 06:02:00 +00:00
|
|
|
var item = items_dict[inventory.current_item_key()]
|
2025-01-03 08:07:35 +00:00
|
|
|
if not item:
|
|
|
|
prop.texture = null
|
|
|
|
push_error("PropItem is null! index=" + str(inventory.current_index))
|
|
|
|
return
|
2025-01-10 07:43:55 +00:00
|
|
|
if item.key in cached_inventory_textures:
|
|
|
|
prop.texture = cached_inventory_textures[item.key]
|
2025-01-03 08:07:35 +00:00
|
|
|
else:
|
|
|
|
prop.texture = null
|
2025-01-10 07:43:55 +00:00
|
|
|
title_label.text = tr(item.key)
|
2025-01-03 08:07:35 +00:00
|
|
|
|
|
|
|
|
|
|
|
func on_left_pressed() -> void:
|
|
|
|
sfx.play()
|
|
|
|
_mouse_moved_on_listening()
|
|
|
|
inventory.index_wrap_add(-1)
|
|
|
|
_update_prop_display_with_texture()
|
|
|
|
_tween_container(true)
|
|
|
|
|
|
|
|
|
|
|
|
func on_right_pressed() -> void:
|
|
|
|
sfx.play()
|
|
|
|
_mouse_moved_on_listening()
|
|
|
|
inventory.index_wrap_add(1)
|
|
|
|
_update_prop_display_with_texture()
|
|
|
|
_tween_container(false)
|
|
|
|
|
|
|
|
|
|
|
|
func _tween_container(left_to_right := true) -> void:
|
|
|
|
if container_tween and container_tween.is_running():
|
|
|
|
container_tween.kill()
|
|
|
|
container_tween = create_tween()
|
|
|
|
if left_to_right:
|
|
|
|
container_tween.tween_property(prop_container, "offset_left", 0.0, 0.3).from(-200.0)
|
|
|
|
prop_container.offset_right = 0.0
|
|
|
|
else:
|
|
|
|
container_tween.tween_property(prop_container, "offset_right", 0.0, 0.3).from(200.0)
|
|
|
|
prop_container.offset_left = 0.0
|
|
|
|
|
|
|
|
|
|
|
|
func _on_panel_pressed() -> void:
|
|
|
|
sfx.play()
|
|
|
|
_mouse_moved_on_listening()
|
|
|
|
print("panel")
|
|
|
|
|
|
|
|
|
|
|
|
func _on_mouse_entered() -> void:
|
|
|
|
listen_mouse = true
|
|
|
|
_mouse_moved_on_listening()
|
|
|
|
|
|
|
|
|
|
|
|
func _on_mouse_exited() -> void:
|
|
|
|
listen_mouse = false
|
|
|
|
|
|
|
|
|
|
|
|
func _mouse_moved_on_listening() -> void:
|
|
|
|
if not displaying:
|
|
|
|
toggle_details(true)
|
|
|
|
return
|
|
|
|
timer.start(display_time)
|
|
|
|
|
|
|
|
|
|
|
|
func _unhandled_input(event: InputEvent) -> void:
|
|
|
|
if locked:
|
|
|
|
return
|
|
|
|
if event.is_action_pressed("prop_left"):
|
|
|
|
on_left_pressed()
|
|
|
|
get_viewport().set_input_as_handled()
|
|
|
|
elif event.is_action_pressed("prop_right"):
|
|
|
|
on_right_pressed()
|
|
|
|
get_viewport().set_input_as_handled()
|
2025-01-03 13:29:22 +00:00
|
|
|
|
2025-01-10 07:43:55 +00:00
|
|
|
|
2025-01-03 13:29:22 +00:00
|
|
|
func _input(event: InputEvent) -> void:
|
|
|
|
if locked:
|
|
|
|
return
|
2025-01-03 08:07:35 +00:00
|
|
|
if listen_mouse and (event is InputEventMouseMotion or event is InputEventScreenTouch):
|
|
|
|
_mouse_moved_on_listening()
|
|
|
|
|
|
|
|
|
|
|
|
func toggle_details(display := true) -> void:
|
|
|
|
if display_tween and display_tween.is_running():
|
|
|
|
display_tween.kill()
|
|
|
|
display_tween = create_tween()
|
|
|
|
if display:
|
|
|
|
displaying = true
|
|
|
|
_toggle_btn_ability(true)
|
|
|
|
display_tween.tween_property(mark, "modulate:a", 0.5, 0.2)
|
|
|
|
display_tween.parallel().tween_property(title_label, "modulate:a", 1.0, 0.2)
|
|
|
|
display_tween.parallel().tween_property(left_btn, "modulate:a", 1.0, 0.5)
|
|
|
|
display_tween.parallel().tween_property(right_btn, "modulate:a", 1.0, 0.5)
|
|
|
|
display_tween.tween_property(mark, "modulate:a", 1.0, 0.2)
|
|
|
|
display_tween.parallel().tween_property(mark, "scale", Vector2(1.1, 1.1), 0.3).set_trans(
|
2024-12-26 13:58:37 +00:00
|
|
|
Tween.TRANS_CUBIC
|
|
|
|
)
|
2025-01-03 08:07:35 +00:00
|
|
|
display_tween.tween_property(mark, "scale", Vector2.ONE, 0.3).set_trans(Tween.TRANS_CUBIC)
|
|
|
|
timer.start(display_time)
|
2024-12-26 13:58:37 +00:00
|
|
|
else:
|
2025-01-03 08:07:35 +00:00
|
|
|
displaying = false
|
|
|
|
display_tween.tween_property(mark, "modulate:a", 0.0, 0.6)
|
|
|
|
display_tween.parallel().tween_property(title_label, "modulate:a", 0.0, 0.6)
|
|
|
|
display_tween.parallel().tween_property(left_btn, "modulate:a", 0.5, 0.5)
|
|
|
|
display_tween.parallel().tween_property(right_btn, "modulate:a", 0.5, 0.5)
|
|
|
|
# display_tween.tween_callback(_toggle_btn_ability.bind(false))
|
|
|
|
timer.stop()
|
|
|
|
|
|
|
|
|
|
|
|
func _toggle_btn_ability(v: bool) -> void:
|
|
|
|
left_btn.disabled = !v
|
|
|
|
right_btn.disabled = !v
|
|
|
|
|
|
|
|
|
2025-01-12 06:02:00 +00:00
|
|
|
func enable_prop_item(prop_key: String) -> void:
|
|
|
|
if not inventory or not prop_key:
|
|
|
|
return
|
|
|
|
if not items_dict.has(prop_key):
|
|
|
|
push_error("PropItem not found! key=" + prop_key)
|
2025-01-03 08:07:35 +00:00
|
|
|
return
|
2025-01-12 06:02:00 +00:00
|
|
|
inventory.enable_item(prop_key)
|
2025-01-03 08:07:35 +00:00
|
|
|
_load_texture_cache()
|
|
|
|
_update_prop_display_with_texture()
|