@tool class_name PropHud extends Control @export_group("DebugItem") @export var add_item := false: set(value): if value: add_item = false add_prop_item(item_name, item_title, item_texture) @export var item_name: String @export var item_title: String @export_file("*.png") var item_texture: String @export_group("Inventory") @export var inventory: PropInventory @export_group("UI-UX") @export var display_time := 1.5 # 不包含渐入渐出(约 0.6s)的时长 @export var locked := false @export var selected := false: set(value): selected = value if value: %Mark.visible = true else: %Mark.visible = false @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 @onready var mark = %Mark as TextureRect @onready var title_label = %TitleLabel as Label var cached_inventory_textures := {} var listen_mouse = false var displaying = false var timer := Timer.new() var display_tween: Tween var container_tween: Tween func _ready() -> void: _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 mouse_entered.connect(_on_mouse_entered) mouse_exited.connect(_on_mouse_exited) selected = selected func _load_from_archive() -> void: if ArchiveManager.archive: inventory = ArchiveManager.archive.prop_inventory if not inventory: return inventory.current_index = wrapi(inventory.current_index, 0, inventory.items.size()) _load_texture_cache() _update_prop_display_with_texture() func _load_texture_cache() -> void: if not inventory: return cached_inventory_textures.clear() for i in inventory.items: if i and i.name and i.texture_path: cached_inventory_textures[i.name] = load(i.texture_path) func _update_prop_display_with_texture(): if not inventory: return if inventory.items.size() == 0: prop.texture = null return var item = inventory.items[inventory.current_index] as PropItem if not item: prop.texture = null push_error("PropItem is null! index=" + str(inventory.current_index)) return if item.name in cached_inventory_textures: prop.texture = cached_inventory_textures[item.name] else: prop.texture = null title_label.text = item.title 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() func _input(event: InputEvent) -> void: if locked: return 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( Tween.TRANS_CUBIC ) display_tween.tween_property(mark, "scale", Vector2.ONE, 0.3).set_trans(Tween.TRANS_CUBIC) timer.start(display_time) else: 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 func add_prop_item(prop_name: String, prop_title: String, texture_path: String) -> void: if not inventory or not prop_name or not texture_path: return inventory.add_item(prop_name, prop_title, texture_path) _load_texture_cache() _update_prop_display_with_texture()