From 75b5e0a6172e909653712c5fe86be1b868b229d0 Mon Sep 17 00:00:00 2001 From: Wickedness Date: Fri, 19 Jun 2026 21:30:20 +0900 Subject: [PATCH] Make unit commands icon first --- scripts/scenes/battle_scene.gd | 51 ++++++++++++++++++++++++----- tools/smoke_visual_assets.gd | 60 +++++++++++++++++++++++++--------- 2 files changed, 86 insertions(+), 25 deletions(-) diff --git a/scripts/scenes/battle_scene.gd b/scripts/scenes/battle_scene.gd index 026726c..41ff37a 100644 --- a/scripts/scenes/battle_scene.gd +++ b/scripts/scenes/battle_scene.gd @@ -99,9 +99,9 @@ const SHOP_MERCHANT_BADGE_SIZE := Vector2(50, 50) const SHOP_ITEM_ICON_SIZE := Vector2(48, 48) const HUD_UNIT_PORTRAIT_SIZE := Vector2(92, 104) const HUD_UNIT_PORTRAIT_STACK_SIZE := Vector2(88, 100) -const HUD_COMMAND_GRID_SIZE := Vector2(420, 70) -const HUD_COMMAND_BUTTON_SIZE := Vector2(132, 30) -const HUD_COMMAND_GRID_COLUMNS := 2 +const HUD_COMMAND_GRID_SIZE := Vector2(420, 46) +const HUD_COMMAND_BUTTON_SIZE := Vector2(72, 42) +const HUD_COMMAND_GRID_COLUMNS := 4 const TOP_TOOL_BUTTON_SIZE := Vector2(42, 42) const POST_MOVE_MENU_SIZE := Vector2(240, 146) const POST_MOVE_TITLE_SIZE := Vector2(196, 22) @@ -795,12 +795,18 @@ func _suppress_local_command_tooltip(button: Button) -> void: button.tooltip_text = "" -func _configure_hud_command_button(button: Button) -> void: +func _configure_hud_command_button(button: Button, icon_kind: String = "") -> void: if button == null: return button.custom_minimum_size = HUD_COMMAND_BUTTON_SIZE button.size_flags_horizontal = Control.SIZE_EXPAND_FILL - button.add_theme_font_size_override("font_size", 13) + button.add_theme_font_size_override("font_size", 1) + if not icon_kind.is_empty(): + button.text = "" + button.icon = _make_toolbar_icon(icon_kind) + button.expand_icon = false + button.set_meta("icon_only", true) + button.set_meta("command_icon", icon_kind) func _configure_top_tool_button(button: Button, node_name: String, icon_kind: String, tooltip: String) -> void: @@ -868,6 +874,33 @@ func _make_toolbar_icon(kind: String) -> Texture2D: _icon_circle(image, Vector2i(16, 16), 10, red) _icon_line(image, Vector2i(16, 9), Vector2i(16, 23), ink, 3) _icon_line(image, Vector2i(9, 16), Vector2i(23, 16), ink, 3) + "wait": + _icon_rect(image, Rect2i(9, 9, 15, 17), shadow) + _icon_line(image, Vector2i(16, 7), Vector2i(24, 11), ink, 3) + _icon_line(image, Vector2i(24, 11), Vector2i(21, 24), ink, 3) + _icon_line(image, Vector2i(21, 24), Vector2i(11, 24), ink, 3) + _icon_line(image, Vector2i(11, 24), Vector2i(8, 11), ink, 3) + _icon_line(image, Vector2i(8, 11), Vector2i(16, 7), ink, 3) + _icon_line(image, Vector2i(12, 15), Vector2i(20, 15), red, 2) + "tactic": + _icon_rect(image, Rect2i(9, 8, 16, 18), shadow) + _icon_rect(image, Rect2i(8, 7, 16, 18), ink) + _icon_rect(image, Rect2i(11, 10, 10, 2), Color(0.16, 0.07, 0.03, 1.0)) + _icon_rect(image, Rect2i(11, 15, 10, 2), Color(0.16, 0.07, 0.03, 1.0)) + _icon_rect(image, Rect2i(11, 20, 7, 2), Color(0.16, 0.07, 0.03, 1.0)) + _icon_circle(image, Vector2i(24, 9), 3, red) + "item": + _icon_line(image, Vector2i(10, 13), Vector2i(22, 13), shadow, 5) + _icon_rect(image, Rect2i(9, 12, 15, 13), ink) + _icon_line(image, Vector2i(12, 12), Vector2i(16, 7), red, 3) + _icon_line(image, Vector2i(21, 12), Vector2i(16, 7), red, 3) + _icon_rect(image, Rect2i(12, 17, 9, 3), Color(0.16, 0.07, 0.03, 1.0)) + "equip": + _icon_line(image, Vector2i(9, 24), Vector2i(23, 10), shadow, 5) + _icon_line(image, Vector2i(9, 24), Vector2i(23, 10), ink, 3) + _icon_line(image, Vector2i(20, 7), Vector2i(25, 12), ink, 3) + _icon_line(image, Vector2i(10, 18), Vector2i(16, 24), red, 3) + _icon_line(image, Vector2i(7, 21), Vector2i(13, 27), red, 3) _: _icon_circle(image, Vector2i(16, 16), 7, ink) return ImageTexture.create_from_image(image) @@ -1589,25 +1622,25 @@ func _create_hud() -> void: wait_button = Button.new() wait_button.text = "대기" - _configure_hud_command_button(wait_button) + _configure_hud_command_button(wait_button, "wait") wait_button.pressed.connect(_on_wait_pressed) button_row.add_child(wait_button) tactic_button = Button.new() tactic_button.text = "책략" - _configure_hud_command_button(tactic_button) + _configure_hud_command_button(tactic_button, "tactic") tactic_button.pressed.connect(_on_tactic_pressed) button_row.add_child(tactic_button) item_button = Button.new() item_button.text = "도구" - _configure_hud_command_button(item_button) + _configure_hud_command_button(item_button, "item") item_button.pressed.connect(_on_item_pressed) button_row.add_child(item_button) equip_button = Button.new() equip_button.text = "병장" - _configure_hud_command_button(equip_button) + _configure_hud_command_button(equip_button, "equip") equip_button.pressed.connect(_on_equip_pressed) button_row.add_child(equip_button) diff --git a/tools/smoke_visual_assets.gd b/tools/smoke_visual_assets.gd index f66d63a..ae9cfca 100644 --- a/tools/smoke_visual_assets.gd +++ b/tools/smoke_visual_assets.gd @@ -3471,19 +3471,38 @@ func _check_hud_command_grid_layout(failures: Array[String]) -> void: failures.append("unit command grid should use %d columns, got %d" % [BattleSceneScript.HUD_COMMAND_GRID_COLUMNS, command_grid.columns]) if command_grid.custom_minimum_size.x < BattleSceneScript.HUD_COMMAND_GRID_SIZE.x or command_grid.custom_minimum_size.y < BattleSceneScript.HUD_COMMAND_GRID_SIZE.y: failures.append("unit command grid should reserve stable space: %s" % str(command_grid.custom_minimum_size)) - for button in [ - scene.wait_button, - scene.tactic_button, - scene.item_button, - scene.equip_button - ]: + var command_icon_expectations := [ + {"button": scene.wait_button, "icon": "wait"}, + {"button": scene.tactic_button, "icon": "tactic"}, + {"button": scene.item_button, "icon": "item"}, + {"button": scene.equip_button, "icon": "equip"} + ] + for expectation in command_icon_expectations: + var button: Button = expectation["button"] if button == null: failures.append("unit command button missing") continue if button.get_parent() != command_grid: failures.append("unit command button should stay in the side command grid: %s" % str(button.name)) if button.custom_minimum_size.x < BattleSceneScript.HUD_COMMAND_BUTTON_SIZE.x or button.custom_minimum_size.y < BattleSceneScript.HUD_COMMAND_BUTTON_SIZE.y: - failures.append("unit command button should reserve fixed Korean label space: %s" % str(button.custom_minimum_size)) + failures.append("unit command button should reserve fixed icon space: %s" % str(button.custom_minimum_size)) + if button.icon == null or str(button.get_meta("command_icon", "")) != str(expectation["icon"]): + failures.append("unit command button should carry an immediate visual icon: %s icon=%s meta=%s" % [button.text, str(button.icon), str(button.get_meta("command_icon", ""))]) + if not bool(button.get_meta("icon_only", false)) or button.text != "": + failures.append("unit command button should be icon-first without visible text: %s text=%s" % [str(button.name), button.text]) + if not scene.state.load_battle("res://data/scenarios/001_yellow_turbans.json"): + failures.append("could not load opening battle for command icon tooltip check") + else: + scene.battle_started = true + scene.briefing_panel.visible = false + scene.result_panel.visible = false + scene._update_hud() + for expectation in command_icon_expectations: + var button: Button = expectation["button"] + if button == null: + continue + if button.tooltip_text.strip_edges().is_empty(): + failures.append("unit command icon should expose its command through tooltip: %s" % str(button.name)) var top_toolbar := scene.end_turn_button.get_parent() as HBoxContainer if top_toolbar == null or top_toolbar.name != "TopToolBar": failures.append("global battle commands should move to the top icon toolbar") @@ -3515,6 +3534,15 @@ func _check_action_button_disabled_reasons(failures: Array[String]) -> void: scene.equip_button = Button.new() scene.end_turn_button = Button.new() scene.threat_button = Button.new() + for button in [ + scene.wait_button, + scene.tactic_button, + scene.item_button, + scene.equip_button, + scene.end_turn_button, + scene.threat_button + ]: + button.set_meta("icon_only", true) if not scene.state.load_battle("res://data/scenarios/001_yellow_turbans.json"): failures.append("could not load battle scene state for action button reasons") _free_action_button_test_scene(scene) @@ -3529,7 +3557,7 @@ func _check_action_button_disabled_reasons(failures: Array[String]) -> void: "remaining_phases": 2 }] scene._update_tactic_button(cao_cao) - if scene.tactic_button.text != "책략" or not scene.tactic_button.tooltip_text.contains("봉인됨") or not scene.tactic_button.tooltip_text.contains("책략"): + if scene.tactic_button.text != "" or not scene.tactic_button.tooltip_text.contains("봉인됨") or not scene.tactic_button.tooltip_text.contains("책략"): failures.append("sealed unit should explain disabled tactic button: %s | %s" % [scene.tactic_button.text, scene.tactic_button.tooltip_text]) cao_cao["status_effects"] = [] @@ -3538,36 +3566,36 @@ func _check_action_button_disabled_reasons(failures: Array[String]) -> void: scene._update_tactic_button(cao_cao) scene._update_item_button(cao_cao) scene._update_equip_button(cao_cao) - if scene.wait_button.text != "대기" or not scene.wait_button.tooltip_text.contains("이미 행동"): + if scene.wait_button.text != "" or not scene.wait_button.tooltip_text.contains("대기") or not scene.wait_button.tooltip_text.contains("이미 행동"): failures.append("acted unit hold button should keep short text and explain in tooltip: %s | %s" % [scene.wait_button.text, scene.wait_button.tooltip_text]) - if scene.tactic_button.text != "책략" or not scene.tactic_button.tooltip_text.contains("이미 행동"): + if scene.tactic_button.text != "" or not scene.tactic_button.tooltip_text.contains("책략") or not scene.tactic_button.tooltip_text.contains("이미 행동"): failures.append("acted unit stratagem button should keep short text and explain in tooltip: %s | %s" % [scene.tactic_button.text, scene.tactic_button.tooltip_text]) - if scene.item_button.text != "도구" or not scene.item_button.tooltip_text.contains("이미 행동"): + if scene.item_button.text != "" or not scene.item_button.tooltip_text.contains("도구") or not scene.item_button.tooltip_text.contains("이미 행동"): failures.append("acted unit supply button should keep short text and explain in tooltip: %s | %s" % [scene.item_button.text, scene.item_button.tooltip_text]) - if scene.equip_button.text != "병장" or not scene.equip_button.tooltip_text.contains("이미 행동"): + if scene.equip_button.text != "" or not scene.equip_button.tooltip_text.contains("병장") or not scene.equip_button.tooltip_text.contains("이미 행동"): failures.append("acted unit arms button should keep short text and explain in tooltip: %s | %s" % [scene.equip_button.text, scene.equip_button.tooltip_text]) cao_cao["acted"] = false cao_cao["moved"] = true scene._update_equip_button(cao_cao) - if scene.equip_button.text != "병장" or not scene.equip_button.tooltip_text.contains("행군 후") or not scene.equip_button.tooltip_text.contains("행군 전"): + if scene.equip_button.text != "" or not scene.equip_button.tooltip_text.contains("병장") or not scene.equip_button.tooltip_text.contains("행군 후") or not scene.equip_button.tooltip_text.contains("행군 전"): failures.append("moved unit should explain disabled equip button: %s | %s" % [scene.equip_button.text, scene.equip_button.tooltip_text]) cao_cao["moved"] = false scene.state.set_inventory_snapshot({}) scene._update_item_button(cao_cao) - if scene.item_button.text != "도구" or not scene.item_button.tooltip_text.contains("비어 있음") or not scene.item_button.tooltip_text.contains("도구"): + if scene.item_button.text != "" or not scene.item_button.tooltip_text.contains("비어 있음") or not scene.item_button.tooltip_text.contains("도구"): failures.append("empty inventory should explain disabled item button: %s | %s" % [scene.item_button.text, scene.item_button.tooltip_text]) scene.state.current_team = BattleState.TEAM_ENEMY scene._update_end_turn_button() - if scene.end_turn_button.text != "차례 종료" or not scene.end_turn_button.tooltip_text.contains("적군 차례") or not scene.end_turn_button.tooltip_text.contains("아군 군령"): + if scene.end_turn_button.text != "" or not scene.end_turn_button.tooltip_text.contains("차례 종료") or not scene.end_turn_button.tooltip_text.contains("적군 차례") or not scene.end_turn_button.tooltip_text.contains("아군 군령"): failures.append("enemy phase should explain disabled end turn button: %s | %s" % [scene.end_turn_button.text, scene.end_turn_button.tooltip_text]) scene.state.current_team = BattleState.TEAM_PLAYER scene.battle_started = false scene._update_threat_button() - if scene.threat_button.text != "적정" or not scene.threat_button.tooltip_text.contains("전장도 미개봉") or not scene.threat_button.tooltip_text.contains("전장도"): + if scene.threat_button.text != "" or not scene.threat_button.tooltip_text.contains("적정") or not scene.threat_button.tooltip_text.contains("전장도 미개봉") or not scene.threat_button.tooltip_text.contains("전장도"): failures.append("inactive battle should explain disabled threat button: %s | %s" % [scene.threat_button.text, scene.threat_button.tooltip_text]) _free_action_button_test_scene(scene)