Skip to content

Commit 30e891b

Browse files
committed
Add concept UI and Cocos skills
1 parent 4d2d15f commit 30e891b

22 files changed

Lines changed: 1203 additions & 9 deletions

File tree

README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,26 @@ FunPlay Skill is a game-development skills library for coding agents, inspired b
2222

2323
- `skills/playable-game-build-flow`: guide a small browser game from intent capture to a playable vertical slice
2424

25+
### Game Design Workflow
26+
27+
- `skills/game-concept-brief`: turn early game inspiration into a compact GDD-lite concept brief
28+
29+
### UI Asset Workflow
30+
31+
- `skills/game-ui-asset-brief`: produce game UI asset prompts, cutout requirements, and validation checks
32+
2533
### Engine Workflow
2634

2735
- `skills/unity-mcp-workflow`: use Funplay Unity MCP as the edit, compile, Play Mode, screenshot, and readback loop
2836

37+
### Cocos Engine
38+
39+
- `skills/minigame-subpackage-rules`: validate WeChat/Douyin minigame subpackage rules
40+
- `skills/canvas-page-popup-bootstrap`: validate and guide new Cocos page, popup, or HUD canvas entries
41+
- `skills/canvas-page-popup-removal`: check blockers before removing page or popup canvas nodes
42+
- `skills/cocos-ui-node-retrofit`: classify and plan safe Cocos UI node retrofits
43+
- `skills/workbench-asset-replace`: plan safe Workbench asset replacement into Cocos visuals
44+
2945
### Meta Routing
3046

3147
- `skills/using-funplay-skills`: onboarding and usage guidance for the library
@@ -96,10 +112,26 @@ CI runs the same test and workspace validation commands.
96112

97113
- `playable-game-build-flow`: guide a small browser game from a one-sentence idea to a playable vertical slice, with the bundled `node <path-to-this-skill>/scripts/validate-pillar.mjs <pillar.md>` for pillar-contract checks
98114

115+
### Game Design Workflow
116+
117+
- `game-concept-brief`: `node skills/game-concept-brief/scripts/build-brief.mjs --prompt "<game idea>"`
118+
119+
### UI Asset Workflow
120+
121+
- `game-ui-asset-brief`: `node skills/game-ui-asset-brief/scripts/build-brief.mjs --style "<art direction>" --asset background --asset button_skin`
122+
99123
### Engine Workflow
100124

101125
- `unity-mcp-workflow`: use when a Unity project is connected to Funplay MCP and needs compile, Play Mode, screenshot, hierarchy, console, or prefab/scene readback verification
102126

127+
### Cocos Engine
128+
129+
- `minigame-subpackage-rules`: `node skills/minigame-subpackage-rules/scripts/validate-minigame-subpackages.mjs profiles/v2/packages/project.json --platform wechatgame`
130+
- `canvas-page-popup-bootstrap`: `node skills/canvas-page-popup-bootstrap/scripts/validate-canvas-entry.mjs canvas/canvas.json page:shop`
131+
- `canvas-page-popup-removal`: `node skills/canvas-page-popup-removal/scripts/check-removal-blockers.mjs canvas/canvas.json popup:coupon`
132+
- `cocos-ui-node-retrofit`: `node skills/cocos-ui-node-retrofit/scripts/classify-retrofit.mjs --intent "<change>" --component cc.Label`
133+
- `workbench-asset-replace`: `node skills/workbench-asset-replace/scripts/plan-asset-replace.mjs --source "<asset>" --target-label GeneratedBackground`
134+
103135
### Meta Routing
104136

105137
- `using-funplay-skills`: ask which verified FunPlay skill should be used for the current goal

commands/engine-safe-edit.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Then:
88

99
1. Determine whether the project is Unity, Godot, or Cocos Creator.
1010
2. Route Unity projects connected to Funplay MCP to `unity-mcp-workflow` when live editor readback, compilation, Play Mode, screenshots, or console logs are needed.
11-
3. For Unity without MCP, Godot, or Cocos Creator, say there is no verified FunPlay skill currently available and continue with normal cautious repository inspection.
11+
3. Route Cocos Creator page/popup canvas, UI retrofit, Workbench asset replacement, or minigame subpackage work to the matching Cocos engine skill.
12+
4. For Unity without MCP, Godot, or unsupported Cocos work, say there is no verified FunPlay skill currently available and continue with normal cautious repository inspection.
1213
4. Ask the user to confirm high-risk editor-generated files before broad edits.
1314
5. End with a short verification checklist for the chosen engine.

commands/engine-workflow.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ Then:
88

99
1. Ask which engine or project type is in scope if it is not already obvious.
1010
2. Use `unity-mcp-workflow` when a Unity project is connected to Funplay MCP and live editor verification is needed.
11+
3. Use the Cocos engine skills for Cocos page/popup canvas entries, safe node removal, UI node retrofits, Workbench asset replacement, and minigame subpackage rules.
1112
3. For non-Unity-MCP engine work, say there is no verified FunPlay skill currently available and continue with normal project-specific inspection.

docs/skill-spec.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ examples:
2626

2727
- Write for agent consumption first: short, direct, explicit instructions.
2828
- Describe when to use the skill, not just what the script does.
29-
- Set `category` to one of `asset-processing`, `game-build-workflow`, `engine-workflow`, or `meta-routing`.
29+
- Set `category` to one of `asset-processing`, `game-build-workflow`, `game-design-workflow`, `ui-asset-workflow`, `engine-workflow`, `cocos-engine`, or `meta-routing`.
3030
- List runtime dependencies, including system tools such as `ffmpeg`.
3131
- Document accepted input formats, produced outputs, and common failure cases.
3232
- Keep scripts deterministic so repeated runs generate predictable filenames.

scripts/validate-workspace.mjs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,12 @@ const skillTests = existsSync('tests/skills.spec.ts') ? readFileSync('tests/skil
5353
const frontmatterKeys = ['name', 'description', 'category', 'dependencies', 'inputs', 'outputs', 'examples'];
5454
const allowedCategories = new Set([
5555
'asset-processing',
56+
'cocos-engine',
5657
'game-build-workflow',
58+
'game-design-workflow',
5759
'engine-workflow',
58-
'meta-routing'
60+
'meta-routing',
61+
'ui-asset-workflow'
5962
]);
6063

6164
if (existsSync(skillsRoot)) {
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
---
2+
name: canvas-page-popup-bootstrap
3+
description: Safely create or inspect new Cocos page, popup, or HUD canvas entries with canonical entry paths, parent and flow wiring, and authored-source guardrails.
4+
category: cocos-engine
5+
dependencies: []
6+
inputs:
7+
- Cocos project canvas files
8+
- desired page, popup, or HUD id
9+
- optional parent page id
10+
- optional flow relationship
11+
outputs:
12+
- canonical node shape
13+
- canvas entry validation result
14+
- flow wiring guidance
15+
- blocker report
16+
examples:
17+
- node skills/canvas-page-popup-bootstrap/scripts/validate-canvas-entry.mjs canvas/canvas.json page:shop
18+
- Use when adding a new page:shop or popup:coupon entry to an existing Cocos canvas.
19+
---
20+
21+
# Canvas Page Popup Bootstrap
22+
23+
Use this skill for narrow Cocos canvas entry work: creating or validating a new `page:*`, `popup:*`, or `hud:*` node and wiring parent/flow truth. It is not a whole new-game workflow and it is not for retrofitting existing UI nodes.
24+
25+
## Canonical Shape
26+
27+
For a page:
28+
29+
- `id`: `page:<leaf>`
30+
- `type`: `page`
31+
- `title`: user-facing title
32+
- `entry`: `assets/ui/pages/<leaf>/<leaf>.prefab`
33+
34+
For a popup:
35+
36+
- `id`: `popup:<leaf>`
37+
- `type`: `popup`
38+
- `title`: user-facing title
39+
- `entry`: `assets/ui/popups/<leaf>/<leaf>.prefab`
40+
- `parent_id`: canonical host page id
41+
42+
For a HUD:
43+
44+
- `id`: `hud:<leaf>`
45+
- `type`: `hud`
46+
- `entry`: established HUD prefab path
47+
48+
## Workflow
49+
50+
1. Classify the request as new page, new popup, new HUD, flow wiring only, or visibility troubleshooting.
51+
2. Prefer the project or daemon structure API when available. If no structure API exists, edit canvas files only when you can mirror all required artifacts safely.
52+
3. Validate the canvas entry:
53+
54+
```bash
55+
node <path-to-this-skill>/scripts/validate-canvas-entry.mjs canvas/canvas.json page:shop
56+
```
57+
58+
4. Keep `parent_id` and `flow.edges` separate. Parent is structure ownership; flow edges are user-visible navigation/opening relationships.
59+
5. If prefab content is touched, use Cocos authoring tools with save/reload proof. Do not hand-edit `.prefab` or `.scene` JSON.
60+
61+
## Guardrails
62+
63+
- `entry` must point to authored page/popup/HUD source, not `assets/main.scene` or generated runtime scenes.
64+
- A canvas node existing does not prove the prefab is authored or visible.
65+
- Do not use this skill for existing-node button/image retrofit; use `cocos-ui-node-retrofit`.
66+
- If the authoritative Cocos/canvas tools are unavailable, report the blocker instead of guessing serialized internals.
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { readFile } from 'node:fs/promises';
2+
3+
function asCanvas(value) {
4+
if (typeof value === 'string') return JSON.parse(value);
5+
return value;
6+
}
7+
8+
export function validateCanvasEntry(canvasInput, nodeId) {
9+
const canvas = asCanvas(canvasInput);
10+
const errors = [];
11+
const warnings = [];
12+
13+
if (canvas.version !== 'v0') {
14+
warnings.push('canvas.version should be "v0".');
15+
}
16+
if (!Array.isArray(canvas.nodes)) {
17+
return { ok: false, errors: ['canvas.nodes must be an array.'], warnings };
18+
}
19+
20+
const node = canvas.nodes.find((candidate) => candidate.id === nodeId);
21+
if (!node) {
22+
return { ok: false, errors: [`Missing canvas node ${nodeId}.`], warnings };
23+
}
24+
25+
if (!['page', 'popup', 'hud'].includes(node.type)) {
26+
errors.push('node.type must be page, popup, or hud.');
27+
}
28+
if (!node.title) {
29+
errors.push('node.title is required.');
30+
}
31+
if (!node.pos || typeof node.pos.x !== 'number' || typeof node.pos.y !== 'number') {
32+
errors.push('node.pos.x and node.pos.y are required numbers.');
33+
}
34+
if (['page', 'popup', 'hud'].includes(node.type) && !node.entry) {
35+
errors.push('node.entry is required for page, popup, and hud nodes.');
36+
}
37+
if (node.type === 'popup' && !node.parent_id) {
38+
errors.push('popup nodes should declare parent_id.');
39+
}
40+
if (node.entry && /__studio_runtime__|assets\/main\.scene/.test(node.entry)) {
41+
errors.push('node.entry must point to the authored page/popup/HUD source, not a runtime scene.');
42+
}
43+
44+
return { ok: errors.length === 0, errors, warnings, node };
45+
}
46+
47+
if (import.meta.url === `file://${process.argv[1]}`) {
48+
const [path, nodeId] = process.argv.slice(2);
49+
if (!path || !nodeId) {
50+
console.error('Usage: node <path-to-this-skill>/scripts/validate-canvas-entry.mjs <canvas.json> <node-id>');
51+
process.exit(2);
52+
}
53+
try {
54+
const result = validateCanvasEntry(await readFile(path, 'utf8'), nodeId);
55+
console.log(JSON.stringify(result, null, 2));
56+
process.exit(result.ok ? 0 : 1);
57+
} catch (error) {
58+
console.error(error.message);
59+
process.exit(1);
60+
}
61+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
name: canvas-page-popup-removal
3+
description: Check blockers and safely remove existing Cocos page or popup canvas nodes without silently deleting prefab, script, or runtime assets.
4+
category: cocos-engine
5+
dependencies: []
6+
inputs:
7+
- canvas/canvas.json
8+
- target page or popup node id
9+
- optional structure API result
10+
outputs:
11+
- deletion blocker report
12+
- referencing flow edge count
13+
- safe deletion guidance
14+
- cleanup boundary summary
15+
examples:
16+
- node skills/canvas-page-popup-removal/scripts/check-removal-blockers.mjs canvas/canvas.json popup:coupon
17+
- Use before deleting an existing page:* or popup:* node from a Cocos canvas.
18+
---
19+
20+
# Canvas Page Popup Removal
21+
22+
Use this skill when the user wants to delete an existing `page:*` or `popup:*` node from Cocos canvas truth.
23+
24+
This skill owns only canvas node removal. It does not silently delete underlying prefab files, scripts, generated runtime scenes, or assets.
25+
26+
## Workflow
27+
28+
1. Confirm the target node exists and is a page or popup.
29+
2. Check blockers:
30+
31+
```bash
32+
node <path-to-this-skill>/scripts/check-removal-blockers.mjs canvas/canvas.json popup:coupon
33+
```
34+
35+
3. Stop if the target has child nodes, dependencies, or is `canvas.flow.root_node_id`.
36+
4. Prefer canonical structure API deletion when available so node truth, ownership artifacts, and flow edges stay aligned.
37+
5. If direct editing is the only route, mirror the same blocker rules and remove only canvas truth plus referencing flow edges.
38+
39+
## Rules
40+
41+
- Do not cascade delete by default.
42+
- Do not invent a replacement flow root.
43+
- Do not treat prefab/script cleanup as part of node deletion unless the user explicitly asks for a separate cleanup.
44+
- Report whether referencing `flow.edges` were removed or should be removed by the structure API.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { readFile } from 'node:fs/promises';
2+
3+
function asCanvas(value) {
4+
if (typeof value === 'string') return JSON.parse(value);
5+
return value;
6+
}
7+
8+
export function checkRemovalBlockers(canvasInput, targetId) {
9+
const canvas = asCanvas(canvasInput);
10+
const nodes = Array.isArray(canvas.nodes) ? canvas.nodes : [];
11+
const blockers = [];
12+
13+
if (!nodes.some((node) => node.id === targetId)) {
14+
blockers.push({ kind: 'missing_node', detail: `${targetId} does not exist.` });
15+
}
16+
17+
for (const node of nodes) {
18+
if (node.parent_id === targetId) {
19+
blockers.push({ kind: 'child_node', detail: `${node.id} has parent_id ${targetId}.` });
20+
}
21+
if (Array.isArray(node.depends_on) && node.depends_on.includes(targetId)) {
22+
blockers.push({ kind: 'dependency', detail: `${node.id} depends_on ${targetId}.` });
23+
}
24+
}
25+
26+
if (canvas.flow?.root_node_id === targetId) {
27+
blockers.push({ kind: 'flow_root', detail: `${targetId} is canvas.flow.root_node_id.` });
28+
}
29+
30+
const edges = Array.isArray(canvas.flow?.edges) ? canvas.flow.edges : [];
31+
const referencingEdges = edges.filter((edge) => edge.from === targetId || edge.to === targetId);
32+
33+
return {
34+
canDelete: blockers.length === 0,
35+
blockers,
36+
referencingEdges: referencingEdges.length
37+
};
38+
}
39+
40+
if (import.meta.url === `file://${process.argv[1]}`) {
41+
const [path, targetId] = process.argv.slice(2);
42+
if (!path || !targetId) {
43+
console.error('Usage: node <path-to-this-skill>/scripts/check-removal-blockers.mjs <canvas.json> <node-id>');
44+
process.exit(2);
45+
}
46+
try {
47+
const result = checkRemovalBlockers(await readFile(path, 'utf8'), targetId);
48+
console.log(JSON.stringify(result, null, 2));
49+
process.exit(result.canDelete ? 0 : 1);
50+
} catch (error) {
51+
console.error(error.message);
52+
process.exit(1);
53+
}
54+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
---
2+
name: cocos-ui-node-retrofit
3+
description: Classify and plan safe Cocos UI node retrofits such as text changes, SpriteFrame swaps, or converting a label-only control into an image-backed button with overlay text.
4+
category: cocos-engine
5+
dependencies: []
6+
inputs:
7+
- target Cocos node path or selection
8+
- existing component list
9+
- intended UI change
10+
- optional source image asset
11+
outputs:
12+
- retrofit classification
13+
- recommended node shape
14+
- proof checklist
15+
- blocker report
16+
examples:
17+
- node skills/cocos-ui-node-retrofit/scripts/classify-retrofit.mjs --intent "replace label with image-backed start button" --component cc.Label --source-asset assets/ui/start.png --actionable
18+
- Use when changing an existing Cocos UI node without creating a new page or popup.
19+
---
20+
21+
# Cocos UI Node Retrofit
22+
23+
Use this skill for targeted edits to existing Cocos UI nodes, especially when replacing text-only controls with image-backed controls, adding overlay text/icons, or fixing a clickable node so the real target owns Sprite, Button feedback, hit size, and handler proof.
24+
25+
## Classify First
26+
27+
Run the classifier or classify manually:
28+
29+
```bash
30+
node <path-to-this-skill>/scripts/classify-retrofit.mjs --intent "<requested change>" --component cc.Label --source-asset assets/ui/button.png
31+
```
32+
33+
Classifications:
34+
35+
- `property-edit`: change an existing component property, such as `cc.Label.string`.
36+
- `resource-swap`: keep structure and replace an existing `cc.Sprite.spriteFrame`.
37+
- `structure-retrofit`: change component mix or add children, such as converting label-only text into Sprite body plus Label overlay.
38+
39+
## Preferred Shape
40+
41+
For an image-backed actionable control:
42+
43+
- target node
44+
- `cc.UITransform`
45+
- `cc.Sprite`
46+
- `cc.Button` when actionable
47+
- child overlay node
48+
- `cc.Label` or `cc.Sprite`
49+
50+
## Guardrails
51+
52+
- Query the selected target before mutation; do not guess node structure.
53+
- Keep the actual selected node as the authority. Do not create a duplicate runtime-only button to satisfy the request.
54+
- Do not hand-edit `.prefab` or `.scene` JSON.
55+
- Do not guess SpriteFrame UUIDs or patch `.meta` files.
56+
- If Cocos authoring tools cannot prove the mutation, report the structured blocker instead of weakening the proof.

0 commit comments

Comments
 (0)