diff --git a/art/ui/panels/panel_story_scroll.png b/art/ui/panels/panel_story_scroll.png new file mode 100644 index 0000000..9aee254 Binary files /dev/null and b/art/ui/panels/panel_story_scroll.png differ diff --git a/scripts/scenes/battle_scene.gd b/scripts/scenes/battle_scene.gd index a67ab0a..aa506b1 100644 --- a/scripts/scenes/battle_scene.gd +++ b/scripts/scenes/battle_scene.gd @@ -773,6 +773,8 @@ func _panel_texture_spec(variant: String) -> Dictionary: return {"texture": "hud_jade", "slice_margin": 46, "content_margin": 9} "dialogue", "compact", "result_tablet", "cinematic_caption": return {"texture": "lacquer", "slice_margin": 96, "content_margin": 14} + "story_caption": + return {"texture": "story_scroll", "slice_margin": 126, "content_margin": 22} "command_seal", "notice", "result_defeat_tablet": return {"texture": "command_seal", "slice_margin": 72, "content_margin": 12} "result_victory_tablet": @@ -936,6 +938,13 @@ func _apply_panel_style(panel: PanelContainer, variant: String) -> void: radius = 10 margin = 14 shadow_size = 16 + "story_caption": + fill = Color(0.15, 0.13, 0.10, 0.94) + border = UI_TARNISHED_BRONZE + border_width = 3 + radius = 10 + margin = 22 + shadow_size = 18 "result_tablet": fill = Color(0.30, 0.27, 0.22, 0.997) border = UI_LACQUER_EDGE @@ -972,9 +981,13 @@ func _apply_panel_style(panel: PanelContainer, variant: String) -> void: if texture_style != null: panel.add_theme_stylebox_override("panel", texture_style) panel.set_meta("generated_panel_texture", true) + panel.set_meta("panel_style_variant", variant) + panel.set_meta("panel_texture_key", str(_panel_texture_spec(variant).get("texture", ""))) return panel.add_theme_stylebox_override("panel", style) panel.set_meta("generated_panel_texture", false) + panel.set_meta("panel_style_variant", variant) + panel.set_meta("panel_texture_key", "") func _make_button_style(fill: Color, border: Color, border_width: int) -> StyleBoxFlat: @@ -3393,19 +3406,20 @@ func _create_hud() -> void: var opening_caption_panel := PanelContainer.new() opening_caption_panel.name = "OpeningCaptionScroll" - opening_caption_panel.position = Vector2(70, 526) - opening_caption_panel.size = Vector2(1140, 132) - opening_caption_panel.custom_minimum_size = Vector2(1140, 132) - _apply_panel_style(opening_caption_panel, "cinematic_caption") + opening_caption_panel.position = Vector2(64, 508) + opening_caption_panel.size = Vector2(1152, 148) + opening_caption_panel.custom_minimum_size = Vector2(1152, 148) + opening_caption_panel.modulate = Color(0.96, 0.95, 0.91, 0.99) + _apply_panel_style(opening_caption_panel, "story_caption") opening_prologue_root.add_child(opening_caption_panel) var opening_caption_row := HBoxContainer.new() - opening_caption_row.custom_minimum_size = Vector2(1092, 84) - opening_caption_row.add_theme_constant_override("separation", 16) + opening_caption_row.custom_minimum_size = Vector2(1100, 102) + opening_caption_row.add_theme_constant_override("separation", 18) opening_caption_panel.add_child(opening_caption_row) var opening_title_column := VBoxContainer.new() - opening_title_column.custom_minimum_size = Vector2(226, 84) + opening_title_column.custom_minimum_size = Vector2(226, 102) opening_title_column.add_theme_constant_override("separation", 4) opening_caption_row.add_child(opening_title_column) opening_title_column.add_child(_make_seal_ribbon(226, 12)) @@ -3414,30 +3428,25 @@ func _create_hud() -> void: opening_prologue_title_label.custom_minimum_size = Vector2(226, 48) opening_prologue_title_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER opening_prologue_title_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER - _apply_label_style(opening_prologue_title_label, UI_PARCHMENT_TEXT, 25) + _apply_label_style(opening_prologue_title_label, UI_AGED_INK, 25) opening_title_column.add_child(opening_prologue_title_label) opening_prologue_step_label = Label.new() opening_prologue_step_label.custom_minimum_size = Vector2(226, 20) opening_prologue_step_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER opening_prologue_step_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER - _apply_label_style(opening_prologue_step_label, UI_OLD_BRONZE, 14) + _apply_label_style(opening_prologue_step_label, UI_TARNISHED_BRONZE, 14) opening_title_column.add_child(opening_prologue_step_label) - var opening_body_panel := PanelContainer.new() - opening_body_panel.custom_minimum_size = Vector2(650, 84) - _apply_panel_style(opening_body_panel, "hud_info") - opening_caption_row.add_child(opening_body_panel) - opening_prologue_body_label = Label.new() - opening_prologue_body_label.custom_minimum_size = Vector2(616, 56) + opening_prologue_body_label.custom_minimum_size = Vector2(664, 102) opening_prologue_body_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART opening_prologue_body_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER - _apply_label_style(opening_prologue_body_label, UI_PARCHMENT_TEXT, 18) - opening_body_panel.add_child(opening_prologue_body_label) + _apply_label_style(opening_prologue_body_label, UI_AGED_INK, 18) + opening_caption_row.add_child(opening_prologue_body_label) var opening_button_column := VBoxContainer.new() - opening_button_column.custom_minimum_size = Vector2(168, 84) + opening_button_column.custom_minimum_size = Vector2(168, 102) opening_button_column.add_theme_constant_override("separation", 6) opening_caption_row.add_child(opening_button_column) @@ -3514,9 +3523,14 @@ func _create_hud() -> void: briefing_objective_header.add_child(_make_section_caption("승리와 패배", 548)) briefing_objective_toggle_button = Button.new() - briefing_objective_toggle_button.text = "닫기" - briefing_objective_toggle_button.tooltip_text = "승리와 패배 조건을 닫거나 펼칩니다." - briefing_objective_toggle_button.custom_minimum_size = Vector2(124, 28) + briefing_objective_toggle_button.text = "" + briefing_objective_toggle_button.icon = _make_toolbar_icon("objective") + briefing_objective_toggle_button.expand_icon = true + briefing_objective_toggle_button.tooltip_text = "승리와 패배 조건 접기" + briefing_objective_toggle_button.custom_minimum_size = Vector2(42, 32) + briefing_objective_toggle_button.add_theme_font_size_override("font_size", 1) + briefing_objective_toggle_button.set_meta("icon_only", true) + briefing_objective_toggle_button.set_meta("command_icon", "objective") briefing_objective_toggle_button.pressed.connect(_on_briefing_objective_toggle_pressed) briefing_objective_header.add_child(briefing_objective_toggle_button) @@ -11581,7 +11595,8 @@ func _update_briefing_objective_visibility() -> void: briefing_objective_panel.visible = has_text and not briefing_objective_collapsed if briefing_objective_toggle_button != null: briefing_objective_toggle_button.visible = has_text - briefing_objective_toggle_button.text = "펼치기" if briefing_objective_collapsed else "닫기" + briefing_objective_toggle_button.text = "" + briefing_objective_toggle_button.tooltip_text = "승리와 패배 조건 펼치기" if briefing_objective_collapsed else "승리와 패배 조건 접기" func _on_begin_battle_pressed() -> void: diff --git a/tools/smoke_chapter_one_polish.gd b/tools/smoke_chapter_one_polish.gd index 7841cfe..1323922 100644 --- a/tools/smoke_chapter_one_polish.gd +++ b/tools/smoke_chapter_one_polish.gd @@ -560,8 +560,10 @@ func _check_readability_contract(failures: Array[String]) -> void: failures.append("briefing objective panel should reserve enough height for victory and defeat text") if scene.briefing_objective_toggle_button == null: failures.append("briefing objective section should have a close/open button") - elif scene.briefing_objective_toggle_button.text != "닫기": - failures.append("briefing objective button should start with a clear close label") + elif scene.briefing_objective_toggle_button.text != "" or scene.briefing_objective_toggle_button.icon == null or not bool(scene.briefing_objective_toggle_button.get_meta("icon_only", false)): + failures.append("briefing objective button should start as an icon-only control") + elif not scene.briefing_objective_toggle_button.tooltip_text.contains("접기"): + failures.append("briefing objective icon tooltip should explain closing the conditions") _check_text_fit_contract(scene, failures) scene.free() diff --git a/tools/smoke_visual_assets.gd b/tools/smoke_visual_assets.gd index 0d1e800..9eebce1 100644 --- a/tools/smoke_visual_assets.gd +++ b/tools/smoke_visual_assets.gd @@ -3598,14 +3598,18 @@ func _check_ancient_ui_theme(failures: Array[String]) -> void: failures.append("mission objective panel should collapse cleanly") if scene.briefing_start_button == null or scene.briefing_start_button.text != "전투 시작": failures.append("briefing start button should clearly start after briefing") - if scene.briefing_objective_toggle_button == null or scene.briefing_objective_toggle_button.text != "닫기": - failures.append("briefing objective panel should expose a close button") + if scene.briefing_objective_toggle_button == null or scene.briefing_objective_toggle_button.text != "" or scene.briefing_objective_toggle_button.icon == null or not bool(scene.briefing_objective_toggle_button.get_meta("icon_only", false)): + failures.append("briefing objective panel should expose an icon-only close button") else: + _check_button_uses_generated_toolbar_icon(failures, scene.briefing_objective_toggle_button, "briefing objective toggle") + _check_button_uses_generated_surface(failures, scene.briefing_objective_toggle_button, "briefing objective toggle") + if not scene.briefing_objective_toggle_button.tooltip_text.contains("접기"): + failures.append("briefing objective icon tooltip should explain closing the panel") scene._set_briefing_objective_collapsed(true) - if scene.briefing_objective_panel == null or scene.briefing_objective_panel.visible or scene.briefing_objective_toggle_button.text != "펼치기": + if scene.briefing_objective_panel == null or scene.briefing_objective_panel.visible or scene.briefing_objective_toggle_button.text != "" or not scene.briefing_objective_toggle_button.tooltip_text.contains("펼치기"): failures.append("briefing objective panel should collapse cleanly") scene._set_briefing_objective_collapsed(false) - if scene.briefing_objective_panel == null or not scene.briefing_objective_panel.visible or scene.briefing_objective_toggle_button.text != "닫기": + if scene.briefing_objective_panel == null or not scene.briefing_objective_panel.visible or scene.briefing_objective_toggle_button.text != "" or not scene.briefing_objective_toggle_button.tooltip_text.contains("접기"): failures.append("briefing objective panel should reopen cleanly") scene.briefing_panel.visible = true scene.battle_started = false @@ -3726,6 +3730,8 @@ func _check_opening_prologue_presentation(failures: Array[String]) -> void: if caption_panel.custom_minimum_size.y > 150.0: failures.append("opening caption should stay compact instead of covering the story art: %s" % str(caption_panel.custom_minimum_size)) _check_panel_uses_generated_texture(failures, caption_panel, "opening cinematic caption generated frame") + if str(caption_panel.get_meta("panel_texture_key", "")) != "story_scroll": + failures.append("opening caption should use the generated story scroll surface") if scene.opening_prologue_next_button == null: failures.append("opening prologue should expose a next button") else: