SCENEGOD/scenegod/web/index.html
type-two de3416869f [laneA] M1: Stage viewport, retarget port, dock+inspector
- room3d.js: pure-module port of rigroom retarget, target parameterized;
  _selftest bakes across two mismatched-rest skeletons (maxErr 6.4e-12)
- stage.js: Stage class (IBL, gizmo, entities, clip bake cache) per PLAN §4.2
- dock.js: asset dock + inspector, offline file-drop + clip retarget
- index.html/style.css: grid layout, guarded timeline import (page survives B absent)

Verified in-browser end-to-end: Mixamo char loaded+normalized, backdrop plane,
gizmo move, running clip retargeted (66 tracks) and animating live.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 18:06:22 +10:00

58 lines
1.8 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>SCENEGOD — machinima stage</title>
<link rel="stylesheet" href="/web/style.css">
</head>
<body>
<header>
<h1>🎬 SCENEGOD</h1><span class="tag">machinima stage</span>
<span id="selftest"></span>
</header>
<div id="app">
<aside id="dock"></aside>
<div id="view"></div>
<aside id="inspector"><div class="empty">nothing selected</div></aside>
<div id="timeline"><div class="empty">timeline — Lane B mounts here</div></div>
</div>
<script type="importmap">
{ "imports": {
"three": "https://unpkg.com/three@0.160.0/build/three.module.js",
"three/addons/": "https://unpkg.com/three@0.160.0/examples/jsm/"
}}
</script>
<script type="module">
import { Stage } from '/web/stage.js';
import { Dock } from '/web/dock.js';
// retarget self-check (?selftest=1) — proves the crown-jewel bake before anything else
if(new URLSearchParams(location.search).has('selftest')){
const { _selftest } = await import('/web/room3d.js');
const r = _selftest();
const el = document.getElementById('selftest');
el.textContent = `selftest: ${r.ok ? 'PASS' : 'FAIL'} (maxErr=${r.maxErr.toExponential(2)})`;
el.className = r.ok ? 'ok' : 'bad';
console.log('[room3d selftest]', r);
}
const stage = new Stage(document.getElementById('view'));
const dock = new Dock({
stage,
dockEl: document.getElementById('dock'),
inspectorEl: document.getElementById('inspector'),
viewEl: document.getElementById('view'),
});
// Timeline is optional — the page must never break when Lane B's file is absent
try {
const { Timeline } = await import('/web/timeline.js');
window.timeline = new Timeline(stage);
} catch(e){ /* timeline.js not present yet */ }
window.stage = stage; window.dock = dock;
</script>
</body>
</html>