Deepen antique Chinese battle UI skin

This commit is contained in:
2026-06-19 06:15:28 +09:00
parent 0b599b39be
commit 065c641931
2 changed files with 177 additions and 56 deletions

View File

@@ -55,10 +55,10 @@ 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, 396)
const DIALOGUE_PANEL_SIZE := Vector2(1100, 260)
const DIALOGUE_PORTRAIT_SIZE := Vector2(184, 224)
const DIALOGUE_COLUMN_SIZE := Vector2(850, 226)
const DIALOGUE_PANEL_POSITION := Vector2(72, 356)
const DIALOGUE_PANEL_SIZE := Vector2(1100, 304)
const DIALOGUE_PORTRAIT_SIZE := Vector2(184, 262)
const DIALOGUE_COLUMN_SIZE := Vector2(850, 266)
const DIALOGUE_TEXT_SIZE := Vector2(830, 112)
const BRIEFING_CAMP_THUMBNAIL_SIZE := Vector2(138, 72)
const CAMP_TALK_PORTRAIT_SIZE := Vector2(58, 58)
@@ -341,9 +341,12 @@ 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", "speech_scroll", "bamboo_slips":
"edict", "notice_edict", "speech_scroll", "bamboo_slips":
style.set_border_width(SIDE_TOP, border_width + 2)
style.set_border_width(SIDE_BOTTOM, border_width + 2)
"edict_compact":
style.set_border_width(SIDE_TOP, border_width + 1)
style.set_border_width(SIDE_BOTTOM, border_width + 1)
"seal", "speaker_seal", "caption":
style.set_border_width(SIDE_LEFT, border_width + 2)
style.set_border_width(SIDE_RIGHT, border_width + 2)
@@ -362,17 +365,29 @@ func _apply_panel_style(panel: PanelContainer, variant: String) -> void:
var shadow_size := 6
match variant:
"paper":
fill = UI_SCROLL_CENTER
border = UI_CHARCOAL_WASH
border_width = 7
margin = 20
shadow_size = 16
fill = Color(0.68, 0.50, 0.25, 0.997)
border = UI_BAMBOO_DARK
border_width = 9
margin = 22
shadow_size = 18
"edict":
fill = Color(0.55, 0.36, 0.15, 0.995)
border = UI_INK_WASH
fill = UI_BONE_PAPER
border = UI_BAMBOO_DARK
border_width = 6
margin = 16
shadow_size = 7
"edict_compact":
fill = UI_BONE_PAPER
border = UI_BAMBOO_DARK
border_width = 3
margin = 6
shadow_size = 2
"notice_edict":
fill = UI_BONE_PAPER
border = UI_BAMBOO_DARK
border_width = 5
margin = 15
shadow_size = 8
margin = 12
shadow_size = 10
"seal":
fill = Color(0.23, 0.018, 0.010, 1.0)
border = UI_OLD_BRONZE
@@ -389,16 +404,16 @@ func _apply_panel_style(panel: PanelContainer, variant: String) -> void:
border_width = 5
margin = 3
"dialogue":
fill = Color(0.036, 0.012, 0.006, 0.996)
border = UI_SEAL_RED_DARK
border_width = 7
margin = 18
fill = Color(0.070, 0.018, 0.010, 0.997)
border = UI_OLD_BRONZE
border_width = 8
margin = 19
shadow_size = 18
"speech_scroll":
fill = Color(0.67, 0.50, 0.27, 0.996)
border = UI_INK_WASH
border_width = 5
margin = 14
fill = UI_BONE_PAPER
border = UI_BAMBOO_DARK
border_width = 6
margin = 15
shadow_size = 4
"notice":
fill = Color(0.070, 0.020, 0.014, 0.982)
@@ -429,10 +444,10 @@ func _apply_panel_style(panel: PanelContainer, variant: String) -> void:
margin = 5
shadow_size = 2
"result_tablet":
fill = Color(0.48, 0.34, 0.17, 0.994)
border = UI_SOOT_EDGE
border_width = 7
margin = 18
fill = Color(0.62, 0.44, 0.20, 0.996)
border = UI_BAMBOO_DARK
border_width = 8
margin = 19
shadow_size = 12
_:
pass
@@ -577,6 +592,69 @@ func _make_scroll_rod(width: float = 0.0, height: float = 4.0) -> HBoxContainer:
return row
func _make_tablet_binding(width: float = 0.0, height: float = 18.0) -> HBoxContainer:
var row := HBoxContainer.new()
row.custom_minimum_size = Vector2(width, height)
row.size_flags_horizontal = Control.SIZE_EXPAND_FILL
row.mouse_filter = Control.MOUSE_FILTER_IGNORE
row.add_theme_constant_override("separation", 3)
row.add_child(_make_binding_end_cap(height))
row.add_child(_make_binding_strip(height, UI_BAMBOO_DARK, 14.0))
row.add_child(_make_binding_strip(height, UI_TARNISHED_BRONZE, 0.0))
row.add_child(_make_seal_knot(height))
row.add_child(_make_binding_strip(height, UI_TARNISHED_BRONZE, 0.0))
row.add_child(_make_binding_strip(height, UI_BAMBOO_DARK, 14.0))
row.add_child(_make_binding_end_cap(height))
return row
func _make_binding_end_cap(size: float) -> ColorRect:
var cap := ColorRect.new()
cap.color = UI_LACQUER_EDGE
cap.custom_minimum_size = Vector2(size * 1.15, size)
cap.mouse_filter = Control.MOUSE_FILTER_IGNORE
return cap
func _make_binding_strip(height: float, color: Color, width: float) -> ColorRect:
var strip := ColorRect.new()
strip.color = color
strip.custom_minimum_size = Vector2(width, height)
strip.size_flags_horizontal = Control.SIZE_EXPAND_FILL if width <= 0.0 else Control.SIZE_SHRINK_CENTER
strip.mouse_filter = Control.MOUSE_FILTER_IGNORE
return strip
func _make_seal_knot(height: float) -> HBoxContainer:
var knot := HBoxContainer.new()
knot.custom_minimum_size = Vector2(height * 2.0 + 3.0, height)
knot.mouse_filter = Control.MOUSE_FILTER_IGNORE
knot.add_theme_constant_override("separation", 3)
for index in range(2):
var tile := ColorRect.new()
tile.color = UI_SEAL_RED if index == 0 else UI_SEAL_RED_DARK
tile.custom_minimum_size = Vector2(height, height)
tile.mouse_filter = Control.MOUSE_FILTER_IGNORE
knot.add_child(tile)
return knot
func _make_ink_wash_rule(width: float = 0.0, height: float = 7.0) -> HBoxContainer:
var row := HBoxContainer.new()
row.custom_minimum_size = Vector2(width, height)
row.size_flags_horizontal = Control.SIZE_EXPAND_FILL
row.mouse_filter = Control.MOUSE_FILTER_IGNORE
row.add_theme_constant_override("separation", 2)
for index in range(5):
var strip := ColorRect.new()
strip.custom_minimum_size = Vector2(10 if index != 2 else width, height)
strip.size_flags_horizontal = Control.SIZE_EXPAND_FILL if index == 2 else Control.SIZE_SHRINK_CENTER
strip.color = UI_INK_WASH if index == 2 else Color(UI_SEAL_RED_DARK.r, UI_SEAL_RED_DARK.g, UI_SEAL_RED_DARK.b, 0.96)
strip.mouse_filter = Control.MOUSE_FILTER_IGNORE
row.add_child(strip)
return row
func _make_seal_ribbon(width: float = 0.0, height: float = 18.0) -> HBoxContainer:
var row := HBoxContainer.new()
row.custom_minimum_size = Vector2(width, height)
@@ -687,28 +765,40 @@ func _create_hud() -> void:
layer.add_child(root)
var top_bar := PanelContainer.new()
top_bar.position = Vector2(24, 16)
top_bar.size = Vector2(1120, 64)
top_bar.position = Vector2(24, 14)
top_bar.size = Vector2(1192, 72)
_apply_panel_style(top_bar, "compact")
root.add_child(top_bar)
var top_row := HBoxContainer.new()
top_row.add_theme_constant_override("separation", 12)
top_row.add_theme_constant_override("separation", 8)
top_bar.add_child(top_row)
status_label = Label.new()
status_label.custom_minimum_size = Vector2(180, 40)
status_label.custom_minimum_size = Vector2(154, 48)
_apply_label_style(status_label, UI_PARCHMENT_TEXT)
top_row.add_child(status_label)
var objective_top_panel := PanelContainer.new()
objective_top_panel.custom_minimum_size = Vector2(460, 54)
_apply_panel_style(objective_top_panel, "edict_compact")
top_row.add_child(objective_top_panel)
var objective_top_row := HBoxContainer.new()
objective_top_row.add_theme_constant_override("separation", 7)
objective_top_panel.add_child(objective_top_row)
objective_top_row.add_child(_make_bamboo_gutter(14, 36))
objective_label = Label.new()
objective_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
objective_label.custom_minimum_size = Vector2(360, 48)
_apply_label_style(objective_label, UI_PARCHMENT_TEXT)
top_row.add_child(objective_label)
objective_label.custom_minimum_size = Vector2(382, 36)
objective_label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
_apply_label_style(objective_label, UI_AGED_INK, 13)
objective_top_row.add_child(objective_label)
objective_top_row.add_child(_make_bamboo_gutter(14, 36))
campaign_status_label = Label.new()
campaign_status_label.custom_minimum_size = Vector2(300, 40)
campaign_status_label.custom_minimum_size = Vector2(260, 48)
_apply_label_style(campaign_status_label, UI_PARCHMENT_TEXT)
top_row.add_child(campaign_status_label)
@@ -724,19 +814,26 @@ func _create_hud() -> void:
objective_notice_panel = PanelContainer.new()
objective_notice_panel.visible = false
objective_notice_panel.position = Vector2(360, 84)
objective_notice_panel.size = Vector2(560, 64)
objective_notice_panel.position = Vector2(338, 88)
objective_notice_panel.size = Vector2(604, 128)
objective_notice_panel.mouse_filter = Control.MOUSE_FILTER_IGNORE
_apply_panel_style(objective_notice_panel, "notice")
_apply_panel_style(objective_notice_panel, "notice_edict")
root.add_child(objective_notice_panel)
var objective_notice_column := VBoxContainer.new()
objective_notice_column.add_theme_constant_override("separation", 5)
objective_notice_panel.add_child(objective_notice_column)
objective_notice_column.add_child(_make_scroll_rod(548, 4))
objective_notice_column.add_child(_make_seal_ribbon(548, 14))
objective_notice_label = Label.new()
objective_notice_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
objective_notice_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
objective_notice_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
objective_notice_label.custom_minimum_size = Vector2(520, 48)
_apply_label_style(objective_notice_label, UI_PARCHMENT_TEXT, 16)
objective_notice_panel.add_child(objective_notice_label)
objective_notice_label.custom_minimum_size = Vector2(548, 54)
_apply_label_style(objective_notice_label, UI_AGED_INK, 15)
objective_notice_column.add_child(objective_notice_label)
objective_notice_column.add_child(_make_scroll_rod(548, 3))
var side_panel := PanelContainer.new()
side_panel.position = Vector2(760, 104)
@@ -1063,8 +1160,9 @@ func _create_hud() -> void:
root.add_child(briefing_panel)
var briefing_column := VBoxContainer.new()
briefing_column.add_theme_constant_override("separation", 8)
briefing_column.add_theme_constant_override("separation", 7)
briefing_panel.add_child(briefing_column)
briefing_column.add_child(_make_tablet_binding(680, 16))
var briefing_title_panel := PanelContainer.new()
briefing_title_panel.custom_minimum_size = Vector2(680, 46)
@@ -1111,6 +1209,7 @@ func _create_hud() -> void:
briefing_objective_row.add_child(briefing_objective_label)
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_row = HBoxContainer.new()
@@ -1161,6 +1260,8 @@ func _create_hud() -> void:
_apply_label_style(briefing_label, UI_AGED_INK, 14)
briefing_scroll.add_child(briefing_label)
briefing_column.add_child(_make_tablet_binding(680, 14))
var prep_button_row := HBoxContainer.new()
prep_button_row.add_theme_constant_override("separation", 8)
briefing_column.add_child(prep_button_row)
@@ -1402,9 +1503,11 @@ func _create_hud() -> void:
dialogue_column = VBoxContainer.new()
dialogue_column.custom_minimum_size = DIALOGUE_COLUMN_SIZE
dialogue_column.size_flags_horizontal = Control.SIZE_EXPAND_FILL
dialogue_column.add_theme_constant_override("separation", 8)
dialogue_column.add_theme_constant_override("separation", 7)
dialogue_row.add_child(dialogue_column)
dialogue_column.add_child(_make_tablet_binding(DIALOGUE_TEXT_SIZE.x, 13))
dialogue_seal_ribbon = _make_seal_ribbon(DIALOGUE_TEXT_SIZE.x, 18)
dialogue_column.add_child(dialogue_seal_ribbon)
@@ -1440,6 +1543,7 @@ func _create_hud() -> void:
dialogue_text_row.add_child(_make_bamboo_gutter(18, DIALOGUE_TEXT_SIZE.y - 20))
dialogue_column.add_child(_make_scroll_rod(DIALOGUE_TEXT_SIZE.x, 3))
dialogue_column.add_child(_make_ink_wash_rule(DIALOGUE_TEXT_SIZE.x, 6))
var dialogue_control_row := HBoxContainer.new()
dialogue_control_row.add_theme_constant_override("separation", 8)
@@ -1476,10 +1580,12 @@ func _create_hud() -> void:
result_column.alignment = BoxContainer.ALIGNMENT_CENTER
result_panel.add_child(result_column)
result_column.add_child(_make_tablet_binding(520, 16))
result_column.add_child(_make_scroll_rod(520, 4))
result_seal_ribbon = _make_seal_ribbon(520, 18)
result_column.add_child(result_seal_ribbon)
result_column.add_child(_make_section_caption("戰功 조서", 520))
result_label = Label.new()
result_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_LEFT
@@ -2054,6 +2160,16 @@ func _draw_silk_map_frame(board_rect: Rect2) -> void:
for rod in [top_rod, bottom_rod, left_rod, right_rod]:
draw_rect(rod, UI_BAMBOO_DARK)
draw_rect(rod, Color(0.62, 0.43, 0.18, 0.80), false, 1.0)
var hanger_y := top_rod.position.y - 8.0
draw_line(
Vector2(top_rod.position.x + 32.0, hanger_y),
Vector2(top_rod.end.x - 32.0, hanger_y),
Color(UI_TARNISHED_BRONZE.r, UI_TARNISHED_BRONZE.g, UI_TARNISHED_BRONZE.b, 0.82),
2.0
)
for x in [top_rod.position.x + 54.0, top_rod.end.x - 54.0]:
draw_line(Vector2(x, hanger_y), Vector2(x, top_rod.position.y + 7.0), Color(UI_BAMBOO_DARK.r, UI_BAMBOO_DARK.g, UI_BAMBOO_DARK.b, 0.88), 2.0)
draw_circle(Vector2(x, hanger_y), 4.0, UI_SEAL_RED_DARK)
for corner in [
top_rod.position - Vector2(3, 3),
Vector2(top_rod.end.x - 11.0, top_rod.position.y - 3.0),
@@ -2064,6 +2180,11 @@ func _draw_silk_map_frame(board_rect: Rect2) -> void:
draw_rect(Rect2(corner + Vector2(2, 2), Vector2(10, 10)), UI_OLD_BRONZE, false, 1.0)
draw_rect(board_rect.grow(4.0), UI_LACQUER_EDGE, false, 5.0)
draw_rect(board_rect.grow(1.0), UI_OLD_BRONZE, false, 2.0)
var seal_rect := Rect2(board_rect.end - Vector2(58, 54), Vector2(34, 34))
draw_rect(seal_rect, Color(UI_SEAL_RED.r, UI_SEAL_RED.g, UI_SEAL_RED.b, 0.34))
draw_rect(seal_rect.grow(-5.0), Color(UI_SEAL_RED_DARK.r, UI_SEAL_RED_DARK.g, UI_SEAL_RED_DARK.b, 0.68), false, 2.0)
draw_line(seal_rect.position + Vector2(8, seal_rect.size.y * 0.5), seal_rect.end - Vector2(8, seal_rect.size.y * 0.5), Color(UI_OLD_BRONZE.r, UI_OLD_BRONZE.g, UI_OLD_BRONZE.b, 0.42), 1.2)
draw_line(seal_rect.position + Vector2(seal_rect.size.x * 0.5, 8), seal_rect.end - Vector2(seal_rect.size.x * 0.5, 8), Color(UI_OLD_BRONZE.r, UI_OLD_BRONZE.g, UI_OLD_BRONZE.b, 0.34), 1.2)
func _current_battle_background_texture() -> Texture2D:
@@ -2108,7 +2229,7 @@ func _terrain_fill_color(cell: Vector2i, terrain_key: String, has_background: bo
func _map_grid_color(has_background: bool) -> Color:
var color := GRID_COLOR
color.a = 0.23 if has_background else 0.52
color.a = 0.14 if has_background else 0.38
return color
@@ -4708,27 +4829,27 @@ func _format_briefing_objectives() -> String:
var text := ""
var victory := str(state.objectives.get("victory", ""))
if not victory.is_empty():
text = "승리 조서: %s" % victory
text = "승리 조서:\n %s" % victory
var defeat := str(state.objectives.get("defeat", ""))
if not defeat.is_empty():
if not text.is_empty():
text += "\n"
text += "패배 흉조: %s" % defeat
text += "패배 흉조:\n %s" % defeat
var progress_lines := state.get_objective_progress_lines(false, false)
if not progress_lines.is_empty():
if not text.is_empty():
text += "\n"
text += "전공 죽간: %s" % _join_strings(progress_lines, ", ")
text += "전공 죽간:\n %s" % _join_strings(progress_lines, ", ")
var risk_lines := state.get_defeat_progress_lines()
if not risk_lines.is_empty():
if not text.is_empty():
text += "\n"
text += "흉조 징후: %s" % _join_strings(risk_lines, ", ")
text += "흉조 징후:\n %s" % _join_strings(risk_lines, ", ")
var rewards_text := _format_briefing_rewards()
if not rewards_text.is_empty():
if not text.is_empty():
text += "\n"
text += "전리품 봉인: %s" % rewards_text
text += "전리품 봉인:\n %s" % rewards_text
return text