import { Application, Container } from 'pixi.js'; // Static imports on purpose: Pixi registers render pipes (graphics, text, sprite) as a // module side effect, and a renderer only knows the pipes that exist when it is created. // Lazy chunks loaded after `app.init()` would therefore fail with "unknown render pipe". import { captureConsole } from './editor/console/log'; import { startEditor } from './editor/App'; import { mountPlayground } from './playground'; import { initUI, Theme, VStack } from './ui'; // Before anything else: a renderer warns while it is being created, and those warnings are // exactly the ones worth having in the panel. captureConsole(); // `desynchronized` bypasses the compositor queue (headless click-to-paint 72 → 16 ms) but may // tear; `?vsync` opts out. Pixi has no option for it, hence our own context. function lowLatencyContext(): { canvas?: HTMLCanvasElement; context?: WebGL2RenderingContext } { const canvas = document.createElement('canvas'); const context = canvas.getContext('webgl2', { alpha: false, antialias: true, premultipliedAlpha: true, stencil: true, desynchronized: true, }); return context ? { canvas, context } : {}; } async function main(): Promise { const params = new URLSearchParams(location.search); const app = new Application(); await app.init({ resizeTo: window, background: Theme.colors.background, antialias: true, resolution: Math.min(2, window.devicePixelRatio || 1), autoDensity: true, preference: 'webgl', ...(params.has('vsync') ? {} : lowLatencyContext()), }); document.body.appendChild(app.canvas); const root = new VStack(); const overlay = new Container(); app.stage.addChild(root, overlay); app.stage.eventMode = 'static'; app.stage.hitArea = app.screen; initUI(app, root, overlay); if (params.has('playground')) mountPlayground(app, root); else await startEditor(app, root); app.renderer.on('resize', () => { app.stage.hitArea = app.screen; root.resize(app.screen.width, app.screen.height); }); } window.addEventListener('error', (event) => { const error: unknown = event.error; console.error('[uncaught]', error instanceof Error ? error.stack : event.message); }); main().catch((error) => { console.error(error); document.body.innerHTML = `
${String(error)}
`; });