From 4d89c03948724ad62b1bacdcbfcce96ec0933f5f Mon Sep 17 00:00:00 2001 From: Wickedness Date: Sat, 20 Jun 2026 22:55:31 +0900 Subject: [PATCH] Improve narration dialogue record card --- scripts/scenes/battle_scene.gd | 26 ++++++++++++++++++++++---- tools/smoke_chapter_one_polish.gd | 10 ++++++++++ tools/smoke_visual_assets.gd | 12 ++++++++---- 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/scripts/scenes/battle_scene.gd b/scripts/scenes/battle_scene.gd index cf39170..ef193dc 100644 --- a/scripts/scenes/battle_scene.gd +++ b/scripts/scenes/battle_scene.gd @@ -4747,6 +4747,7 @@ func _create_hud() -> void: dialogue_portrait_texture = TextureRect.new() dialogue_portrait_texture.set_anchors_preset(Control.PRESET_FULL_RECT) + dialogue_portrait_texture.texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR dialogue_portrait_texture.expand_mode = TextureRect.EXPAND_IGNORE_SIZE dialogue_portrait_texture.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED dialogue_portrait_stack.add_child(dialogue_portrait_texture) @@ -12818,12 +12819,29 @@ func _update_dialogue_portrait(speaker: String, portrait_path: String) -> void: return var texture := _load_portrait_texture(portrait_path) var has_portrait := texture != null + var record_texture := _dialogue_record_texture() if not has_portrait and _dialogue_uses_record_card(speaker) else null + var has_record_texture := record_texture != null var placeholder_text := _dialogue_portrait_placeholder_text(speaker) dialogue_portrait_panel.visible = true - dialogue_portrait_texture.texture = texture - dialogue_portrait_texture.visible = has_portrait + dialogue_portrait_texture.texture = texture if has_portrait else record_texture + dialogue_portrait_texture.visible = has_portrait or has_record_texture + dialogue_portrait_texture.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED if has_portrait else TextureRect.STRETCH_KEEP_ASPECT_COVERED + dialogue_portrait_texture.modulate = Color(1.0, 1.0, 1.0, 0.96 if has_portrait else 0.44) dialogue_portrait_label.text = placeholder_text dialogue_portrait_label.visible = not has_portrait + dialogue_portrait_label.add_theme_font_size_override("font_size", 24 if placeholder_text.contains("\n") else 30) + + +func _dialogue_uses_record_card(speaker: String) -> bool: + var normalized_speaker := speaker.strip_edges() + return normalized_speaker.is_empty() or _canonical_speaker_name(normalized_speaker) == "Narrator" + + +func _dialogue_record_texture() -> Texture2D: + var texture_path := state.get_map_background_path().strip_edges() + if texture_path.is_empty(): + texture_path = DEFAULT_BATTLE_BACKGROUND_PATH + return _load_art_texture(texture_path) func _localized_speaker_name(speaker: String) -> String: @@ -12874,9 +12892,9 @@ func _load_portrait_texture(portrait_path: String) -> Texture2D: func _dialogue_portrait_placeholder_text(speaker: String) -> String: var normalized_speaker := speaker.strip_edges() if normalized_speaker.is_empty(): - return "기록" + return "전황\n기록" if _canonical_speaker_name(normalized_speaker) == "Narrator": - return "기록" + return "전황\n기록" var initials := _dialogue_portrait_initials(normalized_speaker) return "기록" if initials.is_empty() else initials diff --git a/tools/smoke_chapter_one_polish.gd b/tools/smoke_chapter_one_polish.gd index 7851736..ce25f46 100644 --- a/tools/smoke_chapter_one_polish.gd +++ b/tools/smoke_chapter_one_polish.gd @@ -808,6 +808,16 @@ func _check_first_battle_rendered_text_fit(failures: Array[String]) -> void: if not scene.briefing_label.tooltip_text.contains("적은 마을과 성채"): failures.append("opening briefing body should keep the full briefing text in its tooltip") + scene.active_dialogue_lines = scene._normalized_dialogue_lines([{"speaker": "", "text": "천하가 어지러워지던 때, 젊은 조조는 먼저 무너지는 고을의 소식을 들었다."}]) + scene.active_dialogue_index = 0 + scene._render_dialogue_line() + if scene.dialogue_portrait_texture == null or not scene.dialogue_portrait_texture.visible or scene.dialogue_portrait_texture.texture == null: + failures.append("narration dialogue should use the current battlefield image as a record card instead of an empty portrait slot") + elif scene.dialogue_portrait_texture.stretch_mode != TextureRect.STRETCH_KEEP_ASPECT_COVERED: + failures.append("narration record card should cover the portrait slot without black empty space") + if scene.dialogue_portrait_label == null or not scene.dialogue_portrait_label.visible or not scene.dialogue_portrait_label.text.contains("전황"): + failures.append("narration record card should label the slot as a battle record: %s" % ("" if scene.dialogue_portrait_label == null else scene.dialogue_portrait_label.text)) + var briefing: Dictionary = scene.state.get_briefing() var dialogue_lines: Array = [] dialogue_lines.append_array(briefing.get("camp_dialogue", [])) diff --git a/tools/smoke_visual_assets.gd b/tools/smoke_visual_assets.gd index ede27fd..ca49925 100644 --- a/tools/smoke_visual_assets.gd +++ b/tools/smoke_visual_assets.gd @@ -3999,8 +3999,10 @@ func _check_ancient_ui_theme(failures: Array[String]) -> void: scene._render_dialogue_line() if scene.dialogue_portrait_panel == null or not scene.dialogue_portrait_panel.visible: failures.append("speakerless narration should keep the dialogue portrait slot visible") - if scene.dialogue_portrait_label == null or scene.dialogue_portrait_label.text != "기록": - failures.append("speakerless narration should show a stable record placeholder") + if scene.dialogue_portrait_texture == null or not scene.dialogue_portrait_texture.visible or scene.dialogue_portrait_texture.texture == null: + failures.append("speakerless narration should use a battlefield record image instead of an empty portrait slot") + if scene.dialogue_portrait_label == null or not scene.dialogue_portrait_label.text.contains("전황"): + failures.append("speakerless narration should show a stable battle-record placeholder") var portrait_index_after_narration: int = scene.dialogue_row.get_children().find(scene.dialogue_portrait_panel) if portrait_index_after_narration != portrait_index_before_narration: failures.append("speakerless narration should not move the portrait slot") @@ -4014,8 +4016,10 @@ func _check_ancient_ui_theme(failures: Array[String]) -> void: scene._render_dialogue_line() if scene.dialogue_speaker_label == null or scene.dialogue_speaker_label.text != "이야기": failures.append("explicit narrator should keep the story speaker label: %s" % ("" if scene.dialogue_speaker_label == null else scene.dialogue_speaker_label.text)) - if scene.dialogue_portrait_label == null or scene.dialogue_portrait_label.text != "기록": - failures.append("explicit narrator should use the record placeholder instead of a single initial: %s" % ("" if scene.dialogue_portrait_label == null else scene.dialogue_portrait_label.text)) + if scene.dialogue_portrait_label == null or not scene.dialogue_portrait_label.text.contains("전황"): + failures.append("explicit narrator should use the battle-record placeholder instead of a single initial: %s" % ("" if scene.dialogue_portrait_label == null else scene.dialogue_portrait_label.text)) + if scene.dialogue_portrait_texture == null or not scene.dialogue_portrait_texture.visible or scene.dialogue_portrait_texture.texture == null: + failures.append("explicit narrator should keep a readable record image in the portrait slot") scene._hide_dialogue_panel() var enemy_lines := scene._normalized_dialogue_lines([{"speaker": "Wen Chou", "text": "전진!"}]) if enemy_lines.is_empty() or str((enemy_lines[0] as Dictionary).get("speaker", "")) != "문추":