Erste lauffähige Fassung: 3D-Raum, Echtzeit-Multiplayer (WebSocket), Python-IDE via Pyodide im Browser, eigener Arbeitsplatz mit Live-Code-Monitor. Modularer, self-hostbarer Aufbau (Three.js + Node/Express + ws), ohne CDN- Abhängigkeit zur Laufzeit. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
58 lines
2.3 KiB
JavaScript
58 lines
2.3 KiB
JavaScript
// ui.js — DOM-Oberfläche: Start-Overlay, Toolbar, HUD-Anzeigen, Fehleranzeige.
|
|
// Kennt Three.js/Netzwerk nicht — kommuniziert per Callbacks.
|
|
|
|
export class UI {
|
|
constructor() {
|
|
this.overlay = document.getElementById('overlay');
|
|
this.toolbar = document.getElementById('toolbar');
|
|
this.errBox = document.getElementById('err');
|
|
this.el = {
|
|
dbg: document.getElementById('dbg'),
|
|
net: document.getElementById('net'),
|
|
fps: document.getElementById('fps'),
|
|
count: document.getElementById('count'),
|
|
help: document.getElementById('helpBtn'),
|
|
ide: document.getElementById('ideBtn'),
|
|
};
|
|
this._startCb = null;
|
|
this._helpCb = null;
|
|
this._ideCb = null;
|
|
this._helpOn = false;
|
|
|
|
document.getElementById('startbtn').addEventListener('click', () => this._start());
|
|
document.getElementById('name').addEventListener('keydown', (e) => { if (e.key === 'Enter') this._start(); });
|
|
this.el.help.addEventListener('click', () => this._toggleHelp());
|
|
this.el.ide.addEventListener('click', () => { if (this._ideCb) this._ideCb(); });
|
|
}
|
|
|
|
_start() {
|
|
const name = (document.getElementById('name').value || 'Gast').trim().slice(0, 24) || 'Gast';
|
|
const role = document.getElementById('role').value;
|
|
this.overlay.style.display = 'none';
|
|
this.toolbar.style.display = 'flex';
|
|
if (this._startCb) this._startCb(name, role);
|
|
}
|
|
|
|
_toggleHelp() {
|
|
this._helpOn = !this._helpOn;
|
|
this.el.help.classList.toggle('on', this._helpOn);
|
|
this.el.help.textContent = this._helpOn ? '✋ Hilfe angefragt (klick = zurück)' : '✋ Hilfe anfragen';
|
|
if (this._helpCb) this._helpCb(this._helpOn);
|
|
}
|
|
|
|
onStart(cb) { this._startCb = cb; }
|
|
onHelpToggle(cb) { this._helpCb = cb; }
|
|
onOpenIde(cb) { this._ideCb = cb; }
|
|
|
|
setDbg(s) { if (this.el.dbg) this.el.dbg.textContent = s; }
|
|
setNet(text, color) { if (this.el.net) { this.el.net.textContent = text; this.el.net.style.color = color || '#f9e2af'; } }
|
|
setFps(n) { if (this.el.fps) this.el.fps.textContent = n; }
|
|
setCount(n) { if (this.el.count) this.el.count.textContent = n; }
|
|
|
|
showError(where, e) {
|
|
if (!this.errBox) return;
|
|
this.errBox.style.display = 'block';
|
|
this.errBox.textContent = '⚠ Fehler in ' + where + ':\n' + (e && (e.stack || e.message) || e);
|
|
this.setDbg('FEHLER @ ' + where);
|
|
}
|
|
}
|