Refine opening story UI and button scaling

This commit is contained in:
2026-06-20 14:25:44 +09:00
parent 950158eaa0
commit 7f95f47d86
4 changed files with 277 additions and 119 deletions

View File

@@ -74,6 +74,15 @@ func _check_title_menu_start_load_and_settings(failures: Array[String]) -> void:
failures.append("title screen should show a high-resolution battlefield backdrop")
elif BattleSceneScript.TITLE_BACKGROUND_PATH == BattleSceneScript.DEFAULT_BATTLE_BACKGROUND_PATH:
failures.append("title screen should use a dedicated cinematic background, not the first battle map backdrop")
for button_spec in [
{"button": scene.top_settings_button, "context": "top settings"},
{"button": scene.end_turn_button, "context": "top end turn"},
{"button": scene.wait_button, "context": "HUD wait"},
{"button": scene.briefing_start_button, "context": "briefing start"}
]:
var sampled_button := button_spec["button"] as Button
if sampled_button != null:
_check_button_texture_slice_fit(failures, sampled_button, str(button_spec["context"]))
if scene.title_portrait_texture_rect == null or scene.title_portrait_texture_rect.texture == null:
failures.append("title screen should show Cao Cao portrait art")
elif scene.title_portrait_texture_rect.material == null or not bool(scene.title_portrait_texture_rect.material.get_meta("title_portrait_feather_material", false)):
@@ -236,36 +245,45 @@ func _check_title_menu_start_load_and_settings(failures: Array[String]) -> void:
if scene.opening_prologue_root != null:
opening_story_strip = scene.opening_prologue_root.find_child("OpeningStoryBeatStrip", true, false)
if opening_story_strip == null:
failures.append("opening prologue should show a generated four-beat story strip")
failures.append("opening prologue should show a compact four-beat story progress rail")
else:
var progress_caption := opening_story_strip.find_child("OpeningStoryProgressCaption", true, false) as Label
if progress_caption == null or progress_caption.text != "전개":
failures.append("opening story progress rail should use a subtle Korean caption instead of exposed numeric cards")
var opening_story_cards: Array = opening_story_strip.find_children("OpeningStoryBeatCard*", "", true, false)
if opening_story_cards.size() != 4:
failures.append("opening story strip should expose four generated story beats: %d" % opening_story_cards.size())
failures.append("opening story progress rail should expose four story knots: %d" % opening_story_cards.size())
var current_count := 0
var current_index := 0
for opening_story_card in opening_story_cards:
var card_node := opening_story_card as Node
var beat_frame := card_node.find_child("OpeningStoryBeatImageFrame", true, false) as PanelContainer
var beat_seal := card_node.find_child("OpeningStoryBeatSeal", true, false) as PanelContainer
var beat_image := card_node.find_child("OpeningStoryBeatImage", true, false) as TextureRect
var beat_label := card_node.find_child("OpeningStoryBeatLabel", true, false) as Label
if beat_frame == null or not bool(beat_frame.get_meta("generated_panel_texture", false)):
failures.append("opening story beat image should sit inside a generated frame")
var beat_thread := card_node.find_child("OpeningStoryBeatThread", true, false) as ColorRect
if not bool(card_node.get_meta("story_progress_knot", false)):
failures.append("opening story beat should be rendered as a compact progress knot")
if beat_seal == null or not bool(beat_seal.get_meta("generated_panel_texture", false)):
failures.append("opening story beat should use a generated seal number")
if beat_image == null or beat_image.texture == null:
failures.append("opening story beat card should load generated artwork")
elif beat_image.custom_minimum_size.x < 116.0:
failures.append("opening story beat artwork should stay readable in the strip: %s" % str(beat_image.custom_minimum_size))
if beat_label == null or beat_label.text.strip_edges().is_empty():
failures.append("opening story beat card should name its scene")
elif beat_label.get_theme_color("font_color").get_luminance() < 0.66 or beat_label.get_theme_constant("outline_size") < 3:
failures.append("opening story beat label should remain readable over generated artwork: %s" % beat_label.text)
failures.append("opening story beat should use a generated knot seal")
if beat_thread == null:
failures.append("opening story beat should join knots with a subdued thread")
var numeric_labels := card_node.find_children("*", "Label", true, false)
for numeric_label in numeric_labels:
if str((numeric_label as Label).text).strip_edges() in ["1", "2", "3", "4"]:
failures.append("opening story progress should not expose bare numeric labels")
if bool(card_node.get_meta("current_story_beat", false)):
current_count += 1
current_index = opening_story_cards.find(opening_story_card) + 1
if current_count != 1 or current_index != 1:
failures.append("opening story strip should highlight the first story beat on entry")
if opening_story_strip.custom_minimum_size.x > 360.0 or opening_story_strip.custom_minimum_size.y > 56.0:
failures.append("opening story progress rail should stay compact in the upper-right corner: %s" % str(opening_story_strip.custom_minimum_size))
if scene.opening_prologue_next_button == null or scene.opening_prologue_next_button.text != "이어 보기":
failures.append("opening prologue next button should read as a story action")
else:
_check_opening_story_button_art(failures, scene.opening_prologue_next_button, "opening next")
if scene.opening_prologue_skip_button == null or scene.opening_prologue_skip_button.text != "바로 군막":
failures.append("opening prologue skip button should read as a contextual camp shortcut")
else:
_check_opening_story_button_art(failures, scene.opening_prologue_skip_button, "opening skip")
if scene.opening_prologue_scene_texture_rect == null or scene.opening_prologue_scene_texture_rect.texture == null:
failures.append("opening prologue should show generated story artwork")
elif scene.opening_prologue_scene_texture_rect.custom_minimum_size.x <= scene.opening_prologue_scene_texture_rect.custom_minimum_size.y:
@@ -479,10 +497,48 @@ func _check_title_menu_button_art(failures: Array[String], button: Button, expec
failures.append("%s generated button texture should keep high-resolution source pixels: %dx%d" % [context, style.texture.get_width(), style.texture.get_height()])
if style.texture_margin_top > 24 or style.texture_margin_bottom > 24:
failures.append("%s generated button slice should stay shallow enough for the 720p title menu: %d/%d" % [context, style.texture_margin_top, style.texture_margin_bottom])
_check_button_texture_slice_fit(failures, button, context)
if str(button.tooltip_text).strip_edges().is_empty():
failures.append("%s should describe its command through a tooltip" % context)
func _check_opening_story_button_art(failures: Array[String], button: Button, context: String) -> void:
if button == null:
failures.append("%s button missing" % context)
return
if not bool(button.get_meta("opening_story_button", false)):
failures.append("%s should use the compact opening-story button profile" % context)
if button.expand_icon:
failures.append("%s icon should not stretch in QHD fullscreen" % context)
if button.get_theme_constant("icon_max_width") > 22:
failures.append("%s icon should stay small beside Korean text" % context)
var stylebox := button.get_theme_stylebox("normal")
if not (stylebox is StyleBoxTexture):
failures.append("%s should keep a generated button texture" % context)
return
_check_button_texture_slice_fit(failures, button, context)
if button.get_theme_font_size("font_size") > 17:
failures.append("%s should stay visually quiet in the story caption" % context)
func _check_button_texture_slice_fit(failures: Array[String], button: Button, context: String) -> void:
if button == null:
return
var stylebox := button.get_theme_stylebox("normal")
if not (stylebox is StyleBoxTexture):
return
var style := stylebox as StyleBoxTexture
var size := button.custom_minimum_size
if size.x <= 0.0 or size.y <= 0.0:
size = button.get_combined_minimum_size()
var max_x := maxi(1, int(floor(size.x * 0.5)) - 2)
var max_y := maxi(1, int(floor(size.y * 0.5)) - 2)
if style.texture_margin_left > max_x or style.texture_margin_right > max_x:
failures.append("%s generated button horizontal slices should fit the control width: margins %d/%d size %.1f" % [context, style.texture_margin_left, style.texture_margin_right, size.x])
if style.texture_margin_top > max_y or style.texture_margin_bottom > max_y:
failures.append("%s generated button vertical slices should fit the control height: margins %d/%d size %.1f" % [context, style.texture_margin_top, style.texture_margin_bottom, size.y])
func _check_title_command_fit(failures: Array[String], button: Button, context: String) -> void:
if button == null:
return