feat(timeline): P2 并行编排——scene 多轨编辑器 + 白模重叠预览
剧情 Timeline P2 前端 + 共享内核(与 SGame 源真同步): - ir_core/IR_SCHEMA/样张:scene v0.3 + scene 校验 + 导出 gate(D3),与 SGame 仓逐字一致 - timeline.js:appendScene 按 authored start 铺多轨 clip(自然重叠预览),move from 同 actor 跨轨续连(D4); drawStage 改逐 actor 查对话→多人气泡同时计时;导出 _clipDur 纯函数;show() 加 startId 参;常量加 CAMERA_DUR - scene_edit.js(新):演出段编辑模态——拖 clip 改 start(吸附 0.1s)、拖右缘改 dur、增删 clip/轨道、 选中属性条精确编辑、客户端轻量 lint(镜像 validate.py)、▶ 预览此段(复用播放核) - graph.js:scene 节点(KIND_CN/summary/nodeInner 列轨道)+双击进编辑模态 - form.js:右栏 renderScene 精确数值编辑(轨道/clip 的 start/dur/kind/目标)+打开编辑器按钮 - app.py export:捕获 CompileError 并入 report(scene 被拦时不再 500) - test_scene.js:离线 10 断言全过(重叠确凿/晚 1.5s 起步/from 续连);gitignore 忽略本地 _localdemo.db 待浏览器目测拖拽编辑落 IR + 白模重叠演出。
This commit is contained in:
52
IR_SCHEMA.md
52
IR_SCHEMA.md
@ -1,5 +1,8 @@
|
||||
# Story IR Schema(v0.2,M4 扩展)
|
||||
# Story IR Schema(v0.3,P2 扩展)
|
||||
|
||||
> v0.3 变更(剧情 Timeline P2):新增 `scene` 节点(多轨时间线容器,承载并行+时间偏移演出)+ track + clip 模型(见 §4.2)。
|
||||
> scene 与现有线性节点**并存**(D1);scene 内只放演出、不含分支,有单一 `next` 出口(D2)。
|
||||
> **导出 gate(D3)**:含 scene 的事件暂不可编译导出(需 P3 引擎支持),`compile_ir` 遇 scene 报错拦下;校验/白模预览不受限。
|
||||
> v0.2 变更(M4):新增 `sequences`/`out_ref`(子序列复用)、Option `skip`(押注跳过)、
|
||||
> `stage.point_set`(点位集引用 + 坐标校验);条件/奖励词典外置到 `ir_dictionary.json`。
|
||||
> 校验+编译内核收敛进 `ir_core/` 包(CLI 与 M5 Web 后端共用)。
|
||||
@ -65,6 +68,7 @@ Story IR 是"讲故事"与"编译成配置"两段之间的唯一交接棒。它
|
||||
| `fight` | `fight_type`(1 击倒/2 死斗), `camp2`:[slot], `camp1?`:[slot], `win`, `lose` | type0;`camp2Fighters`,`fightStatus`=[type,win,lose] |
|
||||
| `reward` | `grants`:[Grant], `next` | type0;`resultRewardIds` 或 `roleActionCode` |
|
||||
| `out_ref` | `ref`(子序列 id), `next` | 编译前预展开成普通节点(见 §4.1);本节点不直接产行 |
|
||||
| `scene` | `tracks`:[Track], `duration?`, `next` | **P2 多轨演出段**(见 §4.2);并行+时间偏移容器。导出 gate(D3):编译期报错,暂不产行(需 P3 引擎) |
|
||||
|
||||
### 4.1 Sequence / out_ref(子序列复用,对应 `OutRefStoryNodeData`)
|
||||
|
||||
@ -81,6 +85,52 @@ Story IR 是"讲故事"与"编译成配置"两段之间的唯一交接棒。它
|
||||
- **多处复用不撞 id**:不同 `out_ref` 节点前缀不同 → 各自一份独立行。
|
||||
- **限制**:M4 仅支持**一层**(子序列内不得再含 `out_ref`),违者校验报错;子序列内跳转目标须落在子序列内或共享结局。
|
||||
|
||||
### 4.2 scene / Track / Clip(多轨演出段,P2 新增)
|
||||
|
||||
`scene` 是一段被分支夹着的**连续并行演出**(对应影视「一镜到底的演出段」):多条轨道同时推进,
|
||||
每个 clip 有场景内绝对起始秒 `start`,因此「角色 A 走到点 1,1.5 秒后角色 B 才开始走、两者时间重叠」
|
||||
这类语义成为一等公民。scene 内**不含分支**(D2),有单一 `next` 出口;需要选择/战斗/随机仍用图级节点。
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"id": "sc_intro",
|
||||
"kind": "scene",
|
||||
"next": "choice_1", // 单一出口(D2)
|
||||
"duration": 8.5, // 可选;缺省 = 所有 clip end 的最大值
|
||||
"tracks": [ Track, ... ]
|
||||
}
|
||||
```
|
||||
|
||||
**Track(轨道)**
|
||||
```jsonc
|
||||
{ "id": "tk_p1", "actor": "P1", "clips": [ Clip, ... ] } // 演员轨:actor=角色 slot(P1/NP1…)
|
||||
{ "id": "tk_cam", "role": "camera", "clips": [ Clip, ... ] } // 镜头轨:role="camera"
|
||||
```
|
||||
- 演员轨绑定一个 slot,承载该角色的 move/anim/dialogue/narration。
|
||||
- 镜头轨 `role:"camera"`,承载 camera clip(不校验 actor)。
|
||||
- 推荐单 actor 单轨;一个 actor 多轨亦可(校验不强制,但**同 actor 的 move 跨轨也不得时间重叠**)。
|
||||
|
||||
**Clip(片段)**:通用字段 `id`(scene 内唯一)、`kind`、`start`(场景内绝对秒,≥0)、`dur`(可选,按 kind 派生)。
|
||||
|
||||
| kind | 字段 | dur 来源 |
|
||||
|---|---|---|
|
||||
| `move` | `to`(点位名), `speed?`, `dur?` | `dur` > `dist/speed` > `dist/默认速度` |
|
||||
| `dialogue` | `text`, `dur?` | `dur` > `字数×打字速度+尾停` |
|
||||
| `narration` | `text`, `dur?` | 同 dialogue |
|
||||
| `anim` | `ani`, `angle?`, `dur?` | `dur` > 缺省 1.0s(P3 由引擎动画时长表回填) |
|
||||
| `camera` | `focus`(点位名), `dur?` | `dur` > 缺省 2.0s |
|
||||
| `wait` | (仅占位), `dur` | 显式 `dur` |
|
||||
|
||||
- **D4 move 时长派生、位置隐式**:clip 的 `start` 由作者编排;move 的 `dur` 默认由 `dist(from→to)/speed` 派生(可显式 `dur` 覆盖)。
|
||||
move 的 `from` **不存**,运行期由「同 actor 轨上一段 move 的 `to`」推出(无则取点位集初始锚点)。
|
||||
- 校验约束:**同一 actor 的 move 之间时间上不得重叠**(一个人不能同时走两处);dialogue/anim 可与本人 move 重叠(边走边说)。
|
||||
- 时长/打字速度常量与白模预览 `timeline.js` 共享(CHAR_TIME/TAIL_PAUSE/MIN_DLG/MOVE_SPEED/ANIM_DUR/CAMERA_DUR)。
|
||||
- 样张:`samples/scene_demo.ir.json`(A 走、1.5s 后 B 走,两者重叠)。
|
||||
|
||||
> **P3 衔接契约**:scene/track/clip 即 P3 `StoryTimelineData` 的序列化源。引擎进入 scene 时对每 clip 按 `start` 排程
|
||||
> (`UniTask.Delay`),move 用现有多 agent 并发寻路,dialogue 走打字机,camera 设 `otherTarget`,wait 纯延时;
|
||||
> 在 `max(clip.end)` 或显式 `duration` 后推进 `next`。故 IR **不写** move 的 `from`/绝对坐标(引擎自点位集+轨道续连推)。
|
||||
|
||||
### Option(选项)
|
||||
```jsonc
|
||||
{ "text": "收留他", "condition": Condition?, "reward": {"grants":[Grant]}?,
|
||||
|
||||
Reference in New Issue
Block a user