From c1e4c69effd05d7560c9ff7a1d176e4f41cc6899 Mon Sep 17 00:00:00 2001 From: Wickedness Date: Sat, 20 Jun 2026 11:17:19 +0900 Subject: [PATCH] Fix title menu button fit --- scripts/scenes/battle_scene.gd | 29 +++++++++++++++++++++++++---- tools/smoke_title_menu.gd | 27 +++++++++++++++++++++++++-- 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/scripts/scenes/battle_scene.gd b/scripts/scenes/battle_scene.gd index b37b124..bcd1f01 100644 --- a/scripts/scenes/battle_scene.gd +++ b/scripts/scenes/battle_scene.gd @@ -161,6 +161,7 @@ const TITLE_STORY_PREVIEW_CARD_SIZE := Vector2(148, 90) const TITLE_STORY_PREVIEW_IMAGE_FRAME_SIZE := Vector2(140, 74) const TITLE_STORY_PREVIEW_IMAGE_SIZE := Vector2(132, 66) const TITLE_STORY_PREVIEW_LABEL_SIZE := Vector2(140, 16) +const TITLE_MENU_ICON_MAX_WIDTH := 42 const OPENING_STORY_BEAT_CARD_SIZE := Vector2(136, 74) const OPENING_STORY_BEAT_IMAGE_FRAME_SIZE := Vector2(126, 46) const OPENING_STORY_BEAT_IMAGE_SIZE := Vector2(124, 38) @@ -1266,8 +1267,9 @@ func _configure_title_menu_button(button: Button, node_name: String, icon_kind: button.text = label button.tooltip_text = tooltip button.custom_minimum_size = minimum_size - button.icon = _make_toolbar_icon(icon_kind) + button.icon = _make_title_menu_icon(icon_kind) button.expand_icon = false + button.add_theme_constant_override("icon_max_width", TITLE_MENU_ICON_MAX_WIDTH) button.icon_alignment = HORIZONTAL_ALIGNMENT_LEFT button.vertical_icon_alignment = VERTICAL_ALIGNMENT_CENTER button.alignment = HORIZONTAL_ALIGNMENT_CENTER @@ -2045,6 +2047,25 @@ func _make_toolbar_icon(kind: String) -> Texture2D: return ImageTexture.create_from_image(image) +func _make_title_menu_icon(kind: String) -> Texture2D: + return _make_resized_icon_texture(_make_toolbar_icon(kind), TITLE_MENU_ICON_MAX_WIDTH) + + +func _make_resized_icon_texture(texture: Texture2D, max_width: int) -> Texture2D: + if texture == null or max_width <= 0: + return texture + var width := texture.get_width() + var height := texture.get_height() + if width <= max_width: + return texture + var image: Image = texture.get_image() + if image == null: + return texture + var resized_height: int = maxi(1, int(round(float(height) * float(max_width) / float(width)))) + image.resize(max_width, resized_height, Image.INTERPOLATE_LANCZOS) + return ImageTexture.create_from_image(image) + + func _load_toolbar_icon_texture(kind: String) -> Texture2D: var normalized_kind := kind.strip_edges().to_lower() if normalized_kind.is_empty(): @@ -4333,9 +4354,9 @@ func _create_hud() -> void: var title_portrait_shadow := ColorRect.new() title_portrait_shadow.name = "TitlePortraitLacquerField" - title_portrait_shadow.position = Vector2(646, 34) - title_portrait_shadow.size = Vector2(512, 628) - title_portrait_shadow.color = Color(0.045, 0.018, 0.010, 0.56) + title_portrait_shadow.position = Vector2(686, 72) + title_portrait_shadow.size = Vector2(420, 556) + title_portrait_shadow.color = Color(0.10, 0.060, 0.035, 0.10) title_portrait_shadow.mouse_filter = Control.MOUSE_FILTER_IGNORE title_screen_root.add_child(title_portrait_shadow) diff --git a/tools/smoke_title_menu.gd b/tools/smoke_title_menu.gd index e48b8e8..9f3a26f 100644 --- a/tools/smoke_title_menu.gd +++ b/tools/smoke_title_menu.gd @@ -76,6 +76,11 @@ func _check_title_menu_start_load_and_settings(failures: Array[String]) -> void: failures.append("title screen should use a dedicated cinematic background, not the first battle map backdrop") 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") + var portrait_shadow := scene.title_screen_root.find_child("TitlePortraitLacquerField", true, false) as ColorRect if scene.title_screen_root != null else null + if portrait_shadow == null: + failures.append("title screen should keep a subtle portrait grounding field") + elif portrait_shadow.color.a > 0.18: + failures.append("title portrait grounding field should not read as a black rectangle: %.2f alpha" % portrait_shadow.color.a) if scene.title_panel == null or scene.title_panel.position.x > 100.0: failures.append("title menu panel should sit on the left side of the cinematic title screen") elif scene.title_portrait_texture_rect != null and scene.title_panel.position.x + scene.title_panel.size.x >= scene.title_portrait_texture_rect.position.x: @@ -112,6 +117,7 @@ func _check_title_menu_start_load_and_settings(failures: Array[String]) -> void: failures.append("title start command should be visible on first screen") if scene.title_start_button.custom_minimum_size.y < 54.0: failures.append("title start command should be tall enough to read clearly") + _check_title_command_fit(failures, scene.title_start_button, "title start") _check_title_menu_button_art(failures, scene.title_start_button, "new", "title start") if scene.title_load_button == null or scene.title_load_button.text != "로드하기": failures.append("title screen should expose `로드하기`") @@ -122,6 +128,7 @@ func _check_title_menu_start_load_and_settings(failures: Array[String]) -> void: failures.append("title load command should be visible on first screen") if scene.title_load_button.custom_minimum_size.y < 54.0: failures.append("title load command should be tall enough to read clearly") + _check_title_command_fit(failures, scene.title_load_button, "title load") _check_title_menu_button_art(failures, scene.title_load_button, "load", "title load") if scene.title_load_panel == null: failures.append("title screen should create a load-slot selection panel") @@ -134,6 +141,7 @@ func _check_title_menu_start_load_and_settings(failures: Array[String]) -> void: failures.append("title settings command should be visible on first screen") if scene.title_settings_button.custom_minimum_size.y < 54.0: failures.append("title settings command should be tall enough to read clearly") + _check_title_command_fit(failures, scene.title_settings_button, "title settings") _check_title_menu_button_art(failures, scene.title_settings_button, "settings", "title settings") if scene.title_settings_back_button != null and scene.title_settings_back_button.visible: failures.append("title settings back command should stay hidden until settings are open") @@ -379,8 +387,8 @@ func _check_title_menu_button_art(failures: Array[String], button: Button, expec failures.append("%s should keep command icon metadata `%s`, got `%s`" % [context, expected_icon, str(button.get_meta("command_icon", ""))]) if button.icon == null: failures.append("%s should expose generated icon art" % context) - elif button.icon.get_width() < 128 or button.icon.get_height() < 128: - failures.append("%s should use high-resolution generated icon art, got %dx%d" % [context, button.icon.get_width(), button.icon.get_height()]) + elif button.icon.get_width() > BattleSceneScript.TITLE_MENU_ICON_MAX_WIDTH or button.icon.get_height() > BattleSceneScript.TITLE_MENU_ICON_MAX_WIDTH: + failures.append("%s icon should render at title-menu size, got %dx%d" % [context, button.icon.get_width(), button.icon.get_height()]) var stylebox := button.get_theme_stylebox("normal") if not (stylebox is StyleBoxTexture): failures.append("%s should use a generated button texture surface" % context) @@ -394,6 +402,21 @@ func _check_title_menu_button_art(failures: Array[String], button: Button, expec failures.append("%s should describe its command through a tooltip" % context) +func _check_title_command_fit(failures: Array[String], button: Button, context: String) -> void: + if button == null: + return + if button.expand_icon: + failures.append("%s icon should not expand into an oversized title command" % context) + var icon_limit := button.get_theme_constant("icon_max_width") + if icon_limit <= 0 or icon_limit > BattleSceneScript.TITLE_MENU_ICON_MAX_WIDTH: + failures.append("%s icon should be capped at title-menu size, got %d" % [context, icon_limit]) + var combined := button.get_combined_minimum_size() + if combined.y > 76.0: + failures.append("%s combined height should fit inside the title menu, got %.1f" % [context, combined.y]) + if combined.x > 420.0: + failures.append("%s combined width should fit inside the title menu, got %.1f" % [context, combined.x]) + + func _check_bgm_stream_quality(failures: Array[String], stream: AudioStream, label: String, minimum_length: float) -> void: if stream == null: failures.append("%s BGM stream should load before playback" % label)