diff --git a/scripts/scenes/battle_scene.gd b/scripts/scenes/battle_scene.gd index 4347e1d..cf39170 100644 --- a/scripts/scenes/battle_scene.gd +++ b/scripts/scenes/battle_scene.gd @@ -612,7 +612,7 @@ var command_hint_panel: PanelContainer var command_hint_icon: TextureRect var command_hint_title_label: Label var command_hint_detail_label: Label -var command_hint_source_button: Button +var command_hint_source_control: Control var threat_button: Button var battle_unit_list_button: Button var battle_unit_list_panel: PanelContainer @@ -1923,31 +1923,42 @@ func _show_command_hint_for_button(button: Button) -> void: return var label := _command_hint_button_label(button) var detail := _command_hint_button_detail(button) - if label.is_empty() and detail.is_empty(): - _hide_command_hint() - return var tooltip := str(button.tooltip_text).strip_edges() if tooltip.is_empty(): tooltip = _format_local_command_tooltip(label, detail) - command_hint_source_button = button + _show_command_hint(label, detail, str(button.get_meta("command_icon", "status")), button, tooltip) + + +func _show_command_hint(label: String, detail: String, icon_kind: String, source: Control, tooltip: String = "") -> void: + if command_hint_panel == null or source == null or not is_instance_valid(source): + return + var normalized_label := label.strip_edges() + var normalized_detail := detail.strip_edges() + if normalized_label.is_empty() and normalized_detail.is_empty(): + _hide_command_hint() + return + var resolved_tooltip := tooltip.strip_edges() + if resolved_tooltip.is_empty(): + resolved_tooltip = _format_local_command_tooltip(normalized_label, normalized_detail) + command_hint_source_control = source command_hint_panel.visible = true - command_hint_panel.tooltip_text = tooltip - command_hint_panel.position = _command_hint_panel_position(button) + command_hint_panel.tooltip_text = resolved_tooltip + command_hint_panel.position = _command_hint_panel_position(source) command_hint_panel.move_to_front() if command_hint_title_label != null: - _set_fitted_label_text(command_hint_title_label, label, LOCAL_COMMAND_TITLE_FONT_SIZE, LOCAL_COMMAND_TITLE_MIN_FONT_SIZE, COMMAND_HINT_TITLE_SIZE) - command_hint_title_label.tooltip_text = tooltip + _set_fitted_label_text(command_hint_title_label, normalized_label, LOCAL_COMMAND_TITLE_FONT_SIZE, LOCAL_COMMAND_TITLE_MIN_FONT_SIZE, COMMAND_HINT_TITLE_SIZE) + command_hint_title_label.tooltip_text = resolved_tooltip if command_hint_detail_label != null: - _set_fitted_label_text(command_hint_detail_label, detail, LOCAL_COMMAND_DETAIL_FONT_SIZE, LOCAL_COMMAND_DETAIL_MIN_FONT_SIZE, COMMAND_HINT_DETAIL_SIZE) - command_hint_detail_label.tooltip_text = tooltip + _set_fitted_label_text(command_hint_detail_label, normalized_detail, LOCAL_COMMAND_DETAIL_FONT_SIZE, LOCAL_COMMAND_DETAIL_MIN_FONT_SIZE, COMMAND_HINT_DETAIL_SIZE) + command_hint_detail_label.tooltip_text = resolved_tooltip if command_hint_icon != null: - command_hint_icon.texture = _make_toolbar_icon(str(button.get_meta("command_icon", "status"))) - command_hint_icon.tooltip_text = tooltip - _set_control_tree_tooltip(command_hint_panel, tooltip) + command_hint_icon.texture = _make_toolbar_icon(icon_kind) + command_hint_icon.tooltip_text = resolved_tooltip + _set_control_tree_tooltip(command_hint_panel, resolved_tooltip) func _hide_command_hint() -> void: - command_hint_source_button = null + command_hint_source_control = null if command_hint_panel != null: command_hint_panel.visible = false @@ -1955,7 +1966,7 @@ func _hide_command_hint() -> void: func _refresh_command_hint_if_source(button: Button) -> void: if command_hint_panel == null or not command_hint_panel.visible: return - if command_hint_source_button == button: + if command_hint_source_control == button: _show_command_hint_for_button(button) @@ -1992,15 +2003,15 @@ func _command_hint_button_detail(button: Button) -> String: return "" -func _command_hint_panel_position(button: Button) -> Vector2: - var button_rect := button.get_global_rect() +func _command_hint_panel_position(source: Control) -> Vector2: + var button_rect := source.get_global_rect() var viewport_size := _viewport_size_for_layout() var panel_size := COMMAND_HINT_PANEL_SIZE var gap := 8.0 var x := button_rect.position.x if button_rect.get_center().x > viewport_size.x * 0.5: x = button_rect.end.x - panel_size.x - var parent := button.get_parent() + var parent := source.get_parent() if parent != null and parent.name == "TopToolBar": x = minf(x, SIDE_PANEL_POSITION.x - panel_size.x - gap) var y := button_rect.end.y + gap @@ -3335,6 +3346,8 @@ func _create_hud() -> void: top_audio_chip.mouse_filter = Control.MOUSE_FILTER_STOP top_audio_chip.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND top_audio_chip.gui_input.connect(_on_top_audio_chip_gui_input) + top_audio_chip.mouse_entered.connect(_on_top_audio_chip_mouse_entered) + top_audio_chip.mouse_exited.connect(_on_top_audio_chip_mouse_exited) top_audio_icon = top_audio_chip.find_child("TopHudChipIcon", true, false) as TextureRect top_row.add_child(top_audio_chip) @@ -5483,17 +5496,48 @@ func _format_audio_status_tooltip() -> String: return "현재 재생되는 음악과 기본값 듣기에서 확인할 효과음입니다.\n%s" % _format_audio_status_text() +func _format_audio_chip_hint_detail() -> String: + var bgm_text := "음악 꺼짐" + if title_bgm_enabled: + bgm_text = "음악 %s %d%%" % [_current_bgm_display_name(), title_bgm_volume_percent] + var sfx_text := "효과음 꺼짐" + if title_sfx_enabled: + sfx_text = "효과음 %d%%" % title_sfx_volume_percent + return "%s\n%s\n클릭하면 환경 설정" % [bgm_text, sfx_text] + + func _update_top_audio_chip() -> void: if top_audio_chip == null: return var can_show := not _is_title_screen_visible() and not _is_opening_prologue_visible() top_audio_chip.visible = can_show + if not can_show: + if command_hint_source_control == top_audio_chip: + _hide_command_hint() + return var tooltip := "소리 상태\n%s\n클릭하면 환경 설정을 엽니다." % _format_audio_status_text() _set_control_tree_tooltip(top_audio_chip, tooltip) var any_audio_enabled := title_bgm_enabled or title_sfx_enabled top_audio_chip.modulate = Color(1.0, 1.0, 1.0, 0.98 if any_audio_enabled else 0.48) if top_audio_icon != null: top_audio_icon.modulate = Color(1.0, 1.0, 1.0, 1.0 if any_audio_enabled else 0.55) + if command_hint_source_control == top_audio_chip and command_hint_panel != null and command_hint_panel.visible: + _show_top_audio_chip_hint() + + +func _show_top_audio_chip_hint() -> void: + if top_audio_chip == null or not top_audio_chip.visible: + return + _show_command_hint("소리 상태", _format_audio_chip_hint_detail(), "status", top_audio_chip, top_audio_chip.tooltip_text) + + +func _on_top_audio_chip_mouse_entered() -> void: + _show_top_audio_chip_hint() + + +func _on_top_audio_chip_mouse_exited() -> void: + if command_hint_source_control == top_audio_chip: + _hide_command_hint() func _on_top_audio_chip_gui_input(event: InputEvent) -> void: diff --git a/tools/smoke_visual_assets.gd b/tools/smoke_visual_assets.gd index 62703d2..ede27fd 100644 --- a/tools/smoke_visual_assets.gd +++ b/tools/smoke_visual_assets.gd @@ -4949,10 +4949,26 @@ func _check_hud_command_grid_layout(failures: Array[String]) -> void: failures.append("audio status chip should expose the current sound mix in a tooltip: %s" % audio_tooltip) if not _has_descendant_texture(scene.top_audio_chip): failures.append("audio status chip should use generated icon artwork") + scene._on_top_audio_chip_mouse_entered() + if scene.command_hint_panel == null or not scene.command_hint_panel.visible: + failures.append("hovering the audio chip should show the readable command hint panel") + else: + if scene.command_hint_title_label == null or scene.command_hint_title_label.text != "소리 상태": + failures.append("audio chip hint should show sound status title: %s" % ("" if scene.command_hint_title_label == null else scene.command_hint_title_label.text)) + if scene.command_hint_detail_label == null or not scene.command_hint_detail_label.text.contains("효과음"): + failures.append("audio chip hint should show compact sound detail: %s" % ("" if scene.command_hint_detail_label == null else scene.command_hint_detail_label.text)) + _check_panel_uses_flat_readable_backing(failures, scene.command_hint_panel, "audio chip hint readable panel") + scene._on_top_audio_chip_mouse_exited() + if scene.command_hint_panel != null and scene.command_hint_panel.visible: + failures.append("audio chip hint panel should hide when leaving the chip") scene._on_settings_bgm_toggled(false) scene._on_settings_sfx_toggled(false) if scene.top_audio_chip.modulate.a > 0.60: failures.append("audio status chip should dim when both music and SFX are off: %s" % str(scene.top_audio_chip.modulate)) + scene._on_top_audio_chip_mouse_entered() + if scene.command_hint_detail_label == null or not scene.command_hint_detail_label.text.contains("꺼짐"): + failures.append("audio chip hint should reflect muted sound state: %s" % ("" if scene.command_hint_detail_label == null else scene.command_hint_detail_label.text)) + scene._on_top_audio_chip_mouse_exited() scene._on_settings_bgm_toggled(true) scene._on_settings_sfx_toggled(true) if scene.top_audio_chip.modulate.a < 0.90: