feat(pointview): 新增「场景/点位」页签——正交俯视真实场景底图 + 点位精确叠加

第三个页签(与海选审核/演出配置平级),只读查看每个点位集里各点的真实
位置/朝向,配 move.to/camera.focus 时对照用,不必回 Unity 翻 json。

- pointview.js: 独立白模点位查看器(按 kind 上色/朝向箭头/悬停坐标/侧栏清单);
  有底图则把正交俯视真实场景图当画布底图、点位按 shot.bounds 线性投上去
  (像素级对齐家具),带显隐开关;无底图回退黑底白模。
- app.py: /api/pointsets 给有底图的点位集附 shot{url,bounds};新增
  /sceneshot/{name}.png 路由(防目录穿越)。
- Dockerfile/compose: 加 STORY_SCENESHOTS_DIR(/sceneshots) env + 挂载点与注释。

底图由 SGame 仓新增 Editor 工具「剧情场景俯视抓拍」产出
({name}.png + {name}.shot.json,map-local 覆盖范围)。
This commit is contained in:
2026-06-14 11:13:24 +08:00
parent 030f1ee34d
commit 603f78b77f
9 changed files with 414 additions and 4 deletions

View File

@ -255,6 +255,55 @@ body.perform-mode .mode-switch { border-color:#2f7a60; }
#perform-main { flex:1; min-width:0; display:flex; flex-direction:column; padding:14px 16px; min-height:0; }
#perform-main .empty-center { position:static; inset:auto; min-height:240px; }
/* ---- 场景/点位页:靛蓝色调,区分于海选(棕)/演出(青绿) ---- */
body.points-mode { background:#0d0f17; }
body.points-mode header { background:#11142a; border-bottom-color:#2c3160; }
body.points-mode .mode-btn.active { background:#2e3470; border-color:#4a52a0; color:#c5cbf0; }
body.points-mode .mode-switch { border-color:#4a52a0; }
#points-wrap { display:flex; flex:1; min-height:0; background:#0d0f17; }
#wrap.hidden, #perform-wrap.hidden, #points-wrap.hidden { display:none; }
#points-list-pane { width:250px; background:#12152a; border-right:1px solid #262c52;
display:flex; flex-direction:column; flex:none; }
#points-list-pane .perform-listhead { background:#11142a; color:#aab0e0; border-bottom-color:#262c52; }
#points-set-list { overflow:auto; flex:1; }
#points-set-list .ev { border-bottom-color:#1c2040; }
#points-set-list .ev:hover { background:#1a1f3e; }
#points-set-list .ev.sel { background:#222853; border-left-color:#6b73c8; }
#points-main { flex:1; min-width:0; display:flex; flex-direction:column; padding:14px 16px; min-height:0; position:relative; }
#points-main .empty-center { position:static; inset:auto; min-height:240px; }
#points-view { flex:1; min-height:0; display:flex; flex-direction:column; }
#points-view:empty { display:none; }
.pv-head { flex:none; font-size:13px; color:#aab0e0; margin-bottom:8px; }
.pv-head b { color:#e6e9ff; }
.pv-bgtag { color:#9aa0d0; } .pv-bgtag input { vertical-align:middle; margin-right:3px; }
.pv-nobg { color:#7077a8; font-size:12px; }
.pv-body { flex:1; min-height:0; display:flex; gap:12px; }
.pv-stagewrap { position:relative; flex:1; min-width:0; min-height:0; background:#0f1714;
border:1px solid #262c52; border-radius:6px; overflow:hidden; }
.pv-stage { display:block; }
.pv-noanchor { position:absolute; inset:0; display:flex; flex-direction:column; align-items:center;
justify-content:center; text-align:center; color:#8088c0; font-size:13px; line-height:1.7; padding:20px; }
.pv-tip { position:absolute; z-index:5; background:rgba(16,18,34,.95); border:1px solid #4a52a0;
border-radius:5px; padding:6px 9px; font-size:11.5px; color:#dfe2ff; pointer-events:none;
white-space:nowrap; line-height:1.5; box-shadow:0 2px 10px rgba(0,0,0,.5); }
.pv-tip.hidden { display:none; }
.pv-tip b { color:#fff; }
.pv-side { width:230px; flex:none; display:flex; flex-direction:column; min-height:0; }
.pv-legend { flex:none; display:flex; flex-wrap:wrap; gap:8px 12px; padding:4px 2px 10px; font-size:11px; color:#9aa0d0; }
.pv-leg { display:inline-flex; align-items:center; gap:5px; }
.pv-leg i { width:11px; height:11px; border-radius:50%; display:inline-block; border:1px solid #000; }
.pv-leg-hint { color:#7077a8; }
.pv-listhead { flex:none; font-size:11px; color:#8088c0; letter-spacing:.5px; padding:6px 2px; border-top:1px solid #262c52; }
.pv-list { flex:1; overflow:auto; }
.pv-item { display:flex; align-items:center; gap:7px; padding:5px 7px; border-radius:4px; cursor:pointer; font-size:12px; }
.pv-item:hover { background:#1a1f3e; }
.pv-item.sel { background:#262c5c; }
.pv-dot { width:9px; height:9px; border-radius:50%; flex:none; border:1px solid #000; }
.pv-nm { color:#dfe2ff; flex:none; }
.pv-pos { color:#7e85b8; font-size:10.5px; margin-left:auto; text-align:right; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* ---- 演出预览:上=舞台面板(自适应放大) / 下=时间轴面板(可拖高度) ---- */
.tl-stagepanel { flex:1 1 auto; min-height:150px; display:flex; flex-direction:column; }
.tl-mapinfo { flex:none; font-size:12px; color:#9a8f7e; margin-bottom:6px; }