PluginBench
Skill
Pass
Audit score 90

msw-ui-system

msw-git/msw-ai-coding-plugins-official

Complete MSW UI system: design guide, component API, builder, and runtime patterns for `.ui` files.

What is msw-ui-system?

MSW UI System provides a unified reference for designing, building, and scripting game UIs in MSW. It covers layout fundamentals (anchor/pivot/RectTransform), component selection and API, builder invocation through msw_ui_builder.cjs, and Lua runtime patterns for interactive elements. Use this when creating or modifying any `.ui` file or connecting UI logic in `.mlua` scripts.

  • Design guidance for anchor/pivot/RectTransform positioning and mobile-safe layouts
  • Full component API reference (ButtonComponent, TextGUIRendererComponent, SpriteGUIRendererComponent, ScrollLayoutGroup, GridView, TextInput, Slider, Mask, AvatarGUIRenderer) with enum values
  • UIBuilder invocation methods: add/replace/patch/remove nodes, 13 anchor presets, auto-lint on write
  • Layout recipes for common patterns: HUD, popup, toast, menu, inventory grid, scroll list
  • Runtime Lua patterns: popup open/close, toast fade, HP bar, GridView interaction, drag, tab, cooldown, world nametag
  • Automatic `.ui` ↔ `.mlua` UUID binding injection for property defaults

How to install msw-ui-system

npx skills add https://github.com/msw-git/msw-ai-coding-plugins-official --skill msw-ui-system
Prerequisites
  • MSW project with `.ui` file support
  • Node.js (for msw_ui_builder.cjs invocation)
  • Familiarity with anchor/pivot concepts or willingness to read ui-fundamentals.md
Claude Code
Cursor
Windsurf
Cline

How to use msw-ui-system

  1. 1.Read the routing table in the skill to identify which reference document matches your task (e.g., 'anchor/pivot' → ui-fundamentals.md, 'popup placement' → layout-recipes.md)
  2. 2.Load the relevant reference document (ui-fundamentals, ui-hierarchy, component-api, layout-recipes, runtime-patterns, or ui-sound)
  3. 3.For any `.ui` creation or modification, read builder-protocol.md (core) and builder-protocol-ui.md §3 to understand the builder API
  4. 4.Match your layout to a recipe in layout-recipes.md; adapt rather than build from scratch
  5. 5.Invoke msw_ui_builder.cjs with the appropriate method (create, add, patch, remove) and anchor preset
  6. 6.Call b.write() to persist changes; auto-lint runs and validates the `.ui` file
  7. 7.For Lua integration, use b.injectBindings() or the bind parameter in b.write() to auto-populate property default UUIDs
  8. 8.Verify the layout visually with preview_ui_layout.cjs and test interaction in-engine

Use cases

Good for
  • Build a HUD layout with health bar, mana bar, and inventory grid anchored to screen edges
  • Create a popup dialog with buttons and text, then wire open/close and button-click handlers in Lua
  • Design a toast notification system that fades in/out and auto-dismisses
  • Implement a GridView inventory with drag-and-drop interaction patterns
  • Set up a menu with tab navigation and cooldown timers on buttons
Who it's for
  • Game UI designers building layouts in MSW
  • Gameplay programmers wiring UI logic in Lua scripts
  • Full-stack developers handling both `.ui` design and `.mlua` runtime code
  • Mobile game developers needing safe-area and resolution-aware layouts

msw-ui-system FAQ

Why does my UI element appear in the wrong position?

Check ui-fundamentals.md §1–§8 on anchor/pivot/RectTransform. Most issues stem from mixing anchoredPosition with OffsetMin/Max, or incorrect anchor/pivot alignment. Use the formula pos = ±(margin + size/2) for edge placement.

How do I connect a button click to Lua code?

Build the button with msw_ui_builder.cjs, then use b.injectBindings() or the bind parameter in b.write() to auto-populate the button's UUID into your `.mlua` script. See builder-protocol-ui.md §3.6 Binding Injection and runtime-patterns.md for click handler patterns.

Can I edit the `.ui` file directly in JSON?

No. Direct JSON editing breaks UUID, ValueType, and @components consistency. Always use UIBuilder.read() to query and b.write() to mutate. The builder enforces auto-lint and maintains structural integrity.

What's the difference between UIGroup and CanvasGroup?

UIGroup is the root container for a UI hierarchy; CanvasGroup is a child container that affects opacity and z-order of its children. See ui-hierarchy.md for z-order, displayOrder, and Enable vs Visible semantics.

How do I handle mobile safe areas and different resolutions?

Read ui-fundamentals.md §9 on mobile, safe area, and MobileOnly/ActivePlatform. Use anchor presets and the safe-area formula to position UI relative to screen edges, and set font/touch sizes conditionally by device.

Full instructions (SKILL.md)

Source of truth, from msw-git/msw-ai-coding-plugins-official.


name: msw-ui-system description: "MSW .ui single entry point — design + component API + builder + runtime. Anchor/pivot/RectTransform, UIGroup/CanvasGroup hierarchy, layout recipes (HUD/popup/toast/menu/inventory/scroll-list), full API tables for ButtonComponent/TextGUIRendererComponent/SpriteGUIRendererComponent/ScrollLayoutGroup/GridView/TextInput/Slider/Mask/AvatarGUIRenderer + UI enums (AlignmentType/TextOverflowMode/ImageType/FillAmount), .mlua runtime patterns (popup open-close, toast, HP bar, GridView, drag, tab, cooldown, world nametag), UI-client-only caveats (nil on server, no RPC), .ui↔.mlua UUID auto-binding (write+injectBindings), resolution/safe-area/touch. UIBuilder (msw_ui_builder.cjs): all node types (empty/panel/text/sprite/button/slider/scrollLayout/textInput/group/mask/gridView/avatar/skeleton etc.), component add/replace/patch/remove, 13 anchor presets+stretch, auto-inject .mlua UUID bindings after write."

msw-ui-system

MSW .ui single entry point — design guide + component API + builder invocation + runtime patterns bundled into one skill.

Role division with existing skills:

SkillResponsibility
msw-ui-system (this skill)Everything .ui — design (which/when/why), component API/enum (what), builder invocation (how to mutate), runtime mlua patterns. .ui mutations must always go through this skill's builder
references/templates/Pre-built style bundles — .ui + ruid-map + button handler packages

0. Routing

Branch to sub-references based on request keywords.

TriggerReference Document
"anchor/pivot/coordinates/why is the position wrong", "RectTransform", "stretch"references/ui-fundamentals.md §1–§8
"mobile", "safe area", "1920", "MobileOnly", "ActivePlatform", "touch size", "PC reserved zone", "font size by device"references/ui-fundamentals.md §9
"UIGroup", "above popup", "z-order", "displayOrder", "CanvasGroup", "opacity propagation", "Enable vs Visible"references/ui-hierarchy.md; for runtime sibling reorder also read references/runtime-patterns.md §7
"which component", "Sprite vs Text vs Button", "9-slice", "scroll list", "GridView vs ScrollLayoutGroup"references/component-api.md §"Component Selection Guide"
"sprite pivot", "9-slice border", "slice boundary", "set sliced asset metadata", "resource storage properties"Set asset-side metadata via msw-mcp asset_update_resource_storage_info directly; for the .ui side see references/component-api.md §"SpriteGUIRenderer — ImageType Selection"
"make a HUD", "popup placement", "toast", "menu", "inventory grid", "scroll list"references/layout-recipes.md
"connect .mlua after building with .ui builder", "property default UUID", "binding without drag"../msw-general/references/builder-protocol-ui.md §3.6 Binding Injection (unified entry point — load with the builder-protocol.md core)
Runtime UI component field read/write, component property name/type (ButtonComponent.Colors, TextGUIRendererComponent.Overflow, SpriteGUIRendererComponent.FillAmount…)references/component-api.md required before every .mlua access to UI component fields
Enum values (AlignmentType, TextOverflowMode, ImageType, UIBasicParticleType…)references/component-api.md §Enums
Runtime mlua patterns (popup open/close, toast fade, HP bar, GridView, drag, tab, cooldown), Runtime UI Caveats (client-only, server-side nil, etc.)references/runtime-patterns.md
.ui builder invocation methods (UIBuilder API, anchor presets, write auto-lint, component add/patch/remove)../msw-general/references/builder-protocol-ui.md §3 UIBuilder (unified entry point — load with the builder-protocol.md core; .map MapBuilder / .model ModelBuilder live in sibling per-builder files)
"sound", "sfx", "click sound", "hover sound", "button audio", "PlaySound"references/ui-sound.md

1. Basic Workflow

(1) Clarify intent       Layout sketch (ASCII or verbal) + which group to attach to
(2) Check design guide   Match at least one of ui-fundamentals / ui-hierarchy / component-api §Component Selection Guide
(3) Builder Preflight    Read ../msw-general/references/builder-protocol.md (core) + builder-protocol-ui.md §3 (unified call-protocol entry point)
(4) Match recipe          Select the closest template from layout-recipes.md
(5) Invoke builder        Create/patch via scripts/msw_ui_builder.cjs (protocol: builder-protocol-ui.md §3)
(6) Inject bindings       Auto-inject .mlua property default UUIDs via b.write(path, { bind: {...} }) or b.injectBindings(...) (builder-protocol-ui.md §3.6 Binding Injection)
(7) Self-verify           write() auto-runs scripts/ui_lint.cjs (strict ON by default)
(8) Preview               Visual check via scripts/preview_ui_layout.cjs
(9) Sound pass            For any interactive button, offer click/hover SFX wiring (references/ui-sound.md)
(10) Maker Refresh         Apply to engine

2. Global Rules

NEVER

  1. Do not directly edit .ui JSON — .ui creation/modification must go through scripts/msw_ui_builder.cjs. Manual editing breaks UUID·ValueType·@components consistency and causes silent drops.
  2. Read existing .ui files through the builder too — Query via UIBuilder.read(filepath) / .find() / .listEntities(). Do not directly grep/parse raw JSON.
    • .ui direct Read and shell commands such as cat / type / Get-Content / rg / grep / sed / awk / cp / mv are blocked by the registered guard. Use UIBuilder.read/load/snapshot for reads and b.write() for writes. Deleting an entire .ui file has no builder API — delete it with node -e "require('fs').unlinkSync('ui/<File>.ui')" then refresh (shell rm/cat are guard-blocked; a node -e builder call is not).
  3. Set Position directly — Use only anchoredPosition (Position is engine-managed)
  4. Express size via OffsetMin/Max on fixed anchors (AnchorsMin == AnchorsMax) while also using anchoredPosition — Do not mix the two modes
  5. Builder creates new UUIDs but .mlua property defaults are not updated — Binding breaks

ALWAYS

  1. Builder Protocol Preflight — ../msw-general/references/builder-protocol.md (core) + ../msw-general/references/builder-protocol-ui.md §3 must be in context before any .ui mutation (read them only if never loaded this session or lost to compaction) (UIBuilder API, write auto-lint, pos / anchor rules, binding injection, coverage gaps). The core carries the shared contract and cross-builder flow; .map MapBuilder / .model ModelBuilder live in sibling per-builder files — one unified entry point because the cross-flow is interlocked.
  2. Check at least one design guide before invoking the builder (ui-fundamentals / ui-hierarchy / component-api §Component Selection Guide)
  3. Match a recipe first; build from scratch only as a last resort
  4. For edge placement use the formula: pos = ±(margin + size/2)
  5. Separate popups and toasts into their own .ui root UIGroup, standalone show/hide; use empty() / panel() for inner containers, never nested group()
  6. Verify text Alignment default is UpperLeft(0) — 95% of "I centered it but it sticks to the left" issues
  7. Button touch target ≥ 88×88 (mobile support)
  8. After creating any interactive button — proactively suggest wiring click/hover SFX via references/ui-sound.md (default UI SFX RUIDs available). Skip only if the user explicitly opts out or the button is purely decorative.
  9. Build the tree nested, not flat. Controls of one unit (window + title/close, row + chip/value, slot + icon/count) must share a parent via "Parent/Child" paths so they move / fade / toggle / bind as a block. Create each parent before its children; missing parents fail lint (L025 ERROR).
  10. Do not stack root-level text over a sibling box. ui_lint reports this as L030 WARN. Nest the text under the box, use button() for clickable labeled boxes, or put a direct label on panel() / sprite() via their text options.

3. Sub-documents

  • references/ui-fundamentals.md — Coordinate system, RectTransform 3 elements, anchor mode determination (§1–§8) + Resolution·safe area·PC reserved zones·touch targets·font sizes·platform separation (§9)
  • references/ui-hierarchy.md — UIGroup / displayOrder / CanvasGroup / Enable vs Visible
  • references/component-api.md — §"Component Selection Guide" (which/when/why) + full component property/method/event tables (what) + all UI-related enum values (§Enums)
  • references/layout-recipes.md — Layout template collection
  • references/runtime-patterns.md — .mlua runtime patterns (popup/toast/HP/grid/drag…) + Runtime UI Caveats
  • references/ui-sound.md — UI sound integration (_SoundService:PlaySound, click/hover hook, default UI SFX RUIDs)
  • ../msw-general/references/builder-protocol-ui.md §3 — .ui CJS builder call protocol (unified entry point — load with the builder-protocol.md core) — .map MapBuilder / .model ModelBuilder live in sibling per-builder files. panel / text / sprite / button / slider / scroll / script / group / mask / grid / avatar / touchReceive / skeleton / areaParticle / basicParticle, component CRUD, anchor presets, write auto-lint, and .mlua property UUID auto-binding all live in §3 + §3.6.
  • references/templates/templates.md — Pre-built style bundle index (style-N-* .ui, ruid-map.md, Popupbutton.mlua)

4. Scripts

  • scripts/msw_ui_builder.cjs — .ui builder core (UIBuilder class). Read ../msw-general/references/builder-protocol.md (core) + ../msw-general/references/builder-protocol-ui.md §3 (unified entry point) before use.
  • scripts/preview_ui_layout.cjs — .ui layout visual check + touch target warnings
  • scripts/ui_lint.cjs — .ui file self-verification (auto-called by write())
  • scripts/ui_recipe.cjs — Recipe-based scaffolding

Out of Scope

  • .map / .model / .tileset builders — Outside this skill's scope
  • .ui JSON schema (raw field shapes, @type/@components wrapping, AlignmentOption 0–15 mapping, etc.) — Handled internally by the builder. Users/AI do not need to know directly
  • Accessibility patterns (alt text, screen-reader hints, focus order) — Not covered
  • Error-state UI patterns (disabled-button styling beyond Transition.Disabled, validation messages, loading spinners) — Not covered; design ad-hoc per project
  • Automated UI testing / layout assertions beyond ui_lint.cjs and preview_ui_layout.cjs — Not provided
  • Custom shader materials (MaterialId) — Field is exposed but authoring shaders is outside this skill's scope