Instruction file imported from JeflyMarte/crownfall (
.cursor/rules/ui-layout.mdc). Copyright stays with the author.
UI レイアウト・モック寄せ
モック参照の正
| 用途 | 参照 |
|---|---|
| 画面分割・情報構造 | docs/art/reference/UI_Reference_002.png |
| 色・装飾・密度 | docs/art/reference/UI_Reference_003_*.png |
| 解像度 | 720×1280(project.godot) |
| ギャップ整理 | docs/project/Proposal/OD-UI-001_Gap_Analysis_v1.0.md |
モック寄せの曖昧依頼 — 実装前に必ず確認
次のような依頼を受けたら、コード変更前にオーナーへ確認する:
- 「モック通りに」「モック画面の通りに」「003 に寄せて」「レイアウトを合わせて」等、領域分解・段階・テンプレートが未指定の UI 依頼
確認内容(簡潔でよい):
- 対象画面・参照モック(例:
003_04_Equipment) - 採用方針: Container 構造寄せ(絶対座標配置はしない)
- テンプレート既存シーン(例:
EquipmentScene) - 今回のスコープ(例: 骨格のみ / chrome 差し替え / 1 領域だけ)
- GO または修正指示の待ち
GO まで実装しない。
レイアウト原則(Godot 4)
- Container の子に anchor / offset を手動設定しない(親が上書きする)
- 余白 →
MarginContainerまたはControlSpacer のcustom_minimum_size - 間隔 →
separationは 4 の倍数(4, 8, 12, 16, 24…) - 伸縮 →
size_flags_horizontal/vertical(EXPAND_FILL等) - HBox 内の短い数値 Label に
clip_text=trueを付けない(最小幅 0 で数値が消える。アイコン+数値チップで再発済み) - 極限特殊制約の右上は FieldLegend(天候/フロア効果)流用。
hud_label≤13字(天候最長14字未満)。Featured のdescをそのまま載せない。ICO はextreme:legend - HBox 内のタイトル Label に
AUTOWRAP+SIZE_SHRINK_*を付けない(Autowrap Label の min幅≈0 → 幅が潰れて1文字ずつ縦折れ。MAX★付き装備名で再発済み)。タイトルはAUTOWRAP_OFF+名前/★ともSHRINK_BEGIN(★を名前+Lvの直後に置く。名前をEXPAND_FILLにすると★が行末へ飛ぶ)(EquipmentItemDetailHelper._add_item_title) - MAX★付きタイトルの名前 Label に
clip_text=trueを付けない(SHRINK_BEGIN+clip_textは最小幅≈0で名前全体が消える。★だけ残る/空行になる)。名前はclip_text=false+OVERRUN_NO_TRIMMING。省略が必要ならEXPAND_FILL(その場合★は行末へ飛ぶトレードオフ) - 日本語の長い Label に
AUTOWRAP_WORD_SMARTだけを頼らない(空白無し1語扱いで最小幅=全文幅 → 画面が横に広がる。Featured/カード説明はAUTOWRAP_ARBITRARY+EXPAND_FILL+custom_minimum_size.x=0。横伸び対策で中央アンカータイトルにclip_textを付けない — 名前が消える) - 画面下端の FooterPanel 情報欄も同じ(長いイベント要約で横拡大→左欠け/MainColumn に重なる)。
clip_contents+min.x=0+ellipsis、表示時は MainColumnoffset_bottomを Footer 実高で再計算(DungeonSelectScene._sync_list_footer_stack) - 戦闘下パーティカードは4枚均等幅。名前 Label を
clip_text=false/OVERRUN_NO_TRIMMINGにしない(最小幅=全文幅でカード不揃い+画面横伸び)。EXPAND_FILL+stretch_ratio=1+clip_contents、名前は font 縮小のあと ellipsis(DungeonScene._fit_party_card_name_font) - 縦リストの
ScrollContainer.horizontal_scroll_mode=DISABLED禁止(子の最小幅に追従して親まで横拡大する。SHOW_NEVER+clip_contents) - バナー重ねタイトルは
PRESET_CENTER+PRESET_MODE_MINSIZE+clip_text=false。親clip_contents禁止(size 0/クリップで文字消滅) - 絶対座標は オーバーレイ・ポップアップ程度に限定
.tscn手編集はscenes.mdcに従い最小限。配置微調整は Godot エディタ推奨
実装パターン(Crownfall)
- 既存
*UiTokens/*UiHelper/CombatUiFramesを踏襲 - 新規 chrome は Tokens にパス集約。magic number の色・spacing を直書きしない
- 画面は領域単位で分解:
Header/Content/Footer(BottomNav)等 - 1 Task = 1 画面の 1〜2 領域まで。全面を一度にやらない
- 装備セルのアイコン余白は
EquipmentUiTokens.ICON_FRAME_MARGIN_PX(18)。全面キャンバス絵で枠食い込みを再発させない - 弓は
BOW_ICON_INSET_SCALE(0.55)で inset 縮小。レア弓とshadowcordはBOW_ICON_INSET_SCALE_LARGE(0.30)+余白クロップを強め(needs_large_bow_icon)。鍛冶リストでは弓 inset 縮小を使わない - ホームのイベントバナー等は 左メニューと重ねない(メニュー下端+余白)
- 黒マット付き装飾枠を
StyleBoxTexture9-slice しない(角/帯に黒が伸び、金枠だけ短く見える)。書籍・展示室総合戦力はTextureRect直置き - 展示室の焼込名札枠は自慢キャラ未設定時も BG に残る。空状態では
NAME_FRAME_MASKで覆い、展示中だけ名札/補完線を出す(ShowcaseScene._set_stage_visible) - 展示室スキル箱はステ右カラムの細幅(
SKILLS_RECT幅≦ステ)。PanelContainer禁止(子で再膨張)。高さは内容フィット。スキル名は1行+fit_skill_name_font_size(折り返し禁止)
拠点 Hub × セーフエリア(再発防止・必須)
Mac では 既定で simulate OFF。実機だけ apply_chrome_safe_area が動く。既往の詳細カタログは known-pitfalls.mdc(按需)のポインタ行。
❌ BAD
- Mac で
simulate_mobile_safe_area=trueのまま TopBar/左メニューを動的に下げる - デスクトップで
top_inset()をshould_apply_chrome()なしに Intro 等へ足す(stretch 換算で巨大 inset → 「はじまり/スキップ」が画面中央へ) - 全画面の
BottomNavHelper.setupで無条件に chrome を当て、招待状の下ナビを潰す LeftMenuPanel高さを Scroll 子のsize.yで決める- letterbox(
aspect=keep)で inset=0 なのに 54/24 等の強制フォールバック - Header だけ inset して本文/MainColumn を旧位置のまま残す(ノッチ食い込み・白紙)
HubLayoutHelperからSafeAreaHelperを class_name 直参照のみ(-sで未解決)→ preload
✅ GOOD
- Mac: シーン設計座標を尊重(隊長バー top≈0、左メニュー top≈96)
- 実機:
SafeAreaHelper.should_apply_chrome()が true のときだけ chrome - 実機 Hub:
layout_hub_home_contentで左メニューを TopBar に追従、日課・通貨は HubView 下端アンカー DisplayServerセーフ矩形をget_final_transformで換算+iOS 最低 inset- ルート Header と上端アンカー本文を 同じ top で下降
- 検証:
tools/verify_base_hub.gd
❌ BAD(実機)
- TopBar だけ
offset_top = insetして LeftMenu を設計 Y のまま残す → 隊長名と重なる - 日課を絶対 Y(例: 956)のまま、BottomNav だけ Home Indicator 分高くする → 日課がナビに侵食
project.godotに日本語コメントをキーへ混ぜる(aspect / simulate が未設定になる)
ScrollTouch(再発防止・必須)
タッチ縦スクロールとタップ競合。ScrollTouchHelper.enable 後の再生成を忘れると同症状が画面横断で再発する。
❌ BAD
- Scroll 内の Button/STOP コントロールがドラッグを吸収したまま(
enable未適用) _rebuild_*/ BottomNav 後に Button を再生成して STOP のまま放置call_deferredに 型付きScrollContainer/Nodeを渡す(Godot 4.6 でCannot convert argument 1 from Object to Object→ GUT Unexpected Errors/実機ログ)。instance_id: int経由で_refresh_once_by_idするScrollTouchHelperが全RichTextLabelを STOP 化 → 章カード名の親 Button タップ不能/リンク以外の RTL がドラッグ奪取- ScrollTouch で Button を PASS 化したあと
pressedだけに依存(詳細が変わらない) - 入れ子 Scroll(Tab+内側 InventoryScroll 等)で両方 enable して重い/効かない
✅ GOOD
_ready・一覧 rebuild・BottomNavHelper.setupの 直後にScrollTouchHelper.enable(scroll)- 内側リストが不要なら
enable(outer, false)や所持を 非 Scroll(自然高)にする - 状態異常リンク RTL だけ
_cf_keep_mouse_stop+STOP(StatusEffectLinkHelper)。IGNORE の RTL はそのまま - Catalog/装備セルは
gui_input短押し(PASS+deadzone)。選択はハイライト差替のみ(全セル rebuild 禁止) - オーバーレイ行ボタンは ScrollTouch 後に
MOUSE_FILTER_STOPを復元(鍛冶素材一覧) - 鍛冶主ボタン(炉研ぎ/焼直し/一括分解)は
_cf_keep_mouse_stop+_restore_primary_button_input(詳細 rebuild 後も deferred で再適用)。焼直し効果行も同 meta - パーティ「詳細」は
_cf_keep_mouse_stop(ScrollTouchHelperが BaseButton でも meta を見て STOP 維持) - ダンジョン選択の Biome バナー/章カードは
PASS+gui_input短押し(畳み一覧が全面 STOP だとスクロール不能)。タブ/選択/入場確認だけ_cf_keep_mouse_stop - 図鑑のエントリ一覧も同型(フル幅 STOP 禁止)。タブだけ
_mark_codex_tab_stop。_rebuild_entry_list後にScrollTouchHelper.enable(EntryListScroll) - 焼直し効果 Button の
pressedから詳細を即 rebuild しない(freeで発信元破棄→Abort)。call_deferred("_refresh_selection")
装備セルサイズ(再発防止・必須)
キャラ切替や再レイアウトで 装備アイコンが拡大する 事故が繰り返し発生している。
❌ BAD
- スロット/所持セルを
EXPAND_FILLの Grid に載せ、custom_minimum_sizeだけ指定して伸びるままにする _rebuild_*(キャラ切替)のたびにパネル幅からcell_pxを再計算してセルを大きくするSlotsRow.size_flags_horizontal = EXPAND_FILLのまま子ボタンを可変幅にする
✅ GOOD
- 装備スロットは
EquipmentUiTokens.SLOT_PX固定 - 所持セルも
EquipmentUiTokens.INV_CELL_PX固定(幅追従のmaxi(INV_CELL_PX, cell_w)で肥大化させない) - ボタンは
custom_minimum_size+SIZE_SHRINK_CENTER。親SlotsPanel/EquipSlotsGridもSIZE_SHRINK_*(EXPAND_FILL禁止) custom_maximum_sizeは使わない(Godot 4.6.3 に存在せず、参照するとキャラ管理が即クラッシュ)- 弓など枠を埋めやすい武器アートは取込時
SAFE_SCALEを下げて余白を確保(職固有バグと誤認しやすい) - 所持一覧の幅連動再計算は不要(セル固定)。リサイズでも
INV_CELL_PXを維持 - カテゴリ Chip の TextureRect は縦横とも
SIZE_SHRINK_CENTER。ICO_Equip_Cat_*は他と同尺(目安 96)。巨大原画をそのまま載せない EffectsRule(SectionRule)はSTRETCH_SCALE+縦SHRINK。KEEP_ASPECT_COVEREDは縦伸び時に金の縦筋になる- 所持 Grid は Scroll 内で縦 EXPAND 禁止(
SIZE_SHRINK_BEGIN)。行がビューポート高さまで伸びると InvCell の StyleBox 左右辺が巨大な金の縦筋になる - セル Button は
clip_contents = true - 装備スロット Grid / SlotsPanel も横縦とも
SIZE_SHRINK_*(長い職名で CardRow が再配分されてもスロットを伸ばさない) - CharacterCard の最小幅が viewport(720) を超えないこと(
◀▶肥大化・職名横伸び・OwnerBadge 原寸化に注意) - InventoryHeader(おすすめ/ソート等)の最小幅合計も 720 超禁止。長いボタン文言は短縮+
tooltip。Label にclip_textだけ+SHRINKは幅0化で消える - **EffectsGrid(装備中の効果)**も 4 列のラベル全文幅で 720 超→右見切れする。ラベルは StatsGrid と同短表記(会心率/会心ダメ/速度)。行は
EXPAND_FILL+min.x=0+ellipsis。王痕導線ボタンも短縮+tooltip。数値 Label にclip_textを付けない(min 幅≈0 で数字が消える) VBoxContainer/BottomNavはgrow_horizontal = GROW_DIRECTION_END(BOTHだと min 超過時に左右膨張→タブ〜一覧が左欠け)- 下ナビ Button の
custom_minimum_size.xをVIEWPORT/件数固定にしない(Panel の左右 margin 込みで 720 超え→同様に左欠け)。高さ固定+EXPAND_FILL - 各 Tab の ScrollContainer は横スクロール禁止+
clip_contents - スキル行の装備/解除は右端固定幅+本文
EXPAND_FILL+min.x=0+ellipsis。行/枠はclip_contents=false(本文だけ clip)。右content_marginでボタンを内側へ。名を横1行全文幅にするとボタンが見切れる - 画面 BG(
BgTexture)はKEEP_ASPECT_COVERED。CENTEREDにするとレターボックスで背景が消えたように見える
鍛冶屋アイコン(再発防止・必須)
錬成/分解で 左リストの装備アイコンが左に欠ける/右詳細が右にはみ出す 事故が繰り返し発生。
❌ BAD
PanelContainer+rarity_slot_styleの content_margin と「子=セル同サイズ」を同居させる- 完了ポップのレアロゴを
PanelContainer直下にadd_child(N/R/E・Legend がセル全面に伸長) - 説明文を日本語+
AUTOWRAP_WORD_SMARTのまま狭い完了枠へ(最小幅=全文幅ではみ出す) - 鍛冶セルで
BOW_ICON_INSET_SCALE(inset 縮小)を使い、描画辺が InvCell 9-slice 内側を超える - リスト名を
clip_text=false/OVERRUN_NO_TRIMMINGのまま狭いLeftScrollに入れる(行最小幅が溢れ、左アイコンが欠ける) - 下帯非表示なのに BodyScroll を enable/縦 AUTO のままにする(左リストが途中でスクロール不能)
LeftList.clip_contents=true(Scroll 内 VBox で切ると下の行が見えない)- アイコンに中央アンカー+負 offset(親幅0時に左へはみ出す)
- リスト小セル(≲88px)に InvCell 9-slice を使い、左枠が潰れて欠けて見える
- ヒーロー台座/武器枠が詳細ペイン幅より大きい
✅ GOOD(BlacksmithUiHelper.make_item_icon_cell)
- ルートは 固定 px の Button(
PanelContainer禁止)+clip_contents+SIZE_SHRINK_BEGIN - StyleBox の content_margin は 0。アイコンは FULL_RECT+対称 inset(負の中央 offset 禁止)
- リスト小セルは Flat 四辺ボーダー。大セル(ストリップ)のみ InvCell テクスチャ
- アイコン辺は
forge_icon_side_px=min(cell-2*inset, cell*FORGE_ICON_SAFE_FILL)(≤0.52) - 鍛冶リストでは 弓 inset 縮小を使わない
- リスト名は
clip_text+ellipsis+EXPAND_FILL(_apply_list_name_label) LeftScrollは横SHOW_NEVER+clip_contents(DISABLED禁止)。カードもclip_contents- 下帯オミット時は BodyScroll 縦スクロールを切る(外枠がドラッグを奪い、錬成リストが Lv3 付近で止まる)。左一覧は
LeftList.clip_contents=false+SHRINK_BEGIN - 左一覧カードは押し下げ即選択禁止(仮想錬成でスクロールが鈍る)。PASS+短押し(移動キャンセル)。装備/DG選択と同型
- 下帯オミット時は MainSplit を BodyScroll から外して直置き(アンカーで高さ拘束)。配下のままだと長い錬成一覧で LeftScroll が死ぬ
- ヒーローはスタック内に収まるサイズ+
clip_contents - 生産/強化/錬成/分解のリストは同じ
_make_selectable_list_iconを使う - カテゴリ Chip の TextureRect は縦横とも
SIZE_SHRINK_CENTER+固定 px(~40) - 完了ポップの枠アイコンは外側
Controlにレアロゴ。badge_ref_px=INV_CELL_PX。説明はAUTOWRAP_ARBITRARY+短縮 - 限界突破結果ポップも同じ: 効果
RichTextLabelはAUTOWRAP_ARBITRARY+min.x=0+EXPAND_FILL。Scroll 横はSHOW_NEVER+clip_contents(DISABLED+WORD_SMARTだと日本語が横はみ出し)
PanelContainer 上の角バッジ(再発防止)
PanelContainer は 全子ノードを同じ content 矩形に敷く。角バッジを直の子にすると、バッジの塗りがカード全面になる。
❌ BAD
_player_card.add_child(gift_badge)(配布未受取で隊長カード全体が赤くなる)- reparent 後も
$PlayerCard/PlayerRow/...のパス文字列でget_node(ランクアップ閉じで null 参照→デバッガ終了)
✅ GOOD
- バッジは氏名行
HBoxの名前直後(BaseScene._setup_gift_badge)。PlayerCard(PanelContainer)直下に置かない - ノードを reparent する場合は
@onready参照を使い、パス文字列に依存しない
CHR Idle ポートレート(再発防止・必須)
assets/characters/{job|helper_*|pet_*}/idle_*.png は UI 正面 Idle(ガチャ Featured/MVP/キャラ画面)。
戦闘 SpriteFrames の idle(=walk・背面歩行)とは別系統。混ぜない。
❌ BAD
- Idle 有無を
FileAccess/Image.load_from_fileだけに依存 → iOS 等エクスポートで Idle 空(PNG 原寸未梱包)→ walk/顔アイコンへフォールバック - UI 欠落時に
walk_*.pngをドット代替にする(背面歩行に見える) - 不安定 Idle をそのままループ → 拡縮に見える
- 全フレームを「キャンバス中央寄せ」で再配置 → 左右に跳ぶ
- 応急で静止画だけにして放置(その場アニメができなくなる)
- 軽微な高さ揺れ(~1.08)までフル再配置して横跳びを再発させる
✅ GOOD(ChrIdlePortrait)
- フレーム検出・読込は
ResourceLoader優先(エクスポートで.ctexを使う)。FileAccess/PNG 直読みは未インポート時の補助のみ - 新規 Idle PNG 追加後は Godot 再インポート/iOS 再エクスポートまでセット(
.import無しのまま実機確認しない) - 高さ比がほぼ安定 → 元テクスチャのまま
- 軽微(目安 max/min が 1.12 未満)→ 縮んだフレームを 間引き(元配置を壊さない)
- 重度(ビーストテイマー級)→ 縦は足元・横は内容中心で正規化(横を足元合わせにすると胴体スライド)
- 重度職の PNG は
tools/bake_chr_idle_stabilize.gdで焼き、実機でもソースが安定 get_image失敗時のみ素通し(モバイル一律スキップは拡縮を再発させるので禁止)- UI では「その場で動く」を維持する。静止固定は最終手段
✅ GOOD(ChrIdlePortraitView)
_ready前にset_from_entry/set_from_memberされ得る(MVP 表彰台など)- 子
TextureRect/Labelは_ensure_nodes()で遅延生成し、Nil へ texture 代入しない has_idle_texture()は Idle フレーム配列の有無(アイコン載せて true にしない)- Idle 欠落時の最終手段は職アイコン。walk 禁止
❌ BAD(ChrIdlePortraitView)
_readyでのみ子を作り、呼び出し側がツリー投入前に texture を載せる想定にする → MVP 即落ち- Featured/MVP/キャラで walk フォールバックを復活させる
編成 CHR 顔アイコン(再発防止・必須)
ICO_CHR_* / ART_HELPER_* は ~1254px。編成グリッドで選択のたびにセル/アイコンが巨大化する事故が再発しやすい。
❌ BAD
- 選択用 StyleBox だけ
content_margin/border_widthを大きくする → Grid の最小サイズが膨らみ「拡大した」ように見える TextureRect(CHR)を Button の子に置く → 押下・min size 伝播で原寸逃げEXPAND_IGNORE_SIZE無し/ホスト無しでテクスチャ直置き- セルを
EXPAND_FILLのまま肖像 min を拘束しない
✅ GOOD(RosterUiHelper.make_clamped_portrait / pick_panel_style)
- 選択ハイライトは 色だけ変える(margin・border 幅は
card_panel_styleと同一) - 肖像は固定辺+
SIZE_SHRINK_*+clip_contents。絶対キャップPORTRAIT_PX_HARD_MAX(resizedでset_sizeしない) - タップ用 Button は 子なしオーバーレイ(肖像の外)
- グリッド再構築は
remove_child即時+queue_free(ツリーから外して拡大連鎖を防ぎ、free()は信号中 Abort の原因なので禁止) - 入れ替え/選択の rebuild は
call_deferred(pressed/gui_input中に当該ノードを破棄しない) MainVBox.custom_minimum_size.xに content 幅を書き戻さない(循環拡大)NOTIFICATION_RESIZEDは幅が実質変わったときだけカード再生成- 回帰:
tests/unit/test_roster_portrait_clamp.gd
編成・陣形(再発防止・必須)
パーティ選択・陣形オーバーレイ・調査派遣の競合。見た目だけ正しく本反映が壊れる事故が再発しやすい。
❌ BAD
- 陣形オーバーレイ操作のたび
_apply_formation_rows_from_slotsで GameState 即書き(オーバーレイ中は確定まで待つ) - Dim(外側)タップを確定扱い/スナップショット復元しない
- 空き枠を
party_members[i]で埋めて同一メンバーを複数スロットに入れる _sync_formation_slots_from_selectionが空き前列を詰めて後列指定を前列化する- おすすめ/リセットが全 roster から選ぶ(調査派遣中を含む)
- 詳細遷移だけをトリガに
set_active_partyする(閲覧遷移と編成確定を混ぜる) - 復元時に派遣中メンバーを無理に
set_active_partyして失敗 - フッター「保存」必須の下書き運用に戻す(編成変更は即確定が正)
- Toolbar(おすすめ/陣形)を MainScroll 先頭だけに置き Header 金線に食い込ませる
- パーティカード「詳細」を ScrollTouch PASS のまま
pressedだけに頼る(押しても無反応)
✅ GOOD
- メンバー入れ替え・おすすめ・陣形確定は
_commit_active_partyで 即 GameState+セーブ(フッター「保存」は置かない) - フッター「パーティ保存/一覧」はプリセット用として残す
- 陣形オーバーレイ中だけスロット下書き。Dim=キャンセル(スナップショット復元)。確定=
_commit_active_party - 空きは未配置メンバーから埋める+スロット重複除去。sync は空きスロット保持
- 後衛プリセットは後ろ最大2を後列(前列空可)
- 候補は
_eligible_roster_for_party()(派遣中除外)。派遣中は選択不可+「調査中」 - 失敗理由は
active_party_reject_reasonで出し分ける - 詳細は
equipment_focus_member_id+遷移のみ。Button に_cf_keep_mouse_stop - 復元は派遣中スキップ+フォールバックも除外
- タブは Header 直下の固定
ToolbarBand。ステ表示はRosterUiHelper.compute_member_stats+AffixStatCalculator.get_bonuses_for_member
Biome/イベントバナー(再発防止・必須)
ダンジョン選択・解放ポップのバナー名消滅/横伸び/Biome 取り違え。
❌ BAD
- タイトルを
FULL_RECT埋め込み/clip_text/親clip_contents/PRESET_CENTERのみで size 0 display_name.length()>=12などで一部 Biome だけ SMALL 化ScrollContainer.horizontal_scroll_mode=DISABLED(子最小幅に追従して横拡大)- Featured 日本語を
AUTOWRAP_WORD_SMARTのみ(空白無し1語=全文幅) - バナー高さを
host.size.x/resized同期で毎回変える - イベントDGを
SUB_BANNER_FALLBACKの mourngate 流用のみ/枠なし全高キーアート - Featured 上段を「一覧にバナーがあるから」と非表示にする
- 解放ポップ名を VBox 下段配置+次解放フォールバックを whisperwood 固定
- CLEAR をイベントバナー見出しにインライン連結(征討/降臨の直後)。メイン章行と位置がズレる
- CLEAR をダンジョンバナー(Featured/一覧見出し)に載せる。章行と二重表示になる
✅ GOOD
- タイトルは
PRESET_CENTER+PRESET_MODE_MINSIZE+clip_text=false。自然サイズ+中央寄せ BiomeBannerHelper.title_font_sizeで幅フィット。深層のみ初段 SMALL- Scroll は
SHOW_NEVER。Featured Label はEXPAND_FILL+AUTOWRAP_ARBITRARY+min.x=0 - バナー高さはデザイン幅680固定(実幅同期禁止)
- 各イベントに
BAN_DG_*+BIOME_BANNER_PATHS。generate_biome_banner.py --strip-height 232(枠既定 ON) - Featured でもバナー表示。
_sync_featured_bannerもdisplay_name中央重ね - 解放名はバナー内中央重ね。次解放は
ContentUnlockNotice.next_unlock_after_main_clear - ロック中は「?」のみ(実名・バナー・ドロップ非表示)
- CLEAR/挑戦済みは 章行の右端のみ。バナーには出さない(アビス最高到達のみバナー右端可)
職名・本文タイポ
- 職名ラベルは 省略(ellipsis)しない(「ビーストテイマー」全文)
- 長い職名は 改行しない(InfoBox が高さ増でスロット/ステが下ずれる)。必要ならフォント縮小で1行に収める
- キャラ名+一覧ボタン(
NameRow)は名前をEXPAND_FILL+ellipsis にしない。名前は実幅・一覧は末尾追従 - JobIcon は巨大 CHR 原寸を載せない(固定 ~22px)
- 本文 Noto は
UiTypography.BODY_FONT_WEIGHT = 800+軽いvariation_embolden(テーマproduction_theme.tresも同値) - キャラ切替 ◀▶ はテーマ Button(DelaGothic)を使わず、flat+Noto body で描く
- Noto を薄く戻す典型原因: (1) HEAD が wght 600 のまま・太字修正が未コミット (2)
body_font()を通さず素の FontFile/別フォントを当てる (3) 700 止まりで Mobile 小サイズでは足りない
検証
- 完了後
godot --path . -s tools/ui_audit.gdでスクショ取得しモックと比較 - 残差分は数値指定で小さく直す(例:
TabRow separation 8→12)
依頼文の良い例
EquipmentScene を 003_04 参考に、TabRow + 一覧グリッド領域のみ Container 骨格を寄せる。
テンプレ: 現行 EquipmentScene。座標指定なし。Tokens は EquipmentUiTokens 拡張。