feat(timeline): P1 白模演出预览——时间线+俯视舞台播放

- /api/pointsets 增 anchors(含 pos/rot/kind/npc 坐标),保留 points 名字数组兼容下拉
- 新增 static/timeline.js:线性化主路径→按时长铺多轨时间线 + 2D 俯视白模舞台播放
  (走位插值/对话打字机/镜头俯视框示意/playhead/点击跳转);战斗/选择/随机仅标点不模拟
- 工具栏加「演出预览」按钮 + 预览遮罩 + 暗金主题样式
- 时长模型:对话=字数×打字机速度,走位=坐标距离÷速度,动画/镜头给缺省时长
- node 离线测试两样张(含 out_ref+fight+skip)逻辑全过;修掉结局重复渲染 bug

设计文档见主仓 docs/plans/2026-06-13-story-timeline-editor-and-whitebox-preview-design.md (P1 期)
This commit is contained in:
2026-06-13 10:52:20 +08:00
parent 81f62db9f3
commit dbf857769e
5 changed files with 431 additions and 2 deletions

View File

@ -163,9 +163,21 @@ async def pointsets():
try:
with open(os.path.join(_POINTSETS_DIR, fn), encoding="utf-8") as f:
ps = json.load(f)
pts = ps.get("points", [])
out[name] = {
"mapId": ps.get("mapId", ""),
"points": [p.get("name") for p in ps.get("points", [])],
"points": [p.get("name") for p in pts], # 名字数组:兼容现有表单下拉
# 含坐标的锚点白模演出预览用map-local pos[x,y,z] + rot
"anchors": [
{
"name": p.get("name"),
"pos": p.get("pos") or [0, 0, 0],
"rot": p.get("rot", 0),
"kind": p.get("kind", ""),
"npc": p.get("npc", ""),
}
for p in pts
],
}
except Exception as e:
out[name] = {"error": str(e)}