Co-authored-by: manus <manus@noreply.143.198.27.163> Co-committed-by: manus <manus@noreply.143.198.27.163>
76 lines
2.2 KiB
JavaScript
76 lines
2.2 KiB
JavaScript
import * as THREE from 'three';
|
|
import { THEME } from './core/theme.js';
|
|
import { S } from './state.js';
|
|
import { Broadcaster } from './state.js';
|
|
|
|
export class SovOS {
|
|
constructor(scene) {
|
|
this.scene = scene;
|
|
this.apps = new Map();
|
|
this.init();
|
|
}
|
|
|
|
init() {
|
|
this.container = new THREE.Group();
|
|
this.container.position.set(0, 3, -7.5);
|
|
this.scene.add(this.container);
|
|
}
|
|
|
|
registerApp(id, config) {
|
|
const app = this.createWindow(id, config);
|
|
this.apps.set(id, app);
|
|
this.container.add(app.group);
|
|
}
|
|
|
|
createWindow(id, config) {
|
|
const { x, y, rot, title, color } = config;
|
|
const w = 2.8, h = 3.8;
|
|
const group = new THREE.Group();
|
|
group.position.set(x, y || 0, 0);
|
|
group.rotation.y = rot || 0;
|
|
|
|
// Glassmorphism Frame
|
|
const glassMat = new THREE.MeshPhysicalMaterial({
|
|
color: THEME.glass.color,
|
|
transparent: true,
|
|
opacity: THEME.glass.opacity,
|
|
roughness: THEME.glass.roughness,
|
|
metalness: THEME.glass.metalness,
|
|
transmission: THEME.glass.transmission,
|
|
thickness: THEME.glass.thickness,
|
|
ior: THEME.glass.ior,
|
|
side: THREE.DoubleSide
|
|
});
|
|
const frame = new THREE.Mesh(new THREE.PlaneGeometry(w, h), glassMat);
|
|
group.add(frame);
|
|
|
|
// Canvas UI
|
|
const canvas = document.createElement('canvas');
|
|
canvas.width = 512; canvas.height = 700;
|
|
const ctx = canvas.getContext('2d');
|
|
const texture = new THREE.CanvasTexture(canvas);
|
|
const mat = new THREE.MeshBasicMaterial({ map: texture, transparent: true, side: THREE.DoubleSide });
|
|
const screen = new THREE.Mesh(new THREE.PlaneGeometry(w * 0.92, h * 0.92), mat);
|
|
screen.position.z = 0.05;
|
|
group.add(screen);
|
|
|
|
const renderUI = (state) => {
|
|
ctx.clearRect(0, 0, 512, 700);
|
|
// Header
|
|
ctx.fillStyle = 'rgba(0, 0, 0, 0.4)';
|
|
ctx.fillRect(0, 0, 512, 80);
|
|
ctx.fillStyle = '#' + new THREE.Color(color).getHexString();
|
|
ctx.font = 'bold 32px "Orbitron"';
|
|
ctx.fillText(title, 30, 50);
|
|
// Body
|
|
ctx.font = '20px "JetBrains Mono"';
|
|
ctx.fillStyle = '#ffffff';
|
|
config.renderBody(ctx, state);
|
|
texture.needsUpdate = true;
|
|
};
|
|
|
|
Broadcaster.subscribe(renderUI);
|
|
return { group, renderUI };
|
|
}
|
|
}
|