Deepen ancient briefing and dialogue UI

This commit is contained in:
2026-06-19 06:36:06 +09:00
parent 94bd19edab
commit e370edad88
2 changed files with 180 additions and 13 deletions

View File

@@ -55,8 +55,8 @@ const UNIT_ARROW_ATTACK_DURATION := 0.36
const UNIT_COMMAND_ATTACK_DURATION := 0.38
const UNIT_HEAVY_ATTACK_DURATION := 0.34
const UNIT_TACTIC_CAST_DURATION := 0.42
const DIALOGUE_PANEL_POSITION := Vector2(72, 356)
const DIALOGUE_PANEL_SIZE := Vector2(1100, 304)
const DIALOGUE_PANEL_POSITION := Vector2(60, 356)
const DIALOGUE_PANEL_SIZE := Vector2(1160, 304)
const DIALOGUE_PORTRAIT_SIZE := Vector2(184, 262)
const DIALOGUE_COLUMN_SIZE := Vector2(850, 266)
const DIALOGUE_TEXT_SIZE := Vector2(830, 112)
@@ -143,6 +143,7 @@ var briefing_location_label: Label
var briefing_seal_ribbon: HBoxContainer
var briefing_objective_panel: PanelContainer
var briefing_objective_label: Label
var briefing_camp_overview_panel: PanelContainer
var briefing_camp_overview_row: HBoxContainer
var briefing_camp_overview_texture: TextureRect
var briefing_camp_overview_fallback_label: Label
@@ -184,6 +185,8 @@ var manual_save_button: Button
var manual_load_button: Button
var dialogue_row: HBoxContainer
var dialogue_panel: PanelContainer
var dialogue_left_tassel: VBoxContainer
var dialogue_right_tassel: VBoxContainer
var dialogue_portrait_panel: PanelContainer
var dialogue_portrait_texture: TextureRect
var dialogue_portrait_label: Label
@@ -341,7 +344,7 @@ func _age_panel_style(style: StyleBoxFlat, variant: String, border_width: int) -
style.set_border_width(SIDE_RIGHT, border_width + 1)
style.content_margin_top += 2
style.content_margin_bottom += 2
"edict", "notice_edict", "speech_scroll", "bamboo_slips":
"edict", "notice_edict", "speech_scroll", "bamboo_slips", "silk_map":
style.set_border_width(SIDE_TOP, border_width + 2)
style.set_border_width(SIDE_BOTTOM, border_width + 2)
"edict_compact":
@@ -425,6 +428,12 @@ func _apply_panel_style(panel: PanelContainer, variant: String) -> void:
border = UI_INK_WASH
border_width = 5
margin = 4
"silk_map":
fill = Color(0.54, 0.38, 0.18, 0.992)
border = UI_SCROLL_EDGE
border_width = 4
margin = 10
shadow_size = 5
"compact":
fill = Color(0.052, 0.078, 0.052, 0.982)
border = UI_JADE_EDGE
@@ -753,6 +762,64 @@ func _make_ornament_bar(width: float = 4.0, height: float = 0.0) -> ColorRect:
return bar
func _make_edict_marker_stack(labels: Array, height: float = 84.0) -> VBoxContainer:
var stack := VBoxContainer.new()
stack.custom_minimum_size = Vector2(30, height)
stack.size_flags_vertical = Control.SIZE_EXPAND_FILL
stack.mouse_filter = Control.MOUSE_FILTER_IGNORE
stack.add_theme_constant_override("separation", 3)
for index in range(labels.size()):
var panel := PanelContainer.new()
panel.custom_minimum_size = Vector2(30, 22)
panel.size_flags_vertical = Control.SIZE_SHRINK_CENTER
_apply_panel_style(panel, "speaker_seal" if index == 0 else "caption")
stack.add_child(panel)
var label := Label.new()
label.text = str(labels[index])
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
label.custom_minimum_size = Vector2(18, 16)
_apply_label_style(label, UI_PARCHMENT_TEXT, 13)
panel.add_child(label)
return stack
func _make_hanging_tassel(height: float = 262.0) -> VBoxContainer:
var tassel := VBoxContainer.new()
tassel.custom_minimum_size = Vector2(18, height)
tassel.size_flags_vertical = Control.SIZE_EXPAND_FILL
tassel.mouse_filter = Control.MOUSE_FILTER_IGNORE
tassel.add_theme_constant_override("separation", 4)
var top_seal := ColorRect.new()
top_seal.color = UI_SEAL_RED
top_seal.custom_minimum_size = Vector2(18, 18)
top_seal.mouse_filter = Control.MOUSE_FILTER_IGNORE
tassel.add_child(top_seal)
var cords := HBoxContainer.new()
cords.custom_minimum_size = Vector2(18, maxf(0.0, height - 44.0))
cords.size_flags_vertical = Control.SIZE_EXPAND_FILL
cords.mouse_filter = Control.MOUSE_FILTER_IGNORE
cords.add_theme_constant_override("separation", 4)
for index in range(2):
var cord := ColorRect.new()
cord.color = UI_TARNISHED_BRONZE if index == 0 else UI_CINNABAR_DARK
cord.custom_minimum_size = Vector2(6, height - 44.0)
cord.size_flags_vertical = Control.SIZE_EXPAND_FILL
cord.mouse_filter = Control.MOUSE_FILTER_IGNORE
cords.add_child(cord)
tassel.add_child(cords)
var bottom_seal := ColorRect.new()
bottom_seal.color = UI_SEAL_RED_DARK
bottom_seal.custom_minimum_size = Vector2(18, 18)
bottom_seal.mouse_filter = Control.MOUSE_FILTER_IGNORE
tassel.add_child(bottom_seal)
return tassel
func _create_hud() -> void:
var layer := CanvasLayer.new()
add_child(layer)
@@ -1200,22 +1267,35 @@ func _create_hud() -> void:
briefing_objective_panel.add_child(briefing_objective_row)
briefing_objective_row.add_child(_make_bamboo_gutter(18, 84))
briefing_objective_row.add_child(_make_edict_marker_stack(["", "", ""], 84))
briefing_objective_label = Label.new()
briefing_objective_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
briefing_objective_label.custom_minimum_size = Vector2(586, 84)
briefing_objective_label.custom_minimum_size = Vector2(500, 84)
briefing_objective_label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
_apply_label_style(briefing_objective_label, UI_AGED_INK, 15)
briefing_objective_row.add_child(briefing_objective_label)
briefing_objective_row.add_child(_make_edict_marker_stack(["", "", ""], 84))
briefing_objective_row.add_child(_make_bamboo_gutter(18, 84))
briefing_column.add_child(_make_ink_wash_rule(680, 7))
briefing_column.add_child(_make_section_caption("비단 전장도 · 군막 장부", 680))
briefing_camp_overview_panel = PanelContainer.new()
briefing_camp_overview_panel.custom_minimum_size = Vector2(680, 102)
_apply_panel_style(briefing_camp_overview_panel, "silk_map")
briefing_column.add_child(briefing_camp_overview_panel)
var briefing_camp_overview_shell := HBoxContainer.new()
briefing_camp_overview_shell.add_theme_constant_override("separation", 10)
briefing_camp_overview_panel.add_child(briefing_camp_overview_shell)
briefing_camp_overview_shell.add_child(_make_edict_marker_stack(["", ""], 72))
briefing_camp_overview_row = HBoxContainer.new()
briefing_camp_overview_row.custom_minimum_size = Vector2(680, 84)
briefing_camp_overview_row.custom_minimum_size = Vector2(580, 84)
briefing_camp_overview_row.add_theme_constant_override("separation", 10)
briefing_column.add_child(briefing_camp_overview_row)
briefing_camp_overview_row.size_flags_horizontal = Control.SIZE_EXPAND_FILL
briefing_camp_overview_shell.add_child(briefing_camp_overview_row)
var camp_thumbnail_panel := PanelContainer.new()
camp_thumbnail_panel.custom_minimum_size = BRIEFING_CAMP_THUMBNAIL_SIZE
@@ -1243,10 +1323,11 @@ func _create_hud() -> void:
briefing_camp_overview_label = Label.new()
briefing_camp_overview_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
briefing_camp_overview_label.custom_minimum_size = Vector2(520, 72)
briefing_camp_overview_label.custom_minimum_size = Vector2(420, 72)
briefing_camp_overview_label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
_apply_label_style(briefing_camp_overview_label, UI_AGED_INK, 14)
briefing_camp_overview_row.add_child(briefing_camp_overview_label)
briefing_camp_overview_shell.add_child(_make_bamboo_gutter(14, 72))
briefing_column.add_child(_make_scroll_rod(680, 3))
@@ -1474,9 +1555,12 @@ func _create_hud() -> void:
root.add_child(dialogue_panel)
dialogue_row = HBoxContainer.new()
dialogue_row.add_theme_constant_override("separation", 14)
dialogue_row.add_theme_constant_override("separation", 10)
dialogue_panel.add_child(dialogue_row)
dialogue_left_tassel = _make_hanging_tassel(DIALOGUE_PORTRAIT_SIZE.y)
dialogue_row.add_child(dialogue_left_tassel)
dialogue_portrait_panel = PanelContainer.new()
dialogue_portrait_panel.custom_minimum_size = DIALOGUE_PORTRAIT_SIZE
_apply_panel_style(dialogue_portrait_panel, "portrait")
@@ -1506,6 +1590,9 @@ func _create_hud() -> void:
dialogue_column.add_theme_constant_override("separation", 7)
dialogue_row.add_child(dialogue_column)
dialogue_right_tassel = _make_hanging_tassel(DIALOGUE_PORTRAIT_SIZE.y)
dialogue_row.add_child(dialogue_right_tassel)
dialogue_column.add_child(_make_tablet_binding(DIALOGUE_TEXT_SIZE.x, 13))
dialogue_seal_ribbon = _make_seal_ribbon(DIALOGUE_TEXT_SIZE.x, 18)
@@ -4380,8 +4467,10 @@ func _normalized_dialogue_lines(lines: Array) -> Array:
var text := str(line.get("text", ""))
if text.is_empty():
continue
var speaker := str(line.get("speaker", ""))
var display_speaker := str(line.get("display_speaker", speaker))
result.append({
"speaker": str(line.get("speaker", "")),
"speaker": display_speaker,
"text": text,
"portrait": str(line.get("portrait", "")),
"side": _normalized_dialogue_side(line.get("side", "left"))
@@ -4437,12 +4526,13 @@ func _render_dialogue_line() -> void:
return
var line: Dictionary = active_dialogue_lines[active_dialogue_index]
var speaker := str(line.get("speaker", ""))
var display_speaker := str(line.get("display_speaker", speaker))
var side := _normalized_dialogue_side(line.get("side", "left"))
_apply_dialogue_side(side)
dialogue_speaker_label.text = speaker
dialogue_speaker_label.visible = not speaker.is_empty()
dialogue_speaker_label.text = display_speaker
dialogue_speaker_label.visible = not display_speaker.is_empty()
dialogue_text_label.text = str(line.get("text", ""))
_update_dialogue_portrait(speaker, str(line.get("portrait", "")))
_update_dialogue_portrait(display_speaker, str(line.get("portrait", "")))
_update_dialogue_controls()
dialogue_panel.visible = true
_update_hud()
@@ -4460,7 +4550,7 @@ func _update_dialogue_controls() -> void:
func _apply_dialogue_side(side: String) -> void:
if dialogue_row == null or dialogue_portrait_panel == null or dialogue_column == null:
return
var portrait_index := 1 if side == "right" else 0
var portrait_index: int = maxi(0, dialogue_row.get_child_count() - 2) if side == "right" else 1
dialogue_row.move_child(dialogue_portrait_panel, portrait_index)
dialogue_speaker_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT if side == "right" else HORIZONTAL_ALIGNMENT_LEFT
dialogue_text_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT if side == "right" else HORIZONTAL_ALIGNMENT_LEFT
@@ -4880,6 +4970,8 @@ func _update_briefing_camp_overview(briefing: Dictionary, prep_locked: bool) ->
return
var overview_text := _format_briefing_camp_overview_text(briefing, prep_locked)
briefing_camp_overview_row.visible = not overview_text.is_empty()
if briefing_camp_overview_panel != null:
briefing_camp_overview_panel.visible = not overview_text.is_empty()
if briefing_camp_overview_label != null:
briefing_camp_overview_label.text = overview_text
var texture := _current_battle_background_texture()