diff --git a/scripts/scenes/battle_scene.gd b/scripts/scenes/battle_scene.gd index 3f22c30..82ece3e 100644 --- a/scripts/scenes/battle_scene.gd +++ b/scripts/scenes/battle_scene.gd @@ -607,6 +607,8 @@ var battle_unit_list_enemy_button: Button var battle_unit_list_status_label: Label var battle_unit_list_rows: VBoxContainer var battle_unit_list_mode := "ally" +var top_audio_chip: PanelContainer +var top_audio_icon: TextureRect var top_save_button: Button var top_load_button: Button var top_settings_button: Button @@ -3206,6 +3208,14 @@ func _create_hud() -> void: _apply_label_style(campaign_status_label, UI_PARCHMENT_TEXT) (campaign_chip_data["row"] as HBoxContainer).add_child(campaign_status_label) + var audio_chip_data := _make_top_hud_chip("TopAudioStatusChip", "status", Vector2(58, 54), "hud_info") + top_audio_chip = audio_chip_data["chip"] as PanelContainer + 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_icon = top_audio_chip.find_child("TopHudChipIcon", true, false) as TextureRect + top_row.add_child(top_audio_chip) + var top_tool_row := HBoxContainer.new() top_tool_row.name = "TopToolBar" top_tool_row.custom_minimum_size = Vector2(410, 50) @@ -5289,6 +5299,7 @@ func _refresh_title_volume_controls() -> void: if settings_audio_status_label != null: settings_audio_status_label.text = audio_status settings_audio_status_label.tooltip_text = audio_tooltip + _update_top_audio_chip() func _format_audio_status_text() -> String: @@ -5305,6 +5316,30 @@ func _format_audio_status_tooltip() -> String: return "현재 재생되는 음악과 기본값 듣기에서 확인할 효과음입니다.\n%s" % _format_audio_status_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 + 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) + + +func _on_top_audio_chip_gui_input(event: InputEvent) -> void: + if not (event is InputEventMouseButton): + return + if event.button_index != MOUSE_BUTTON_LEFT or not event.pressed: + return + _on_settings_pressed() + var viewport := get_viewport() + if viewport != null: + viewport.set_input_as_handled() + + func _current_bgm_display_name() -> String: var key := current_bgm_key if key.is_empty(): @@ -9977,6 +10012,7 @@ func _update_hud() -> void: campaign_status_label.text = _format_campaign_hud_summary_text() campaign_status_label.tooltip_text = campaign_detail _set_top_hud_chip_tooltip(top_campaign_chip, campaign_detail) + _update_top_audio_chip() _update_mission_panel() _update_cell_info() _update_forecast() diff --git a/tools/smoke_visual_assets.gd b/tools/smoke_visual_assets.gd index 2cf3ac9..bdc7a06 100644 --- a/tools/smoke_visual_assets.gd +++ b/tools/smoke_visual_assets.gd @@ -4747,6 +4747,34 @@ func _check_hud_command_grid_layout(failures: Array[String]) -> void: var top_toolbar := scene.end_turn_button.get_parent() as HBoxContainer if top_toolbar == null or top_toolbar.name != "TopToolBar": failures.append("global battle commands should move to the top icon toolbar") + if scene.top_audio_chip == null: + failures.append("top HUD should expose a compact audio status chip") + else: + if scene.top_audio_chip.get_parent() == top_toolbar: + failures.append("audio status should be a quiet HUD chip, not another global command button") + if scene.top_audio_chip.custom_minimum_size.x > 64.0 or scene.top_audio_chip.custom_minimum_size.y < 46.0: + failures.append("audio status chip should stay compact and stable: %s" % str(scene.top_audio_chip.custom_minimum_size)) + var audio_tooltip := _collect_child_tooltips(scene.top_audio_chip) + if not audio_tooltip.contains("소리 상태") or not audio_tooltip.contains("현재 음악:") or not audio_tooltip.contains("효과음"): + 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_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_settings_bgm_toggled(true) + scene._on_settings_sfx_toggled(true) + if scene.top_audio_chip.modulate.a < 0.90: + failures.append("audio status chip should brighten when sound is available: %s" % str(scene.top_audio_chip.modulate)) + var audio_click := InputEventMouseButton.new() + audio_click.button_index = MOUSE_BUTTON_LEFT + audio_click.pressed = true + scene._hide_settings_panel() + scene._on_top_audio_chip_gui_input(audio_click) + if scene.settings_panel == null or not scene.settings_panel.visible: + failures.append("clicking the audio chip should open the in-game settings panel") + scene._hide_settings_panel() for button in [ scene.end_turn_button, scene.threat_button,