t1k:cocos:playable:parameter-scan
| Field | Value |
|---|---|
| Module | playable |
| Version | 0.5.6 |
| Effort | medium |
| Tools | — |
Keywords: canvas-scan, component-scan, config-scan, discover, find-nodes, parameter-scan, scan, scene-scan
How to invoke
Section titled “How to invoke”/t1k:cocos:playable:parameter-scan[--mode ui|config|all] [--deep] [--canvas <path>] [--path <folder>]Cocos Playable Parameter Scan
Section titled “Cocos Playable Parameter Scan”Two-layer scene and config discovery engine for the flat-primitive parameter architecture. The scanner identifies parameterizable Cocos nodes and emits a report; the implement step consumes that report and produces flat-primitive PlayableConfig entries (one per node, with prefixed primitives — never ComponentParameter wrappers).
Two-Layer System
Section titled “Two-Layer System”| Layer | Flag | Approval | Output |
|---|---|---|---|
| UI | --mode ui | None (auto) | Parameterizable nodes JSON |
| Config | --mode config | Required | Config candidates JSON |
| Both | --mode all | Config only | Combined report |
Decision Tree
Section titled “Decision Tree”| Intent | Action |
|---|---|
| ”Parameterize all UI components” | --mode ui → auto-generate per-node flat-primitive entries |
| ”Scan nodes under a specific Canvas” | --mode ui --canvas <path> |
| ”Extract config values for params” | --mode config → present candidates |
| ”Find magic numbers in gameplay code” | --mode config --deep |
| ”Scan specific game folder” | --mode config --path <folder> |
| ”Full parameter pass” | --mode all |
| Mode | Scope | MCP Required | Approval |
|---|---|---|---|
--mode ui | Canvas descendants + component detection | Yes | None |
--mode config | *Config.ts files in scripts/ | No | Required |
--mode config --deep | Above + magic numbers in gameplay code | No | Required |
--mode all | UI (auto) then Config (review) | Yes | Config only |
Deprecated Modes (Backward Compatible)
Section titled “Deprecated Modes (Backward Compatible)”| Old Flag | Maps To | Emits Warning |
|---|---|---|
--quick | --mode ui (wired nodes only) | Yes |
--standard | --mode ui | Yes |
--deep (alone) | --mode all --deep | Yes |
Config Detection (--mode config)
Section titled “Config Detection (--mode config)”What Gets Detected
Section titled “What Gets Detected”| Category | Keywords | Primitive |
|---|---|---|
| Health | hp, health, damage, heal | RangeParameter (0-1000) |
| Timing | duration, delay, cooldown, interval | RangeParameter (0-60) |
| Speed | speed, velocity, rate | RangeParameter (0-100) |
| Counts | count, max, bullets, amount | RangeParameter (0-99, step:1) |
| Distance | offset, range, position, fov | RangeParameter |
| Colors | color, tint (hex literals) | ColorParameter |
| Flags | enabled, active, visible | BooleanParameter |
Config File Detection
Section titled “Config File Detection”Finds all *Config.ts files in the target path and parses:
- Exported const objects:
export const GameConfig = { ... } - Individual exports:
export const PLAYER_HP = 100
Magic Number Detection (--deep)
Section titled “Magic Number Detection (--deep)”When --deep is specified, also scans .ts files for:
- Numeric assignments:
this.speed = 5; - Tween durations:
.to(0.5, {...}) setTimeoutvalues:setTimeout(fn, 3000)
Exclusions: Loop indices, array indices, import statements.
Output Format
Section titled “Output Format”{ "mode": "config", "configCandidates": [ { "key": "PlayerMaxHP", "value": 100, "type": "number", "category": "Gameplay-Combat", "source": "GameConfig.ts:17", "primitive": "RangeParameter" } ], "totalCandidates": 60}See references/config-detection.md for the full detection algorithm.
Canvas Selection (--mode ui)
Section titled “Canvas Selection (--mode ui)”By default, scans nodes under Canvas (and any sibling BG canvas). Use --canvas to target a specific root:
--canvas "Canvas/SomeView/SafeArea"--canvas "Canvas/BattleUI"--canvas "Canvas/SomeView,Canvas/EndCard" # comma-separatedPath matching: exact path · suffix match · wildcard Canvas/*/SafeArea.
Workflow
Section titled “Workflow”Step 1: Detect mode from user intent or flagsStep 2: Acquire scene data (MCP batch or scene JSON parse)Step 3: For each node, detect components via manage_component get_allStep 4: Build component signature per nodeStep 5: Match signature against NodePreset (shape templates)Step 6: Emit scan report JSON (flat-primitive shape per node)Component Detection Priority
Section titled “Component Detection Priority”| Priority | Component | Notes |
|---|---|---|
| P0 | Node, UITransform | Always present on UI nodes |
| P0 | UIOpacity | Common, emits opacity (no prefix) |
| P0 | Widget | Emits widget-prefixed primitives |
| P1 | Sprite, Label, Button, Camera | Core visual/interaction → prefixed primitives |
| P1 | RichText, ProgressBar, Slider, Toggle | Extended UI → prefixed primitives |
| P2 | Layout, Mask | Layout/clipping |
| SKIP | ParticleSystem*, Skeleton*, VideoPlayer, WebView, EditBox, ScrollView, PageView | Excluded |
Scan Report JSON Format
Section titled “Scan Report JSON Format”{ "scanRoot": "Canvas/SomeView/SafeArea", "nodes": [ { "uuid": "...", "name": "Btn_CTA", "path": "Canvas/SomeView/EndCard/Btn_CTA", "components": ["cc.Node", "cc.UITransform", "cc.Sprite", "cc.Label", "cc.Button", "cc.UIOpacity"], "matchedPreset": "Button", "primitiveShape": { "spriteColor": "#FFFFFF", "spriteFrame": "", "labelString": "PLAY", "labelColor": "#000000", "labelFontSize": 48, "buttonTransition": "SCALE", "buttonZoomScale": 1.1, "buttonNormalColor": "#4CAF50", "buttonPressedColor": "#388E3C", "opacity": 255 }, "suggestedCategory": "UILayer-EndCard" } ], "codeDetectedGroups": [ { "name": "Battle UI", "properties": ["battleRoot", "scopeOverlay", "releaseLabel"], "sourceFile": "BattleUIController.ts", "suggestedCategory": "UILayer-Battle" } ], "presetsMatched": 3, "groupsDetected": 1}Each node entry becomes ONE top-level ObjectParameter in PlayableConfig whose body is the primitiveShape map. The suggestedCategory becomes the entry’s category. No wrapper classes, no nested ObjectParameter.
@property Group Detection
Section titled “@property Group Detection”When scanning code alongside scene nodes, detect @property({ group: 'X' }) decorators to identify logical UI groupings:
@property({ type: Node, group: 'Battle UI' })battleRoot: Node = null;
@property({ type: Label, group: 'Battle UI' })releaseLabel: Label = null;Each grouped property is still its own top-level ObjectParameter. The group name becomes a shared category suggestion (UILayer-{Group}) so the dashboard sidebar collapses them together. Grouped properties do NOT produce a wrapper composite class — they produce N separate flat entries with one shared category.
Critical Rules
Section titled “Critical Rules”- Batch-check components. Do NOT pre-filter by name.
- Use
manage_component get_allper node when MCP is connected. - Read actual scene values for primitive defaults.
- Never skip
UIOpacityorWidgetdetection. - Report nodes with no parameterizable components as “skipped”.
- Each scanned node → ONE
ObjectParameterentry, never a wrapper class instance. - Component-prefixed primitives on multi-component nodes (
spriteColor,labelString,buttonTransition). Single-field components skip the prefix (opacity).
References
Section titled “References”references/config-detection.md— Config file parser + magic-number detectorreferences/property-group-detection.md—@propertygroup detection algorithm- Parent skill
references/scan-strategy.md— Batch Canvas scanning approach - Parent skill
references/field-coverage.md— Component → prefixed-primitive tables - Parent skill
references/mcp-assignment.md— MCP health checks and batching
Batch Scanning Script
Section titled “Batch Scanning Script”For large Canvas trees (100+ nodes), use the batch scanning script:
node scripts/batch-scan.cjs --canvas "Canvas/SomeView" --output scan-report.json --verboseOptions:
--canvas <path>— Root node path to scan--output <file>— Output JSON file (default: stdout)--delay <ms>— Delay between MCP calls (default: 50ms)--verbose— Print progress to stderr
The script handles rate limiting automatically to avoid overwhelming the MCP server.
Gotchas
Section titled “Gotchas”--autodisables review gates on every mode.- Scene values become primitive defaults; placeholder values pollute the parameter list.
- RichText is a separate component from Label in Cocos 3.8+ — do not conflate.
- Nodes with only Node + UITransform and no other components are non-parameterizable.
- Batch script requires MCP server running (
http://127.0.0.1:3000/mcp). - NodePreset is a shape template, not a wrapper class. A “Button” preset means “this node has Sprite+Label+Button+UIOpacity components → emit these prefixed primitives”, not “wrap them in a ButtonParameter class”.