Add briefing force preview markers

This commit is contained in:
2026-06-20 05:26:42 +09:00
parent 2723cdb8d7
commit 7b78c8255c
3 changed files with 142 additions and 1 deletions

View File

@@ -139,6 +139,9 @@ const BRIEFING_CAMP_THUMBNAIL_SIZE := Vector2(188, 86)
const BRIEFING_TACTICAL_MARKER_CHIP_SIZE := Vector2(122, 26)
const BRIEFING_TACTICAL_MARKER_ICON_SIZE := Vector2(22, 22)
const BRIEFING_TACTICAL_MARKER_MAX_COUNT := 3
const BRIEFING_FORCE_PREVIEW_ICON_SIZE := Vector2(32, 32)
const BRIEFING_FORCE_PREVIEW_MAX_ALLIES := 2
const BRIEFING_FORCE_PREVIEW_MAX_ENEMY_TYPES := 4
const OPENING_STORY_BEAT_CARD_SIZE := Vector2(122, 66)
const OPENING_STORY_BEAT_IMAGE_SIZE := Vector2(112, 42)
const CHAPTER_SEAL_BADGE_SIZE := Vector2(54, 54)
@@ -409,6 +412,7 @@ var briefing_camp_overview_row: HBoxContainer
var briefing_camp_overview_texture: TextureRect
var briefing_camp_overview_fallback_label: Label
var briefing_camp_overview_label: Label
var briefing_force_preview_overlay: Control
var briefing_tactical_marker_list: VBoxContainer
var briefing_label: Label
var briefing_start_button: Button
@@ -3270,6 +3274,13 @@ func _create_hud() -> void:
camp_thumbnail_stack.add_child(briefing_camp_overview_fallback_label)
camp_thumbnail_stack.add_child(_make_map_lattice_overlay(BRIEFING_CAMP_THUMBNAIL_SIZE))
briefing_force_preview_overlay = Control.new()
briefing_force_preview_overlay.name = "BriefingForcePreviewOverlay"
briefing_force_preview_overlay.set_anchors_preset(Control.PRESET_FULL_RECT)
briefing_force_preview_overlay.custom_minimum_size = BRIEFING_CAMP_THUMBNAIL_SIZE
briefing_force_preview_overlay.mouse_filter = Control.MOUSE_FILTER_IGNORE
camp_thumbnail_stack.add_child(briefing_force_preview_overlay)
briefing_camp_overview_label = Label.new()
briefing_camp_overview_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
briefing_camp_overview_label.custom_minimum_size = Vector2(238, 86)
@@ -10346,9 +10357,118 @@ func _update_briefing_camp_overview(briefing: Dictionary, prep_locked: bool) ->
if briefing_camp_overview_fallback_label != null:
briefing_camp_overview_fallback_label.text = "비단 전장도"
briefing_camp_overview_fallback_label.visible = not has_texture
_rebuild_briefing_force_preview_overlay()
_rebuild_briefing_tactical_marker_list()
func _rebuild_briefing_force_preview_overlay() -> void:
if briefing_force_preview_overlay == null:
return
for child in briefing_force_preview_overlay.get_children():
briefing_force_preview_overlay.remove_child(child)
child.queue_free()
var allies := _briefing_force_preview_allies()
for index in range(allies.size()):
var ally: Dictionary = allies[index]
var icon := _make_briefing_force_preview_icon(ally, "ally", _format_briefing_force_unit_tooltip(ally, "아군"))
icon.name = "BriefingForcePreviewAllyIcon%d" % (index + 1)
icon.position = Vector2(8.0 + float(index) * 34.0, 46.0)
briefing_force_preview_overlay.add_child(icon)
var enemies := _briefing_force_preview_enemy_types()
for index in range(enemies.size()):
var enemy: Dictionary = enemies[index]
var icon := _make_briefing_force_preview_icon(enemy, "enemy", _format_briefing_force_unit_tooltip(enemy, "적세"))
icon.name = "BriefingForcePreviewEnemyIcon%d" % (index + 1)
icon.position = Vector2(148.0 - float(index) * 30.0, 8.0)
briefing_force_preview_overlay.add_child(icon)
func _briefing_force_preview_allies() -> Array[Dictionary]:
var result: Array[Dictionary] = []
for unit in state.get_controllable_player_units():
result.append(unit)
if result.size() >= BRIEFING_FORCE_PREVIEW_MAX_ALLIES:
break
return result
func _briefing_force_preview_enemy_types() -> Array[Dictionary]:
var result: Array[Dictionary] = []
var seen_classes := {}
for unit in state.get_living_units(BattleState.TEAM_ENEMY):
var class_key := str(unit.get("class_id", _unit_class_display_name(unit))).strip_edges()
if class_key.is_empty():
class_key = str(unit.get("name", "enemy"))
if seen_classes.has(class_key):
continue
seen_classes[class_key] = true
result.append(unit)
if result.size() >= BRIEFING_FORCE_PREVIEW_MAX_ENEMY_TYPES:
break
return result
func _make_briefing_force_preview_icon(unit: Dictionary, side: String, tooltip_text: String) -> PanelContainer:
var panel := PanelContainer.new()
panel.custom_minimum_size = BRIEFING_FORCE_PREVIEW_ICON_SIZE
panel.tooltip_text = tooltip_text
panel.set_meta("briefing_force_side", side)
_apply_panel_style(panel, "portrait")
var panel_style := panel.get_theme_stylebox("panel")
if panel_style != null:
panel_style.content_margin_left = 2
panel_style.content_margin_right = 2
panel_style.content_margin_top = 2
panel_style.content_margin_bottom = 2
var stack := Control.new()
stack.custom_minimum_size = BRIEFING_FORCE_PREVIEW_ICON_SIZE
stack.tooltip_text = tooltip_text
panel.add_child(stack)
var texture_rect := TextureRect.new()
texture_rect.name = "BriefingForcePreviewImage"
texture_rect.set_anchors_preset(Control.PRESET_FULL_RECT)
texture_rect.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
texture_rect.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
texture_rect.texture = _briefing_force_preview_texture(unit, side)
texture_rect.visible = texture_rect.texture != null
texture_rect.tooltip_text = tooltip_text
stack.add_child(texture_rect)
var fallback_label := Label.new()
fallback_label.set_anchors_preset(Control.PRESET_FULL_RECT)
fallback_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
fallback_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
fallback_label.text = _dialogue_portrait_initials(str(unit.get("name", "")))
fallback_label.visible = texture_rect.texture == null
fallback_label.tooltip_text = tooltip_text
_apply_label_style(fallback_label, UI_PARCHMENT_TEXT, 11)
stack.add_child(fallback_label)
_set_control_tree_tooltip(panel, tooltip_text)
return panel
func _briefing_force_preview_texture(unit: Dictionary, side: String) -> Texture2D:
var texture: Texture2D = null
if side == "ally":
texture = _load_portrait_texture(str(unit.get("portrait", "")))
if texture == null:
texture = _load_art_texture(str(unit.get("sprite", "")))
if texture == null:
texture = _load_unit_class_icon_texture(unit)
return texture
func _format_briefing_force_unit_tooltip(unit: Dictionary, side_label: String) -> String:
return "%s · %s\n%s · 품계 %d" % [
side_label,
str(unit.get("name", "부대")),
_unit_class_display_name(unit),
int(unit.get("level", 1))
]
func _rebuild_briefing_tactical_marker_list() -> void:
if briefing_tactical_marker_list == null:
return