本文へ移動
cccskills
無料GitHub で公開

scenario-godot-ui

Use when building or fixing game UI in Godot 4.7: main menu, settings screen, HUD (health bar, ammo, minimap frame), Control layout, containers, anchors, themes in code, 'UI scales wrong on phones', 'text too small on 4K', notch or safe area, stretch mode and aspect, gamepad or keyboard menu navigation, focus lost, input rebinding screen, localization (CSV, PO, tr_n plurals, Arabic RTL, CJK fonts, pseudolocalization), screen reader accessibility, UI scale slider, or clicks not reaching the game.

インストール方法を見る

含まれるファイル(20)

  • SKILL.md21.5 KB
  • references/critique.md4.7 KB
  • references/expert-notes.md8.4 KB
  • references/gui-paths.md8.4 KB
  • references/procedures.md17.9 KB
  • references/sources.md7.9 KB
  • scripts/agentkit/ui/examples/build_g7.gd14.5 KB
  • scripts/agentkit/ui/hud_bar.gd1.5 KB
  • scripts/agentkit/ui/menu_stack.gd3.7 KB
  • scripts/agentkit/ui/safe_area.gd1.5 KB
  • scripts/agentkit/ui/ui_audit.gd6.8 KB
  • scripts/agentkit/ui/ui_capture.gd4.8 KB
  • scripts/agentkit/ui/ui_focus.gd4.4 KB
  • scripts/agentkit/ui/ui_layout.gd10.6 KB
  • scripts/agentkit/ui/ui_rebind.gd8.6 KB
  • scripts/agentkit/ui/ui_selftest.gd1.2 KB
  • scripts/agentkit/ui/ui_settings.gd5.0 KB
  • scripts/agentkit/ui/ui_stretch.gd6.3 KB
  • scripts/agentkit/ui/ui_theme.gd8.8 KB
  • scripts/gd_ui.py9.5 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Godot UI (UI developer)

Target: Godot 4.7.2.stable, macOS Apple Silicon.

Expert level here means one layout proven, by numbers and images, from a 1080x2400 phone in portrait to a 3840x2160 monitor, in every language, with mouse, pad and screen reader. The stretch transform scales, containers place, one Theme built in code styles, and nothing ships before a layout matrix and a contact sheet say so. If a sibling skill named here is missing from your available skills, ask the user to install it (npx skills add scenario-labs/skills --skill <name>); unattended, proceed from tool schemas and flag the gap.

REQUIRED BACKGROUND: scenario-godot-expert (channels, review loop, 6.3 traps).

Stance (the expert delta)

  1. Pick the base size for the extremes, not for 1080p. A square base (720x720) with canvas_items + expand and Handheld Orientation sensor gives one scale for portrait and landscape (docs, Multiple resolutions). Measured: 1.5x on a 1080x2400 phone in both orientations, 3x on 4K. A 1152x648 base gives a 0.9375x canvas on the same phone and three undersized buttons [added, measured]. Godotneers' 1920x1080 base (1_OFJLyqlXI) suits desktop only.
  2. Containers place, anchors pin. Sizing is a negotiation: the minimum size is the floor, Expand claims leftover space, Fill uses it (Godotneers 1_OFJLyqlXI 00:35:00, Karto 5Hog6a0EYa0 00:14:39). Measured in a 400 px HBox: Expand without Fill leaves the claimed space empty (sibling pushed to x 380); Fill or a stretch ratio without Expand changes nothing; ratios are summed, 1:3 gives 96 and 290 of 386 px (Karto 00:15:45). Anchor presets are relative to the parent; set_anchors_preset() alone keeps the old offsets (a 50x50 child stays 50x50 on FULL_RECT), so use set_anchors_and_offsets_preset() (Karto 00:05:24, measured). A corner element also needs its grow direction, or longer text grows off screen [added, measured 1462 px wide in a 1152 px canvas].
  3. The look lives in one Theme resource built in code, with type variations instead of per-node overrides (docs, Theme type variations). StyleBoxes are shared Resources: an override reused on two nodes changes both (Karto 00:19:00).
  4. Focus is explicit. Nothing has focus at scene start, so ui_down does nothing until something calls grab_focus() (docs, Controller navigation; measured). Keep a menu stack that disables covered panels and returns focus to the opener (Mostly Mad Productions ecJZipjUj6k 00:08:57).
  5. The current selection is the highest-contrast element on screen, body text comes first, two or three fonts at most, and the outro is faster than the intro (Rawb Herb, GodotCon 2025, sjmAD1ZLBcE 00:31:42, 00:21:34, 00:55:38).
  6. Text is keys, never literals. Named placeholders with format(), tr_n() for plurals, context for identical English, auto translate disabled on dynamic text (docs, Internationalizing games). Fonts get fallbacks, not remaps.
  7. HUD is passive and signal-driven. Its root and wrappers ignore the mouse; values change on signals, not in _process (consensus of 1_OFJLyqlXI, Yuw7CK5H8eA, f90ieBOoIYQ). A new string reshapes (200 labels: 1.1 to 1.5 ms of CPU per frame); assigning the identical string is an early-out, so the cost is the changed text, not the assignment [added, measured]. In-place array mutations never call a setter (0 calls after append, 1 after reassigning), so state arrays emit their own signal (NoBSGodot Yuw7CK5H8eA 00:05:06, measured).
  8. Verify at device sizes headless, then look. Headless, root.size takes any size and applies the project stretch, so a layout matrix runs in seconds; a windowed capture then renders each device with the notch drawn in [added, measured].

Establish first

InputChangesDefault if nobody says
Platforms and orientationsbase size, orientation, touch target sizephone portrait + landscape, desktop to 4K: base 720x720, canvas_items, expand, orientation 6 (sensor)
Art stylestretch mode and scale modevector or high-res: canvas_items + fractional; pixel art: viewport, base 640x360, integer, Exclusive Fullscreen (docs)
Input devicesfocus work, rebind screen, touch sizesmouse, keyboard, pad, touch
Languagesfonts, RTL, Text Server Data on exporten plus one long (de), one CJK (ja), one RTL (ar) for tests
Accessibility barscreen reader, UI scale slider, contrastWCAG 4.5:1 body text, UI scale 0.75 to 2.0 via content_scale_factor
Rendererupscaler choice in settingsForward+ (Jolt kept); Compatibility forces bilinear 3D scaling

Workflow

1. Project settings. Write the stretch keys explicitly: a hand-written project.godot gets disabled and keep (deltas). gd_env.set_project_setting for display/window/size/viewport_width/height, stretch/mode, stretch/aspect, handheld/orientation, gui/theme/custom. Check that 3d/physics_engine="Jolt Physics" and the renderer survived. GATE: gd_ui.stretch_math(window, base, ...) for each target gives the expected logical size and scale (port matches the engine on 224 cases, origin and scale included).

2. Theme in code. ui_theme.gd build(overrides) returns a Theme: Button states with a thick accent focus box, Label, panels, sliders, tabs, ProgressBar, variations TitleLabel, HudLabel, HudValue, PrimaryButton, HudPanel, HealthBar, TrailBar. Save it as .tres, set the default font to a SystemFont with CJK and Arabic fallbacks, two or three fonts at most. Text drawn at many scales (HUD numerals at 3x) gets MSDF: gui/theme/default_font_multichannel_signed_distance_field or the font's multichannel_signed_distance_field, both false by default (Karto 5Hog6a0EYa0 00:20:50, measured). Default Theme Scale is read once: a runtime set changed nothing (measured). In the editor a Theme edit needs a scene reload to repaint (Godotneers 00:22:10) and an override is inactive until its checkbox is ticked (Karto 00:17:25); in code only add_theme_*_override counts, and runtime Theme edits propagate at once (measured). GATE: contrast_report() body pairs >= 4.5:1 (worst measured 4.37 is the disabled state, allowed); check_variations() finds no misspelt variation.

3. Scenes in code. Root Control full rect, a safe_area.gd MarginContainer, then containers. Buttons 88 logical tall at a 720 base (132 px on a phone at 1.5x). Settings rows in ScrollContainers inside a TabContainer. HUD on a CanvasLayer, root MOUSE_FILTER_IGNORE, AspectRatioContainer for the minimap; a round minimap or portrait frame is a clip_children mask (Clip Only on a rounded Panel), but a child with another z_index escapes it (GDQuest W4j4tnQLcTA 00:03:47, measured), so keep masked content at z 0 or use a SubViewport. Toggles read "On"/"Off" as text (CoffeeCrow 9H_fN4OxyIE 00:08:11). safe_area.gd recomputes on size_changed (top margin 104 at 1.5x, 82 at 2x, measured). examples/build_g7.gd builds the whole G7 set. GATE: ui_audit.gd audit_tree() returns no hud_blocks_input, icon_keep_size, grows_offscreen_*, no_accessible_name, shared_stylebox_override, unknown_variation.

4. Layout matrix headless. gd_ui.layout_matrix(P, scene, targets, min_touch_px=..., safe_insets=..., locale=..., pseudo=True) for 8 targets (phone portrait and landscape, 4:3 tablet, 1366x768, 1080p, 21:9, 4K, 800x600). GATE: zero offscreen, outside_safe, small_target, text (clipped or overflowing), overlap and collapsed issues for each scene, in en, de and pseudolocalized at 0.4 expansion.

5. Capture matrix windowed, then look. gd_ui.capture_matrix(P, scene, targets, safe_insets=...) renders each target at its physical size with black bars and red notch bands, and builds a contact sheet. Open the sheet. GATE: image_checks flags none; by eye: selection visible, no clipped glyphs (CJK, Arabic), notch bands over background only, bars and frames intact. Never capture through an embedded Window with content_scale_*: it draws unscaled (P13, measured).

6. Focus and input. gd_ui.focus_walk(P, scene, steps) pushes ui_* actions through push_input and records the focus owner; ui_focus.graph() lists unreachable focusables. Menu stack: open, cancel, focus back on the opener. GATE: every focusable reachable from the default; first key press from no focus lands on the default; covered panels unreachable.

7. Rebinding. ui_rebind.gd: accept (no echo, no Escape, sticks over 0.5), normalize (physical keycode, device -1, axis sign), report conflicts, swap or refuse, save as ConfigFile, reset from project settings. Show the key with DisplayServer.keyboard_get_label_from_physical() (windowed only): on a French layout physical Q reads "A" (measured). Add pad buttons yourself: in 4.7.2 ui_accept and ui_cancel hold keys only (Enter, Kp Enter, Space; Escape), so add Joypad Button 0 and 1 (Mostly Mad ecJZipjUj6k 00:12:00, measured). GATE: binding matches on keyboard and on any pad after a save and load round trip.

8. Localization. CSV with a ?plural column, gd_ui.check_csv offline, --import, then gd_ui.register_translations. Run en, fr, de, ja, ar and pseudolocalization; expansion_ratio defaults to 0.0, so set 0.3 to 0.4 and call reload_pseudolocalization() (measured). --language fr is the non-persistent test. Animated text is a RichTextEffect: bbcode var plus _process_custom_fx(char_fx), options from char_fx.env (Cashew OldDew KMqYeRae6rM 00:14:01; measured [lift px=6] read 6.0), installed with install_effect(). GATE: no missing keys per locale; Arabic mirrors (anchors and HBox order); plurals right in en and fr; layout matrix clean.

9. Settings and cost. ui_settings.gd autoload applies window mode, vsync, render scale and upscaler, quality, UI scale, bus volumes, locale; saves and reloads. GATE: save and load round trip; ui_scale 1.5 turns a 1280x720 canvas into 853x480.

Numbers

ValueRelative toSource
Base 720x720, canvas_items, expand, orientation sensorphone portrait and landscape plus desktopdocs, Multiple resolutions
Scale 1.5 on 1080x2400 and 2400x1080, 3.0 on 3840x2160, 1.0672 on 1366x768base 720x720measured [added]
Base 720x1280 on a 2400x1080 phone: expand 2844x1280 at 0.844x (UI shrinks), keep_width 897 px side bars; keep_height on 1080x2400: 240 px barswhy a square base beats an aspect choicemeasured [added]
Pixel art 640x360 viewport integer; viewport at fractional 1.0672 (1366x768) resamples and blurs text720p to 4Kdocs, measured
Default Theme Scale 2.0 to 3.0 for a 4K base, 1.5 to 2.0 mobile 1080p base; read once (runtime set: no change)base sizedocs, measured
Touch target 126 px phone, 96 px tablet (48 dp at about 420 and 320 dpi)physical pixels[added]
Button 88 logical at base 720132 px on a phone[added, measured]
WCAG 4.5:1 body, 3:1 large texttext vs its backgroundWCAG 2 [added]
Damage trail: one-shot timer 0.4 s, restarted per hit; heal instanthealth changeDashNothing f90ieBOoIYQ 00:01:26
Text Server Data ~4 MBexport size, for no-space scriptsdocs
200 labels: 1.1 to 1.5 ms new text every frame, 0.17 to 0.23 ms for 10 per frame, under 0.1 ms same text (as idle)CPU per frame, headless M5 Maxmeasured [added]

Quality gates

Measurable: test_ui_live.py U1 to U15 green (compile, stretch parity, CSV, layout matrix, capture, focus, rebind, HUD, localization, engine facts, theme and settings, cost, embedded Window, round-2 layout and theme facts, clip mask and text effect); zero issues in the layout matrix for each scene and locale; audit clean; contrast >= 4.5:1 on body pairs; save and load round trips. Visual: one contact sheet per scene and locale (menu, HUD, settings ja, menu ar, settings pseudo), opened: focus visible, glyphs complete, nothing under the notch, letterbox where expected, selection still visible in grayscale (Rawb Herb).

Common mistakes

MistakeWhat it looks likeFix
1920x1080 or 1152x648 base for a phone gametiny buttons in portrait (scale 0.9375 at 1080x2400)square base 720x720 + expand
Stretch keys left out of an agent-written project.godotUI fixed size, black space on 4Kwrite mode and aspect explicitly
Full-rect Control with default STOP filter over the gameclicks never reach _unhandled_input (0 of 1)MOUSE_FILTER_IGNORE on HUD roots and wrappers
Corner preset without grow directionscore text runs off the right edgegrow_horizontal = GROW_DIRECTION_BEGIN
No grab_focus() on openpad does nothingmenu stack grabs the default on the first nav event
TextureRect left on KEEP_SIZE in a containera 512 px icon makes a 64 px row 614x512; IGNORE_SIZE with no minimum collapses to width 0EXPAND_FIT_WIDTH_PROPORTIONAL (64x64 measured) or ignore size + min size, Stretch Keep Aspect Centered (Godotneers 1_OFJLyqlXI 00:10:28)
OptionButton items as literal EnglishJapanese screen shows "Windowed"items as keys (OPT_WINDOWED)
Tabs left at theme defaulttabs too small to touchtab styleboxes with content margins; the matrix checks the TabBar
Stored binding with device 0 from a synthesized eventpad 2 or the real keyboard (device 16) do not triggernormalize to device -1
Pseudolocalization on, expansion untouched or no reloadno padding (default ratio 0.0)set expansion_ratio, TranslationServer.reload_pseudolocalization()
POT generation trusted for custom nodes in old tutorialsstrings missing (4.2 bug)fixed in 4.3 (Cashew OldDew v0tJPsNNOM8 00:08:00, not rerun); CSV keys avoid POT
Locale Test set in project settingsships in Frenchclear it; use --language fr
Hiding a container child with visible = false for an effectsiblings jump (relayout)modulate.a = 0 or offset_transform_scale (MrElipteach pK2vI2-jCH4 00:02:54)
Expecting a focus ring after a mouse clickring only on the next key or pad pressby design: gui/common/show_focus_state_on_pointer_event 1 (text inputs only)

Handoffs

  • In: state autoloads and signals (scenario-godot-architecture), input actions and values (scenario-godot-gameplay), bus names Master, Music, SFX (scenario-godot-audio), icons, panels, fonts (scenario-* skills; nine-patch margins set in code).
  • Out: render scale and upscaler contract (scenario-godot-rendering-lighting); Text Server Data, real-device safe area and touch (scenario-godot-performance-export); intro and outro tracks, offset_transform motion (scenario-godot-animation); test_ui_live.py for CI (scenario-godot-pipeline-automation).

Godot 4.7 notes

  • offset_transform_* (4.7) moves container children without relayout; offset_transform_visual_only defaults to true, so clicks hit the layout rect (measured). pivot_offset_ratio (4.7) for center pivots; grab_focus(hide_focus) (4.6).
  • AccessibilityServer (4.7), accessibility_name, FOCUS_ACCESSIBILITY (RichTextLabel default); accessibility_support 0 Auto runs only with an assistive app active.
  • auto_translate_mode replaced auto_translate; FoldableContainer (4.5), VirtualJoystick, PopupMenu.allow_search (4.7); [img] takes width_unit/height_unit. Upscalers: FSR2=2, MetalFX spatial=3, temporal=4.
  • push_input(event, true) takes logical coordinates. Godot 3 names (rect_size, add_color_override, margin_*, stretch 2d, process_custom_fx) are gone.

References

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Handle review comments received on GitHub for the current branch's PR or a given PR number or URL, by triaging each unresolved thread, fixing what is warranted, pushing, and replying in each thread, when asked to address, fix or answer PR comments. Works in any Scenario repository.

日本語の概要は準備中です。原文の説明を表示しています。

scenario-labs/skills9922026年10月13日 更新

Generate one short Conventional Commits squash message describing only the net diff between the PR's base and head, set its header as the PR title, validate it with the repository's commitlint and both copy its description to the clipboard and display it, when asked for a squash message. Works in any Scenario repository, whatever its default branch.

日本語の概要は準備中です。原文の説明を表示しています。

scenario-labs/skills9922026年10月13日 更新

Refresh the current pull request description from its net changes, following the repository's PR template, when asked to update or write the PR summary. Works in any Scenario repository, whatever its default branch.

日本語の概要は準備中です。原文の説明を表示しています。

scenario-labs/skills9922026年10月13日 更新

scenario

無料

Use when connecting an AI agent to Scenario (scenario.com) through MCP, or when a task involves generating images, video, 3D, audio, sprites, textures, or game assets. Also when picking a Scenario model, running a LoRA, refining a generation prompt, uploading reference images, waiting on generation jobs, checking credits or quota, hitting Scenario auth, scope, or Forbidden errors, or setting up mcp.scenario.com in Claude Code, Cursor, VSCode, or another agent.

日本語の概要は準備中です。原文の説明を表示しています。

scenario-labs/skills9922026年10月13日 更新

Use when generating or handling 3D assets through the Scenario MCP server, including text-to-3D or image-to-3D meshes, GPT-6 Astra 3D or Claude Opus 5.5 3D, GLB, FBX, OBJ, STL, or VOX files, PBR-textured or game-ready models, voxel models, multi-view reconstruction, retexture, remesh, UV unwrap, auto-rigging a biped or quadruped, or retargeting an animation, previewing a mesh in the inline 3D viewer, or downloading a model for import into Unity, Unreal, Godot, or Blender.

日本語の概要は準備中です。原文の説明を表示しています。

scenario-labs/skills9922026年10月13日 更新

Use when generating navigable 3D worlds or Gaussian splat scenes on Scenario via MCP: text-to-world, image-to-world, a 360 panorama or skybox turned into a walkable splat, multi-view photos or a video walkthrough reconstructed as a splat, or one object photo to splat. Keywords: World Labs Marble 1.1, 1.1 Plus, 1.0 Draft, Hunyuan World, HY World, image-to-skybox, skybox-to-splat, multiview-to-splat, TripoSplat, gaussian splatting, 3DGS, spz, world generation, explorable scene, VR.

日本語の概要は準備中です。原文の説明を表示しています。

scenario-labs/skills9922026年10月13日 更新

scenario-labs のスキルをすべて見る

このスキルの問題を報告する