From a07f78e1d07966c9a6d1042d2371f8e1d38426a2 Mon Sep 17 00:00:00 2001 From: cakipaul Date: Sun, 27 Jul 2025 23:19:28 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BD=BF=E7=94=A8=20InspectorBalloon=20?= =?UTF-8?q?=E5=B1=95=E7=A4=BA=20prop=20=E4=BF=A1=E6=81=AF=EF=BC=8C?= =?UTF-8?q?=E9=81=BF=E5=85=8D=20dialog=20=E5=86=B2=E7=AA=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scene/ux/bag/prop_bag.gd | 4 ++ scene/ux/inspector_balloon.gd | 89 +++++++++++++++++++++++++++++++ scene/ux/inspector_balloon.gd.uid | 1 + scene/ux/inspector_balloon.tscn | 76 ++++++++++++++++++++++++++ scene/ux/prop_inspector.gd | 32 ++++------- scene/ux/prop_inspector.tscn | 6 ++- 6 files changed, 186 insertions(+), 22 deletions(-) create mode 100644 scene/ux/inspector_balloon.gd create mode 100644 scene/ux/inspector_balloon.gd.uid create mode 100644 scene/ux/inspector_balloon.tscn diff --git a/scene/ux/bag/prop_bag.gd b/scene/ux/bag/prop_bag.gd index 44eef4d3..e7c2821c 100644 --- a/scene/ux/bag/prop_bag.gd +++ b/scene/ux/bag/prop_bag.gd @@ -34,6 +34,10 @@ func _load_item_buttons() -> void: # prop keys var inventory = hud.inventory for prop_key in inventory.important_items: + if not hud.items_dict.has(prop_key): + printerr("Important item not found in items_dict: ", prop_key) + continue + hud.items_description_dict.has(prop_key) var button = preload("uid://wxd25ec3cqyy").instantiate() button.text = tr(prop_key) button.pressed.connect(_display_item.bind(prop_key, button)) diff --git a/scene/ux/inspector_balloon.gd b/scene/ux/inspector_balloon.gd new file mode 100644 index 00000000..434d1678 --- /dev/null +++ b/scene/ux/inspector_balloon.gd @@ -0,0 +1,89 @@ +class_name InspectorBalloon +extends MarginContainer + +signal quitted(is_manually: bool) + +@export var prop_title_to_content_wait_time := 3.0 +@export var auto_quit_time := 5.0 + +@onready var character_label = %CharacterLabel as RichTextLabel +@onready var content_label = %ContentLabel as RichTextLabel + +enum { DISPLAYING_NONE, DISPLAYING_TITLE, DISPLAYING_CONTENT } + +var _display_mutex := Mutex.new() +var _displaying_status := DISPLAYING_NONE +var _pending_content := "" +var _balloon_tween: Tween + + +func _ready() -> void: + character_label.text = "" + content_label.text = "" + + +func show_prop_balloon(obtain_str: String, prop_title: String, content: String) -> void: + _display_mutex.lock() + if _balloon_tween and _balloon_tween.is_running(): + _balloon_tween.kill() + _balloon_tween = create_tween() + show() + _pending_content = content + # 如果有获得的物品名称,则显示标题,否则直接显示内容 + if not obtain_str.is_empty(): + obtain_str = "[color=orange]" + obtain_str + "[/color]" + _displaying_status = DISPLAYING_TITLE + else: + _display_content() + _display_mutex.unlock() + return + character_label.show() + character_label.text = obtain_str + content_label.text = prop_title + if not _pending_content.is_empty(): + _balloon_tween.tween_interval(prop_title_to_content_wait_time) + _balloon_tween.tween_callback(_display_content) + else: + _balloon_tween.tween_interval(auto_quit_time) + _balloon_tween.tween_callback(_finished.bind(false)) + _display_mutex.unlock() + + +func _display_content() -> void: + _display_mutex.lock() + if _balloon_tween and _balloon_tween.is_running(): + _balloon_tween.kill() + _balloon_tween = create_tween() + _displaying_status = DISPLAYING_CONTENT + character_label.hide() + content_label.text = _pending_content + _pending_content = "" + _balloon_tween.tween_interval(auto_quit_time) + _balloon_tween.tween_callback(_finished.bind(false)) + _display_mutex.unlock() + + +func _finished(manually: bool) -> void: + _display_mutex.lock() + character_label.text = "" + content_label.text = "" + _displaying_status = DISPLAYING_NONE + hide() + quitted.emit(manually) + _display_mutex.unlock() + + +func _input(event: InputEvent) -> void: + _display_mutex.lock() + if _displaying_status == DISPLAYING_NONE: + _display_mutex.unlock() + return + if event.is_action_pressed("interact") or event.is_action_pressed("cancel"): + get_viewport().set_input_as_handled() + if _balloon_tween and _balloon_tween.is_running(): + _balloon_tween.kill() + if not _pending_content.is_empty() and _displaying_status == DISPLAYING_TITLE: + _display_content() + else: + _finished(true) + _display_mutex.unlock() diff --git a/scene/ux/inspector_balloon.gd.uid b/scene/ux/inspector_balloon.gd.uid new file mode 100644 index 00000000..689077e1 --- /dev/null +++ b/scene/ux/inspector_balloon.gd.uid @@ -0,0 +1 @@ +uid://dhjjskfl8r5nk diff --git a/scene/ux/inspector_balloon.tscn b/scene/ux/inspector_balloon.tscn new file mode 100644 index 00000000..0fa74eb8 --- /dev/null +++ b/scene/ux/inspector_balloon.tscn @@ -0,0 +1,76 @@ +[gd_scene load_steps=4 format=3 uid="uid://dufshurokh0ws"] + +[ext_resource type="Theme" uid="uid://dlrwa60futc45" path="res://config/balloon_theme.tres" id="1_wqjpu"] +[ext_resource type="Script" uid="uid://dhjjskfl8r5nk" path="res://scene/ux/inspector_balloon.gd" id="2_d4kw8"] +[ext_resource type="PackedScene" uid="uid://ckvgyvclnwggo" path="res://addons/dialogue_manager/dialogue_label.tscn" id="2_kla48"] + +[node name="InspectorBalloon" type="MarginContainer"] +anchors_preset = 7 +anchor_left = 0.5 +anchor_top = 1.0 +anchor_right = 0.5 +anchor_bottom = 1.0 +offset_left = -35.5 +offset_top = -69.0 +offset_right = 35.5 +grow_horizontal = 2 +grow_vertical = 0 +focus_mode = 2 +mouse_filter = 2 +theme = ExtResource("1_wqjpu") +theme_override_constants/margin_bottom = 38 +script = ExtResource("2_d4kw8") + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +layout_mode = 2 +size_flags_horizontal = 4 +size_flags_vertical = 4 +mouse_filter = 2 + +[node name="Panel" type="MarginContainer" parent="VBoxContainer"] +clip_children = 2 +layout_mode = 2 +size_flags_horizontal = 4 +size_flags_vertical = 8 +mouse_filter = 2 +theme_override_constants/margin_left = 0 +theme_override_constants/margin_top = 0 +theme_override_constants/margin_right = 0 +theme_override_constants/margin_bottom = 5 + +[node name="Container" type="HBoxContainer" parent="VBoxContainer/Panel"] +layout_direction = 1 +layout_mode = 2 +mouse_filter = 2 +alignment = 1 + +[node name="CharacterLabel" type="RichTextLabel" parent="VBoxContainer/Panel/Container"] +unique_name_in_owner = true +clip_contents = false +layout_mode = 2 +size_flags_horizontal = 4 +size_flags_vertical = 0 +mouse_filter = 2 +theme_override_colors/font_shadow_color = Color(0.305882, 0.305882, 0.305882, 0.388235) +theme_override_constants/shadow_offset_y = 1 +theme_override_constants/shadow_offset_x = 1 +bbcode_enabled = true +text = "c" +fit_content = true +scroll_active = false +autowrap_mode = 0 + +[node name="ContentLabel" parent="VBoxContainer/Panel/Container" instance=ExtResource("2_kla48")] +unique_name_in_owner = true +clip_contents = false +layout_mode = 2 +size_flags_horizontal = 4 +size_flags_vertical = 0 +mouse_filter = 2 +theme_override_colors/font_shadow_color = Color(0.306923, 0.306923, 0.306923, 0.388235) +theme_override_constants/shadow_offset_y = 1 +theme_override_constants/shadow_offset_x = 1 +text = "l" +autowrap_mode = 0 +seconds_per_step = 0.005 +seconds_per_pause_step = 0.1 diff --git a/scene/ux/prop_inspector.gd b/scene/ux/prop_inspector.gd index 478a5717..77446c15 100644 --- a/scene/ux/prop_inspector.gd +++ b/scene/ux/prop_inspector.gd @@ -19,6 +19,8 @@ signal quit_and_hidden @onready var scroll_container = %ScrollContainer as ScrollContainer @onready var content_label = %ContentLabel as Label @onready var tip_label = %TipLabel as Label +@onready var inspector_balloon = %InspectorBalloon as InspectorBalloon + var tip_cover = "Q: " + tr("ui_退出") + " " + "E: " + tr("ui_阅读") var tip_notes = "Q: " + tr("ui_退出") + " " + "E: " + tr("ui_收起") @@ -41,6 +43,11 @@ func _ready() -> void: full_texture.modulate.a = 0.0 content_label.modulate.a = 0.0 tip_label.modulate.a = 0.0 + inspector_balloon.quitted.connect(_on_inspector_balloon_quitted) + + +func _on_inspector_balloon_quitted(_is_manually: bool): + _hide() func _hide(): @@ -127,8 +134,6 @@ var locking = false: SceneManager.unlock_player() _lock_mutex.unlock() -var balloon - func pop_prop_inspection( prop_key: String, @@ -163,31 +168,16 @@ func pop_prop_inspection( # 显示道具获得提示 if prop_key: var prop_title = tr(prop_key) - var text = "~ title\n" + var obtain_str = "" if display_obtained: - var obtain_str = tr("ui_获得道具") + obtain_str = tr("ui_获得道具") if as_important_item: obtain_str = tr("ui_获得重要物品") - text += obtain_str + ": " + prop_title + "[#item]\n" # 道具的一句话说明 var original_word_lines = tr(prop_key + "_说明").replace("{br}", "\n").split("\n") # 缩略只要第一行 - text += original_word_lines[0] + ("..." if len(original_word_lines) > 1 else "") - text += "\n=> END" - var current_prop_res = DialogueManager.create_resource_from_text(text) - # 手动跳过的同时显示下一句 - if is_instance_valid(balloon): - balloon.queue_free() - else: - DialogueManager.dialogue_ended.connect( - _on_inspecting_prop_words_ended, CONNECT_ONE_SHOT - ) - balloon = preload("res://scene/dialog/balloon.tscn").instantiate() - DialogueManager.show_dialogue_balloon_scene(balloon, current_prop_res, "title") - - -func _on_inspecting_prop_words_ended(_res): - _hide() + var content = original_word_lines[0] + ("..." if len(original_word_lines) > 1 else "") + inspector_balloon.show_prop_balloon(obtain_str, prop_title, content) func _show_prop_words(line_id: String): diff --git a/scene/ux/prop_inspector.tscn b/scene/ux/prop_inspector.tscn index d10fb871..a6ba5c9b 100644 --- a/scene/ux/prop_inspector.tscn +++ b/scene/ux/prop_inspector.tscn @@ -1,9 +1,10 @@ -[gd_scene load_steps=5 format=3 uid="uid://cekhj65axie0p"] +[gd_scene load_steps=6 format=3 uid="uid://cekhj65axie0p"] [ext_resource type="Script" uid="uid://1xdb7s1nigv8" path="res://scene/ux/prop_inspector.gd" id="1_2wpwe"] [ext_resource type="Texture2D" uid="uid://f186lvt5y2ql" path="res://asset/art/ui/遮罩/inspect背景遮罩.png" id="2_j83lq"] [ext_resource type="Texture2D" uid="uid://cvgw2mxrlr6io" path="res://asset/art/scene/c02/旧版/s02_走道/ux_进门鼠疫海报yz.png" id="2_wr575"] [ext_resource type="FontVariation" uid="uid://1ryw42kej6lv" path="res://config/font_ui.tres" id="4_opug5"] +[ext_resource type="PackedScene" uid="uid://dufshurokh0ws" path="res://scene/ux/inspector_balloon.tscn" id="5_p8nxc"] [node name="PropInspector" type="CanvasLayer"] process_mode = 3 @@ -133,3 +134,6 @@ theme_override_fonts/font = ExtResource("4_opug5") text = "Q: Exit E: Read" horizontal_alignment = 1 vertical_alignment = 1 + +[node name="InspectorBalloon" parent="." instance=ExtResource("5_p8nxc")] +unique_name_in_owner = true