create-pixifact 0.14.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -18,9 +18,25 @@ bun run dev
18
18
  - Vite 项目脚本
19
19
  - `pixifact` 和 `pixifact-cli` 依赖
20
20
  - 开发模式下的 Pixifact Runtime 接入,可直接观察节点、截图、菜单状态并模拟输入
21
+ - 已初始化的 Git 仓库和 `.gitignore`,忽略依赖、构建产物、Pixifact 缓存与本机 env 文件;首次提交由项目使用者创建
22
+ - 项目级 `.agents/skills/pixifact/`,包含 Pixifact skill、Agent metadata 和完整离线参考,随脚手架包分发
21
23
 
22
24
  ## 生成脚本
23
25
 
26
+ 创建完成后的终端提示会列出以下命令,在项目根目录运行:
27
+
28
+ | 命令 | 用途 |
29
+ | --- | --- |
30
+ | `bun run dev` | 启动 Web 开发服务 |
31
+ | `bun run build` | 构建 Web 生产版本 |
32
+ | `bun run compile` | 独立编译 `.scene` 到 `.pixifact/generated` |
33
+ | `bun run editor` | 启动 Pixifact 编辑器 |
34
+ | `bun run validate` | 校验项目 |
35
+
36
+ 模板的 `.env` 默认设置 `VITE_PLATFORM=web`。`dev` 和 `build` 会自动处理 Scene 编译,也可以使用 `compile` 单独编译 Scene。
37
+
38
+ ## 观察运行中的游戏
39
+
24
40
  ```bash
25
41
  bun run dev
26
42
  pixifact runtime tree
@@ -33,3 +49,4 @@ pixifact runtime screenshot
33
49
  ## 环境要求
34
50
 
35
51
  - Bun
52
+ - Git
@@ -1,6 +1,9 @@
1
+ import { execFile } from 'node:child_process';
1
2
  import { cp, mkdir, readdir, readFile, stat, writeFile } from 'node:fs/promises';
2
3
  import path from 'node:path';
3
4
  import { fileURLToPath } from 'node:url';
5
+ import { promisify } from 'node:util';
6
+ const runFile = promisify(execFile);
4
7
  function packageDirectory() {
5
8
  const currentFile = fileURLToPath(import.meta.url);
6
9
  const sourceDirectory = path.basename(path.dirname(currentFile));
@@ -11,6 +14,12 @@ function packageDirectory() {
11
14
  function templateDirectory(template) {
12
15
  return path.join(packageDirectory(), 'templates', template);
13
16
  }
17
+ function skillDirectory() {
18
+ const currentDirectory = path.dirname(fileURLToPath(import.meta.url));
19
+ return path.basename(currentDirectory) === 'src'
20
+ ? path.resolve(currentDirectory, '../../../skills/pixifact')
21
+ : path.join(currentDirectory, 'skills/pixifact');
22
+ }
14
23
  function projectDisplayName(name) {
15
24
  return name
16
25
  .split(/[-_\s]+/)
@@ -53,6 +62,16 @@ export async function createPixifactProject(options) {
53
62
  const projectJson = JSON.parse(await readFile(projectJsonPath, 'utf8'));
54
63
  projectJson.name = projectDisplayName(options.name);
55
64
  await writeJson(projectJsonPath, projectJson);
65
+ await cp(skillDirectory(), path.join(projectRoot, '.agents/skills/pixifact'), { recursive: true });
66
+ await writeFile(path.join(projectRoot, '.gitignore'), [
67
+ 'node_modules/',
68
+ 'dist/',
69
+ '.pixifact/',
70
+ '.env.local',
71
+ '.env.*.local',
72
+ '',
73
+ ].join('\n'), 'utf8');
74
+ await runFile('git', ['init', '--quiet'], { cwd: projectRoot });
56
75
  return {
57
76
  name: options.name,
58
77
  root: projectRoot,
package/dist/index.js CHANGED
@@ -16,7 +16,20 @@ else {
16
16
  try {
17
17
  const result = await createPixifactProject({ name });
18
18
  process.stdout.write(`已创建 ${result.name}:${result.root}\n`);
19
- process.stdout.write(`下一步:cd ${result.name} && bun install && bun run dev\n`);
19
+ process.stdout.write('已初始化 Git 仓库,并安装 Pixifact skill 到 .agents/skills/pixifact/。\n');
20
+ process.stdout.write([
21
+ '下一步:',
22
+ ` cd ${result.name}`,
23
+ ' bun install',
24
+ '',
25
+ '项目命令:',
26
+ ' bun run dev 启动 Web 开发服务',
27
+ ' bun run build 构建 Web 生产版本',
28
+ ' bun run compile 编译 Scene',
29
+ ' bun run editor 启动 Pixifact 编辑器',
30
+ ' bun run validate 校验项目',
31
+ '',
32
+ ].join('\n'));
20
33
  }
21
34
  catch (error) {
22
35
  process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
@@ -0,0 +1,106 @@
1
+ ---
2
+ name: pixifact
3
+ description: 用于下游 Pixifact 游戏项目:编辑项目相对 .scene 文件、维护同名 Scene 脚本契约、运行 validate / compile 并截取任意 Scene 的静态预览;以及在 Vite Web 开发模式下通过 pixifact runtime 读取运行中游戏的 PixiJS 节点、业务状态和日志,发送标准输入并验证行为。适用于 UI、HUD、menu、轻量 Scene、交互逻辑、视觉检查、运行时验证和诊断任务。
4
+ ---
5
+
6
+ # Pixifact
7
+
8
+ 用于下游 Pixifact 游戏项目。目标是直接编辑项目里的 `.scene` 源文件和同名 `.ts` 脚本,再用 Pixifact CLI 校验和编译。
9
+
10
+ ## Scene 工作流
11
+
12
+ 处理 Scene、UI、HUD、menu、layout 或视觉资产任务时,优先编辑项目相对 `.scene` 源文件。
13
+
14
+ 1. 读取 `package.json`、`pixifact.project.json` 和目标 `.scene` / `.ts` 文件。
15
+ 2. 开始任何非纯查阅的 Scene 改动前,按 `references/scene-authoring-decisions.md` 做短决策;新建或大改 Scene 时先读全文。
16
+ 3. 新建 Scene、添加节点、修改布局或不确定对象属性时,先读 `references/scene-objects.md`。
17
+ 4. 涉及层级结构重组、复杂列表、overlay、slot content 或子 Scene 拆分时,先读 `references/scene-hierarchy-patterns.md`。
18
+ 5. 新建或修改同名 `.ts` 脚本契约、`@part()`、`@prop()`、`@event()` 或 `@slot()` 时,先读 `references/scene-script-patterns.md`。
19
+ 6. 读取项目摘要:
20
+ ```bash
21
+ pixifact summary
22
+ ```
23
+ 7. 需要结构上下文时 inspect 目标 Scene:
24
+ ```bash
25
+ pixifact scene inspect --scene src/scenes/MainMenu.scene
26
+ ```
27
+ 8. 新建空 Scene 文件对时执行:
28
+ ```bash
29
+ pixifact scene create src/scenes/MainMenu.scene
30
+ ```
31
+ 命令按路径 basename 创建同名 `.scene` 与 `.ts`;随后直接编辑 `.scene`,必要时同步脚本契约。
32
+ 9. 校验被编辑的 Scene:
33
+ ```bash
34
+ pixifact scene validate --scene src/scenes/MainMenu.scene
35
+ ```
36
+ 多个 Scene 可能受影响时:
37
+ ```bash
38
+ pixifact scene validate --all
39
+ ```
40
+ 10. 视觉任务在校验通过后截取目标 Scene,不需要启动 Editor:
41
+ ```bash
42
+ pixifact scene screenshot --scene src/scenes/MainMenu.scene --output /tmp/main-menu.png
43
+ ```
44
+ 查看 PNG 后继续调整 `.scene`,直到静态画面符合目标;此命令需要本机 Google Chrome,不执行游戏脚本。游戏运行状态用 `runtime screenshot` 验证。
45
+ 11. 校验通过后编译:
46
+ ```bash
47
+ pixifact compile-scenes
48
+ ```
49
+ 12. 运行项目最小相关检查,通常是:
50
+ ```bash
51
+ bun run build
52
+ ```
53
+ 13. 改动影响微信或抖音目标时,读取项目对应 mode 的 env 文件,再运行该 mode 的校验与构建。例如微信 mode 为 `wechat`:
54
+ ```bash
55
+ pixifact validate --mode wechat
56
+ pixifact build --mode wechat
57
+ ```
58
+
59
+ 默认项目根是当前工作目录;不在项目根运行时再加 `--project-root <path>`。项目自己的 `bun run build`、`bun run dev` 等命令只作为后续检查或预览入口。
60
+
61
+ ## 运行时验证工作流
62
+
63
+ 任务影响 Vite Web 游戏行为、交互或运行时状态,或者需要诊断运行中游戏时,先完整阅读 `references/runtime-observation.md`,再按以下顺序操作:
64
+
65
+ 1. 读取项目 `package.json` 和 Runtime 接入代码,使用项目已有开发命令启动游戏;不要猜启动命令。
66
+ 2. 运行 `pixifact runtime list` 发现当前页面;多个页面时为后续命令显式传 `--runtime <runtime-id>`。
67
+ 3. 操作前读取 `runtime state` 和 `runtime logs`,记住日志返回的 `latestSeq`。
68
+ 4. 用 `runtime tree --output .pixifact/runtime/tree.json` 保存现场节点树;编译节点的 `source.scenePath` / `source.locator` 指向 `.scene`,子 Scene 实例的 `instanceSource` 指向父 Scene 中的放置位置。需要 bounds 或详细字段时再查询 `runtime node <uid>`。
69
+ 5. 通过 renderer 坐标或键盘发送 `runtime input`;不要直接调用节点方法或修改运行时状态。
70
+ 6. 操作后重新查询 `state`、`tree` 或 `node`,并用 `runtime logs --after <latestSeq>` 验证结果;涉及画面变化时在操作前后分别截图比较。
71
+
72
+ 不要缓存 `runtime-id` 或 PixiJS `uid`。输入命令返回 `dispatched: true` 只表示事件已分发,不代表行为成功。Runtime 信息足够回答问题时不依赖浏览器工具;需要判断像素、构图或动画观感时仍使用项目已有视觉检查方式。
73
+
74
+ ## 对象和脚本契约
75
+
76
+ 动手前判断见 `references/scene-authoring-decisions.md`。官方 `.scene` 对象、通用属性、对象专属属性、children 规则、slot、event 和 structured prop 写法见 `references/scene-objects.md`。层级结构组织、root 区块、layout container、scroll、overlay 和 inspect 复核见 `references/scene-hierarchy-patterns.md`。`.scene` 与同名 `.ts` 脚本的配对模板、`@part()` / `@prop()` / `@event()` / `@slot()` 模式和常见诊断修复见 `references/scene-script-patterns.md`。运行中 Vite Web 游戏的 Runtime 接入、查询、输入和验证边界见 `references/runtime-observation.md`。不要在 `SKILL.md` 里复制完整对象清单或模板库;如果不确定某个标签、属性、层级或脚本契约是否可写,先读 reference,再以 `pixifact scene validate` 为准。
77
+
78
+ ## 硬性规则
79
+
80
+ - `.scene` 是 authored visual structure、hierarchy、layout、text、image、子 Scene instance、slot 和 event wiring 的 source of truth。
81
+ - Scene 资产是同目录、同 basename 的文件对,例如 `src/scenes/Hud.scene` 和 `src/scenes/Hud.ts`。
82
+ - `.scene` root 使用 `<Scene name="...">`。
83
+ - `<Group>` 用于有明确宽高或 frame layout 的普通盒子容器;`Container` 保持 Pixi 原生 bounds / scale 尺寸语义。
84
+ - Scene 脚本类必须继承 `Group`,并使用 `@scene()` 标记。
85
+ - Scene decorator、event、slot 和异步 Scene 准备 API 从 `pixifact/scene` 导入,不要从 `pixifact/compiler` 导入运行时 API。
86
+ - Scene 脚本类不能声明自定义构造参数;构造时第一个对象保留给 initial Props,其他运行依赖通过显式方法传入。
87
+ - `@part()` 绑定 `.scene` 中稳定 `id` 节点;`@prop()`、`@event()`、`@slot()` 暴露公开契约。
88
+ - `@prop()` 只能装饰无 initializer 的 `declare` property,类型由 TypeScript 声明推断;不要写 setter、accessor 或 `type` option。
89
+ - `.scene` 只使用完整值 `{prop}` / `{variant.field}` Binding,不写表达式、插值、watch 或双向绑定。
90
+ - `.scene` 中的事件属性如 `@clicked="handlePause"` 绑定 action name;运行时连接 external actions 或当前 root 脚本同名方法。不要把它写成全局函数或生成文件逻辑。
91
+ - 不要在 `.scene` 文件中添加 `script="..."`。
92
+ - 不要给 `@scene()` 添加 template path。
93
+ - 引用其他 Scene 时使用 `.scene` 路径,不要使用裸名称。
94
+ - 不要编辑生成的 Scene 文件,例如 `.pixifact/generated/**`、`src/generated/**`、`*.scene.generated.ts` 或 `scenes.generated.ts`。
95
+ - 使用 `<slot name="..."/>` 表示 slot outlet。
96
+ - Structured prop 使用 dot-path attributes,例如 `rectTransform.x="0"`;不要传 JSON string。
97
+ - 可编辑节点必须有稳定 `id`。
98
+ - 官方对象和属性见 `references/scene-objects.md`;最终以 `pixifact scene validate` 为准。
99
+
100
+ ## 游戏代码
101
+
102
+ 非 Scene 逻辑按项目现有 TypeScript 风格实现。优先使用 Pixifact 公开 import;只有 Pixifact 未覆盖的底层渲染或资产行为才直接使用 PixiJS v8。
103
+
104
+ ## 完成条件
105
+
106
+ 不要只编辑文件就结束。Scene 改动必须运行 validate、compile 和最小相关 build/dev 检查。已接入 Runtime 且任务影响运行时行为时,必须查询操作前后状态或节点,并检查增量日志;如果失败,报告准确的失败命令和 diagnostic。
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Pixifact"
3
+ short_description: "在 Pixifact 项目中编辑 Scene、维护脚本契约并验证运行中游戏"
4
+ default_prompt: "使用 $pixifact 编辑下游游戏的 Scene 或逻辑,并通过 CLI 校验和 Runtime 验证运行结果。"
@@ -0,0 +1,89 @@
1
+ # Pixifact Runtime Observation
2
+
3
+ 本文件随 Pixifact skill 安装,用于下游 Vite Web 游戏在开发模式下观察和验证真实运行行为。Runtime 直接读取当前 PixiJS `app.stage`;编译节点可指回其 `.scene` 来源。
4
+
5
+ ## 接入前提
6
+
7
+ Vite 配置启用开发 transport:
8
+
9
+ ```ts
10
+ import { pixifactRuntimePlugin } from 'pixifact/compiler-node';
11
+
12
+ export default defineConfig({
13
+ plugins: [pixifactRuntimePlugin()],
14
+ });
15
+ ```
16
+
17
+ 游戏启动完成后注册页面唯一的 PixiJS `Application`:
18
+
19
+ ```ts
20
+ if (import.meta.env.DEV) {
21
+ const { registerPixiRuntime } = await import('pixifact/runtime-dev');
22
+
23
+ registerPixiRuntime(app, {
24
+ getState: () => ({
25
+ phase: game.phase,
26
+ player: { hp: player.hp },
27
+ }),
28
+ });
29
+ }
30
+ ```
31
+
32
+ `getState` 可选,只在 `runtime state` 请求时同步执行。需要稳定、反复查询的业务状态放在这里;不要新增 `registerRuntimeState`,也不要让 Runtime 遍历 JavaScript 堆。
33
+
34
+ ## 标准验证闭环
35
+
36
+ 1. 读取 `package.json`,使用项目已有命令启动 Vite 开发服务器,并确保游戏页面已经打开。
37
+ 2. 运行 `pixifact runtime list`。只有一个页面时自动选择;多个页面时记录目标 `runtimeId`,后续命令添加 `--runtime <runtime-id>`。
38
+ 3. 查询 `pixifact runtime state` 和 `pixifact runtime logs`,把日志的 `latestSeq` 作为操作前基线。
39
+ 4. 用 `pixifact runtime tree --output .pixifact/runtime/tree.json` 保存节点树快照。编译节点的 `source.scenePath` / `source.locator` 指向源 `.scene`;子 Scene 实例的 `instanceSource` 指向父 Scene 中的放置位置。需要尺寸、`globalBounds`、交互字段或类型信息时运行 `pixifact runtime node <uid>`。
40
+ 需要修改这个节点时,先运行 `pixifact scene inspect --scene <source.scenePath>`,再根据 `source.locator` 定位;调整子 Scene 实例在父 Scene 中的位置时,改用 `instanceSource`。
41
+ 5. 使用 `globalBounds` 中心点发送 click,或发送项目真实使用的键盘输入。
42
+ 6. 重新查询 state、tree 或 node,并运行 `pixifact runtime logs --after <latestSeq>`。涉及视觉结果时,在操作前后分别运行 `runtime screenshot --output <png-path>` 并比较画面。只有可观察结果符合预期,验证才完成。
43
+
44
+ 页面刷新后 `runtime-id` 和 PixiJS `uid` 都可能改变,必须重新发现。不要把它们写入源码、Scene 或项目数据。
45
+
46
+ ## 命令速查
47
+
48
+ ```bash
49
+ pixifact runtime list
50
+ pixifact runtime tree [--output <json-path>] [--runtime <runtime-id>]
51
+ pixifact runtime screenshot [--output <png-path>] [--runtime <runtime-id>]
52
+ pixifact runtime node <pixi-uid> [--runtime <runtime-id>]
53
+ pixifact runtime state [--runtime <runtime-id>]
54
+ pixifact runtime logs [--after <seq>] [--level <level>] [--runtime <runtime-id>]
55
+ pixifact runtime input click --x <x> --y <y> [--runtime <runtime-id>]
56
+ pixifact runtime input move --x <x> --y <y> [--runtime <runtime-id>]
57
+ pixifact runtime input key <key> [--runtime <runtime-id>]
58
+ pixifact runtime input keydown <key> [--runtime <runtime-id>]
59
+ pixifact runtime input keyup <key> [--runtime <runtime-id>]
60
+ ```
61
+
62
+ 点击坐标使用 Pixi renderer screen 坐标。先查询目标节点的 `globalBounds`,使用 `x + width / 2`、`y + height / 2` 计算中心点,不要根据截图猜坐标。
63
+
64
+ `runtime tree` 默认输出完整树。节点很多或需要反复搜索时,保存一次 JSON 快照;此时终端只返回文件路径和采集元数据:
65
+
66
+ ```bash
67
+ pixifact runtime tree --output .pixifact/runtime/tree.json [--runtime <runtime-id>]
68
+ ```
69
+
70
+ 快照包含 `schemaVersion`、`capturedAt`、`runtimeId` 和 `root`。它只代表采集时刻的 `app.stage`,不能作为 `.scene` 数据源;页面刷新后必须重新生成,快照中的 `runtimeId` 和 PixiJS `uid` 也不能长期复用。
71
+
72
+ `runtime screenshot` 捕获当前 `app.stage` 的 PixiJS Canvas PNG,保留视口平移和缩放。省略 `--output` 时写入项目根下的 `.pixifact/runtime/frame.png`;传入 `--output <png-path>` 可覆盖路径。截图不包含浏览器 UI、HTML/CSS 或 DOM overlay。
73
+
74
+ ## 状态与诊断
75
+
76
+ - `state` 回答“现在是什么状态”,只包含项目通过 `getState` 明确暴露的 JSON。
77
+ - `tree` / `node` 回答“当前显示树是什么样”,数据源始终是 `app.stage`。
78
+ - 编译节点的 `source` 提供项目相对 `.scene` 路径和 inspect locator;根节点 locator 为 `null`。子 Scene 实例还可能有父级 `instanceSource`。脚本动态创建的 Pixi 节点没有来源字段。
79
+ - `logs` 回答“刚才发生了什么”,保留最近 500 条 `console`、`window.error` 和 `unhandledrejection` 记录。
80
+ - 私有状态不适合加入长期 `getState` 时,可在能访问该状态的源码位置临时添加日志;验证完成后删除日志。
81
+ - `state.available: false` 表示项目没有提供 `getState`,继续使用 tree、node 和 logs,不要假造业务状态。
82
+
83
+ ## 边界
84
+
85
+ - Runtime 只支持 Vite Web 开发模式,不用于 production、微信小游戏或 Editor Authoring Preview。
86
+ - Runtime 不提供 eval、节点 mutation、业务状态 mutation、直接节点 click、方法调用或日志持久化。
87
+ - `input` 只分发标准 pointer / keyboard 事件,不绕过 PixiJS 命中测试。
88
+ - `dispatched: true` 不代表动画、异步加载或业务流程已经稳定;由 Agent 重复查询可观察结果并控制超时。
89
+ - 程序生成的输入事件 `isTrusted` 为 `false`,不能完成全屏或音频解锁等受信任手势。
@@ -0,0 +1,118 @@
1
+ # Pixifact Scene Authoring Decisions
2
+
3
+ 本文件随 Pixifact skill 安装,用于下游项目在编辑 `.scene` 和同名 `.ts` 前做最小决策。目标不是写长篇分析,而是让 agent 先判断改动应该落在哪一层、需要哪些公开契约、用什么布局和验证闭环。
4
+
5
+ ## 默认决策顺序
6
+
7
+ 动手前按这个顺序判断:
8
+
9
+ 1. 用户要改的是视觉结构、布局、文案、图片,还是行为?
10
+ 2. 这是现有 Scene 的局部修改,还是应该新建可复用子 Scene?
11
+ 3. 父子 Scene 是否需要公开契约:`@prop()`、`@event()`、`@slot()` 或 `@part()`?
12
+ 4. 层级树应该怎么组织:root 区块、容器、layout container、子 Scene、叶子节点各放哪里?
13
+ 5. 改完需要跑哪些命令证明结果?
14
+
15
+ 把结论压成短决策即可,不要写长篇推理。
16
+
17
+ ```md
18
+ Decision:
19
+ - Source of truth: edit `src/scenes/Hud.scene`
20
+ - Script needed: yes, expose `@prop({ default: 0 }) declare coins: number`
21
+ - Hierarchy: `HBoxContainer#resourceRow` groups icon + text
22
+ - Validation: validate Hud.scene, compile-scenes, then build
23
+ ```
24
+
25
+ ## Source of Truth
26
+
27
+ | 用户目标 | 默认落点 |
28
+ | --- | --- |
29
+ | 改位置、尺寸、颜色、图片、字体、静态文案 | `.scene` |
30
+ | 调整父子层级、分组、布局容器、slot 填充 | `.scene` |
31
+ | 运行时改变由公开 Prop 控制的文字、显隐、颜色、数值 | `.ts` 声明 `@prop()`,`.scene` 用 Binding 指向目标属性 |
32
+ | 点击、拖拽、输入、动画、计时器、状态切换 | `.ts` |
33
+ | 父 Scene 给子 Scene 传值 | 子 `.ts` 暴露 `@prop()`,父 `.scene` 写属性 |
34
+ | 子 Scene 通知父 Scene | 子 `.ts` 暴露 `@event()`,父 `.scene` 写 `@eventName="actionName"` |
35
+ | 父 Scene 给子 Scene 塞内容 | 子 `.scene` 写 `<slot>`,子 `.ts` 暴露 `@slot()`,父 `.scene` 子节点写 `slot="name"` |
36
+
37
+ 如果只是静态 UI,不要为了“更像组件”而写脚本逻辑。静态视觉属性留在 `.scene`。
38
+
39
+ ## 是否拆子 Scene
40
+
41
+ 优先不拆。只有满足下面至少一条时才新建子 Scene:
42
+
43
+ - 会在多个父 Scene 中复用。
44
+ - 有独立 public props、events 或 slots。
45
+ - 自身有明确交互行为,例如按钮、列表项、弹窗。
46
+ - 层级足够复杂,拆出后能减少父 Scene 噪音。
47
+
48
+ 不要因为一个面板只用一次就立刻拆子 Scene。先用容器组织;需要复用或公开契约时再拆。
49
+
50
+ ## 契约选择
51
+
52
+ | 需要 | 用法 |
53
+ | --- | --- |
54
+ | 脚本访问 `.scene` 节点 | 节点写稳定 `id`,脚本写 `@part()` |
55
+ | 父 Scene 设置子 Scene 单个值 | `@prop({ default: ... }) declare name: string / number / boolean` |
56
+ | 一个 Prop 切换一组样式 | `defineVariants()` + `@prop({ variants })` + `{variant.field}` Binding |
57
+ | 父 Scene 设置一组相关字段 | exported structured prop class + dot-path attributes |
58
+ | 子 Scene 发出动作 | `@event()` + `createEvent()` |
59
+ | 父 Scene 填充子内容 | 子 `.scene` 写 `<slot name="..."/>`,脚本写 `@slot()` |
60
+
61
+ 常见选择树:
62
+
63
+ ```txt
64
+ 需要改变显示文字?
65
+ - 静态文案:改 <Text text="...">
66
+ - 运行时可变且属于公开契约:脚本声明 `@prop()`,`.scene` 写 `<Text text="{propName}">`
67
+ - 仅内部行为更新:Text 写稳定 id,脚本用 `@part()` 或显式方法更新
68
+
69
+ 需要按钮点击?
70
+ - 子 Scene 暴露 @event() readonly click = createEvent()
71
+ - pointertap 时 this.click.emit()
72
+ - 父 Scene 写 @click="methodName"
73
+ - 父脚本实现 methodName()
74
+
75
+ 需要父 Scene 塞图标?
76
+ - 子 Scene 写 <slot name="icon" />
77
+ - 子脚本写 @slot({ name: 'icon' })
78
+ - 父 Scene 子节点写 slot="icon"
79
+ ```
80
+
81
+ ## 布局选择
82
+
83
+ | 情况 | 优先写法 |
84
+ | --- | --- |
85
+ | 背景铺满 | `left="0" right="0" top="0" bottom="0"` |
86
+ | HUD 贴边元素 | `left` / `right` / `top` / `bottom` |
87
+ | 居中弹窗或按钮组 | `horizontal="0"` / `vertical="0"` |
88
+ | 横向资源条、工具栏 | `HBoxContainer` |
89
+ | 纵向菜单、任务列表 | `VBoxContainer` |
90
+ | 背包、关卡卡片、固定列 | `GridContainer` |
91
+ | 长列表、背包滚动区 | `ScrollContainer` + 内部 `VBoxContainer` / `GridContainer` |
92
+ | 纯分组、统一移动或显隐 | `Container` |
93
+
94
+ 布局和层级不确定时,先读 `scene-hierarchy-patterns.md`,并写一个短树形草图。
95
+
96
+ ## 不要写
97
+
98
+ - 不要编辑 generated files。
99
+ - 不要在 `.scene` 写 `script="..."` 或 `class="..."`。
100
+ - 不要给 `@scene()` 传路径。
101
+ - 不要把静态视觉属性迁移到 `.ts`。
102
+ - 不要猜不存在的 `.scene` 标签或属性。
103
+ - 不要为缺失 `@part()`、未知 prop、未知 event 写静默 fallback。
104
+ - 不要为了单次使用过早拆子 Scene。
105
+ - 不要给 `@prop()` 写 `type` option、initializer、accessor、getter 或 setter。
106
+ - 不要在 `.scene` Binding 中写表达式、插值、watch 或双向绑定。
107
+
108
+ ## 验证选择
109
+
110
+ | 改动范围 | 验证 |
111
+ | --- | --- |
112
+ | 单个 Scene 的 `.scene` / `.ts` | `pixifact scene validate --scene <path>` |
113
+ | 多个 Scene 或公共子 Scene 契约 | `pixifact scene validate --all` |
114
+ | 层级结构大改 | 先 `pixifact scene inspect --scene <path>` 对比树,再 validate |
115
+ | validate 通过 | `pixifact compile-scenes` |
116
+ | 影响运行项目 | `bun run build` 或项目最小相关检查 |
117
+
118
+ 如果 validation 或 compile 失败,修源码,不修生成文件;修复后重跑失败命令。