muse-engine-29 / index.html
axonis22's picture
Muse Engine 29 - Look Picker (Phase 29 engine, Look A + Look B by Muse Glimmer, lamp fix)
8fb1496 verified
Raw History Blame Contribute Delete
12.6 kB
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Muse Engine 29 - Look Picker</title>
<style>
:root {
--bg: #070a10;
--panel: rgba(12, 18, 28, 0.92);
--line: #1e2a3c;
--text: #d7e6ff;
--muted: #8aa0c0;
--accent: #5ec8ff;
--ok: #3ecf8e;
--warn: #e6b84d;
--freeze: #6ea8ff;
--next: #b388ff;
}
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; background: var(--bg); color: var(--text);
font-family: "Segoe UI", system-ui, Roboto, sans-serif; }
body { display: grid; grid-template-columns: 340px 1fr; min-height: 100vh; }
#side {
background: var(--panel); border-right: 1px solid var(--line);
padding: 16px 14px 24px; overflow-y: auto; z-index: 2;
}
#side h1 { margin: 0 0 4px; font-size: 16px; letter-spacing: .3px; }
#side .sub { color: var(--muted); font-size: 12px; margin-bottom: 14px; line-height: 1.35; }
.btnrow { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px; }
a.btn, button.btn {
display: inline-block; text-decoration: none; color: #061018; background: var(--freeze);
border: 0; border-radius: 8px; padding: 8px 12px; font-size: 12px; font-weight: 600;
cursor: pointer;
}
a.btn.secondary, button.btn.secondary { background: #243247; color: var(--text); }
a.btn.ok { background: var(--ok); color: #042016; }
.section { margin-top: 16px; }
.section h2 { margin: 0 0 8px; font-size: 12px; text-transform: uppercase;
letter-spacing: .08em; color: var(--muted); }
.phases { display: flex; flex-direction: column; gap: 6px; }
.phase {
border: 1px solid var(--line); border-radius: 10px; padding: 8px 10px;
background: rgba(255,255,255,0.02); cursor: pointer;
}
.phase:hover { border-color: #2f4058; }
.phase.active { border-color: var(--next); box-shadow: 0 0 0 1px rgba(179,136,255,.35); }
.phase .top { display: flex; justify-content: space-between; gap: 8px; align-items: baseline; }
.phase .num { font-weight: 700; font-size: 13px; }
.phase .tag {
font-size: 10px; text-transform: uppercase; letter-spacing: .06em;
padding: 2px 6px; border-radius: 999px; background: #1a2433; color: var(--muted);
}
.phase .tag.done { background: rgba(62,207,142,.15); color: var(--ok); }
.phase .tag.now { background: rgba(179,136,255,.18); color: #d2b8ff; }
.phase .tag.park { background: rgba(230,184,77,.14); color: var(--warn); }
.phase .tag.plan { background: rgba(110,168,255,.12); color: var(--freeze); }
.phase p { margin: 4px 0 0; font-size: 11px; color: var(--muted); line-height: 1.35; }
.checks label {
display: flex; gap: 8px; align-items: flex-start; font-size: 12px;
color: var(--text); margin: 6px 0; cursor: pointer;
}
.checks input { margin-top: 2px; }
.note {
font-size: 11px; color: var(--muted); line-height: 1.4;
border-left: 2px solid var(--line); padding-left: 8px; margin-top: 8px;
}
#stage { position: relative; min-height: 100vh; background: #05070c; }
#muse-canvas { display: block; width: 100%; height: 100vh; cursor: grab; background: #06080c; }
#muse-canvas:active { cursor: grabbing; }
#hud {
position: absolute; left: 12px; bottom: 12px; color: #cfe8ff; font-size: 12px;
background: rgba(0,0,0,.4); padding: 6px 10px; border-radius: 8px; pointer-events: none;
}
#banner {
position: absolute; left: 12px; top: 12px; right: 12px; max-width: 520px;
background: rgba(0,0,0,.45); color: #9ecbff; font-size: 12px;
padding: 8px 10px; border-radius: 8px; pointer-events: none; line-height: 1.35;
}
#credit {
position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%);
background: rgba(0,0,0,.75); color: #fff; padding: 20px 28px; border-radius: 14px;
text-align: center; pointer-events: none; opacity: 0; transition: opacity .6s; z-index: 5;
}
#credit.show { opacity: 1; }
#credit h1 { margin: 0 0 6px; font-size: 20px; }
#credit p { margin: 4px 0; color: #bcd6ff; font-size: 12px; }
@media (max-width: 900px) {
body { grid-template-columns: 1fr; }
#side { max-height: 42vh; }
#muse-canvas { height: 58vh; }
}
</style>
<link rel="stylesheet" href="engine/ui/e29-ui.css" />
<script type="importmap">
{ "imports": { "three": "./engine/vendor/three/three.core.min.js", "three/addons/": "./engine/vendor/three/addons/" } }
</script>
</head>
<body>
<aside id="side">
<h1>Muse Engine 29 · Look Picker</h1>
<div class="sub">Phase 29 engine (combat feel + Phase 28 movement) with two switchable looks. Look B scene + character models authored by Muse Glimmer. Raw WebGL1 renderer.</div>
<div class="section">
<h2>Look</h2>
<div class="btnrow" id="look-buttons"></div>
<p class="note" id="look-note">L cycles looks in-game · Tab opens the config panel (look, model import, gameplay toggles). Visuals only: colliders and hitboxes are the same in every look.</p>
</div>
<div class="btnrow">
<button class="btn" type="button" id="btn-config">Config (Tab)</button>
<button class="btn secondary" type="button" id="btn-credit">Flash credit</button>
<button class="btn secondary" type="button" id="btn-focus">Focus canvas</button>
</div>
<div class="section">
<h2>Phases 24 → 32</h2>
<div class="phases" id="phase-list"></div>
<p class="note">Select a phase to mark the lab focus (saved in this browser).</p>
</div>
<div class="section">
<h2>Look / model checks (Phase 25–27+)</h2>
<div class="checks" id="look-checks">
<label><input type="checkbox" data-k="normals" /> Normals readable at distance (outside shapes)</label>
<label><input type="checkbox" data-k="tex" /> Base-color textures / material reads (paint, metal, rubber)</label>
<label><input type="checkbox" data-k="nm" /> Phase 26: normal maps sample on look GLB (ToyCar NM)</label>
<label><input type="checkbox" data-k="bollard" /> Phase 27: Mooring Bollard visible (Key K toggle)</label>
<label><input type="checkbox" data-k="glb" /> At least one showroom-grade textured GLB in look pack</label>
<label><input type="checkbox" data-k="toycar" /> Bar = showroom end cars (Khronos textured GLB preferred)</label>
<label><input type="checkbox" data-k="lookb" /> Look B (Muse) swap tested with L (game still playable)</label>
<label><input type="checkbox" data-k="parkour28" /> Phase 28: parkour steps + ladder climb + Space jump</label>
<label><input type="checkbox" data-k="combat29" /> Phase 29: hostiles blocked by buildings + fall-then-boom kills</label>
</div>
</div>
<div class="section">
<h2>Controls (current engine)</h2>
<p class="note">Click to aim · WASD move · Mouse look · Space jump · LMB shoot · R reload · E door · Ctrl crouch · N night · <b>L</b> next look · <b>Tab</b> config panel · Shift+L load a GLB prop · K bollard on/off · T char shapes · O orbit cam · C credit · Esc release mouse</p>
</div>
</aside>
<main id="stage">
<canvas id="muse-canvas"></canvas>
<div id="banner">Muse Engine 29 · L = next look · Tab = config · hostiles fall then boom · P28 parkour</div>
<div id="hud">Muse Glimmer · Muse Engine 29 · Look Picker</div>
<div id="credit">
<h1>MUSE ENGINE 29</h1>
<p>WebGL1 · Phase 29 combat feel · Look Picker</p>
<p>Look B scene + characters authored by Muse Glimmer</p>
</div>
</main>
<script>
(function () {
var PHASES = [
{ n: 24, tag: 'done', title: 'Freeze', blurb: 'Mitsh polish + Mitch parkour jump-blocks. Playable. Climb/ladder experiments parked in TRACK.' },
{ n: 25, tag: 'done', title: 'Lean + look', blurb: 'Leaner scene + shootable hostiles. Textured multi-mesh GLB (textured GLB). Key K look toggle. Climb/jump/parkour frozen from P24.' },
{ n: 26, tag: 'done', title: 'Normal maps (NM)', blurb: 'Sample GLB normalTexture on look props (bay look GLB via Key L). TBN from tangents/UV. Ladder/jumps still PARKED in TRACK — not this phase.' },
{ n: 27, tag: 'done', title: 'Mooring Bollard mesh', blurb: 'Muse pick: pierMooringBollard - in-engine bollard near pier. Key K. TEX+NM kept.' },
{ n: 28, tag: 'done', title: 'Parkour Climb', blurb: 'Land on tops, coyote/buffer jump, step-up/mantle, climbable ladder + short parkour route right of spawn. Movement-only; look/shoot kept.' },
{ n: 29, tag: 'now', title: 'Combat Feel + Look Picker', blurb: 'Hostile solid AABB vs buildings/props (no wall-clip). Kill = visible fall/tip then boom/despawn. This release adds a look picker: Look A (Phase 29) / Look B (Muse).' },
{ n: 30, tag: 'plan', title: 'Prop / scene pass', blurb: 'Lean scene props + textured ground/walls; distance silhouette on fewer, better meshes.' },
{ n: 31, tag: 'plan', title: 'Hostile / char looks', blurb: 'Character/hostile meshes closer to textured bar; Key T packs stay.' },
{ n: 32, tag: 'plan', title: 'Diary + compare / picker', blurb: 'Diary clip; compare vs showroom look bar; stabilize Muse engine for later picker if Paul greenlights.' }
];
var list = document.getElementById('phase-list');
var hud = document.getElementById('hud');
var banner = document.getElementById('banner');
var key = 'muse-engine-29.lab';
var state = { phase: 29, checks: {} };
try {
var raw = localStorage.getItem(key);
if (raw) state = Object.assign(state, JSON.parse(raw));
} catch (e) {}
var q = new URLSearchParams(location.search).get('phase');
if (q && !isNaN(+q)) state.phase = +q;
function save() {
try { localStorage.setItem(key, JSON.stringify(state)); } catch (e) {}
}
function tagClass(t) {
if (t === 'done') return 'done';
if (t === 'now') return 'now';
if (t === 'park') return 'park';
return 'plan';
}
function renderPhases() {
list.innerHTML = '';
PHASES.forEach(function (p) {
var el = document.createElement('div');
el.className = 'phase' + (state.phase === p.n ? ' active' : '');
el.innerHTML = '<div class="top"><span class="num">Phase ' + p.n + ' · ' + p.title + '</span><span class="tag ' + tagClass(p.tag) + '">' + p.tag + '</span></div><p>' + p.blurb + '</p>';
el.onclick = function () {
state.phase = p.n;
save();
renderPhases();
syncHud();
history.replaceState(null, '', '?phase=' + p.n);
};
list.appendChild(el);
});
}
function syncHud() {
var p = PHASES.filter(function (x) { return x.n === state.phase; })[0];
hud.textContent = 'Muse Glimmer · Phase Lab · focus P' + state.phase + (p ? ' · ' + p.title : '');
banner.textContent = 'Focus Phase ' + state.phase + (p ? ' — ' + p.title + '. ' + p.blurb : '');
}
document.querySelectorAll('#look-checks input').forEach(function (inp) {
var k = inp.getAttribute('data-k');
inp.checked = !!state.checks[k];
inp.onchange = function () {
state.checks[k] = inp.checked;
save();
};
});
document.getElementById('btn-credit').onclick = function () {
var c = document.getElementById('credit');
c.classList.add('show');
setTimeout(function () { c.classList.remove('show'); }, 2200);
};
document.getElementById('btn-config').onclick = function () { if (window.E29Panel) window.E29Panel.open(); };
function renderLookButtons() {
var box = document.getElementById('look-buttons');
if (!box || !window.MuseLooks) return;
box.innerHTML = '';
window.MuseLooks.list().forEach(function (l) {
var b = document.createElement('button');
b.type = 'button';
b.className = 'btn' + (window.MuseLooks.active() === l.id ? '' : ' secondary');
b.textContent = 'Look ' + l.id + ' · ' + l.name;
b.onclick = function () { window.MuseLooks.setActive(l.id); };
box.appendChild(b);
});
}
window.addEventListener('load', function () {
renderLookButtons();
if (window.MuseLooks && window.MuseLooks.onChange) window.MuseLooks.onChange(renderLookButtons);
});
document.getElementById('btn-focus').onclick = function () {
document.getElementById('muse-canvas').focus();
document.getElementById('muse-canvas').click();
};
renderPhases();
syncHud();
})();
</script>
<script src="engine/looks/look-switcher.js?v=e29"></script>
<script src="game/looks/look-a.js?v=e29"></script>
<script src="game/looks/look-b.js?v=e29"></script>
<script src="engine/engine.js?v=e29-lookpicker"></script>
<script src="engine/ui/start-screen.js?v=e29"></script>
<script src="engine/ui/config-panel.js?v=e29"></script>
</body>
</html>