This commit is contained in:
parent
6bc125be1c
commit
ed5a4379db
76 changed files with 1418 additions and 988 deletions
61
src/index.ts
61
src/index.ts
|
|
@ -32,6 +32,15 @@ const main = async () => {
|
|||
let game: GameLoop | null = null;
|
||||
let configPane: ConfigPane | null = null;
|
||||
const getGame = () => game;
|
||||
const destroyCurrentGame = async () => {
|
||||
const currentGame = game;
|
||||
if (!currentGame) {
|
||||
return;
|
||||
}
|
||||
|
||||
game = null;
|
||||
await currentGame.destroy();
|
||||
};
|
||||
|
||||
const errorPresenter = new ErrorPresenter(
|
||||
queryRequiredElement('.errors-container', HTMLElement)
|
||||
|
|
@ -40,7 +49,7 @@ const main = async () => {
|
|||
errorPresenter.render(error);
|
||||
if (error.severity === Severity.ERROR) {
|
||||
document.body.classList.remove('is-loading');
|
||||
game?.destroy();
|
||||
void destroyCurrentGame();
|
||||
shouldStop = true;
|
||||
}
|
||||
});
|
||||
|
|
@ -53,19 +62,24 @@ const main = async () => {
|
|||
const grainOverlay = queryRequiredElement('.garden-grain', HTMLDivElement);
|
||||
const promptElement = queryRequiredElement('.garden-prompt', HTMLDivElement);
|
||||
const exportStatus = queryRequiredElement('.export-status', HTMLSpanElement);
|
||||
const settingsButton = queryRequiredElement('button.settings', HTMLButtonElement);
|
||||
const restartButton = queryRequiredElement('button.restart', HTMLButtonElement);
|
||||
const infoButton = queryRequiredElement('button.info', HTMLButtonElement);
|
||||
const settingsButton = queryRequiredElement(
|
||||
'[data-control="settings"]',
|
||||
HTMLButtonElement
|
||||
);
|
||||
const restartButton = queryRequiredElement(
|
||||
'[data-control="restart"]',
|
||||
HTMLButtonElement
|
||||
);
|
||||
const infoButton = queryRequiredElement('[data-control="info"]', HTMLButtonElement);
|
||||
const infoElement = queryRequiredElement('.info-page', HTMLElement);
|
||||
const minimizeFullScreenButton = queryRequiredElement(
|
||||
'button.minimize-full-screen',
|
||||
const fullScreenButton = queryRequiredElement(
|
||||
'[data-control="full-screen"]',
|
||||
HTMLButtonElement
|
||||
);
|
||||
const maximizeFullScreenButton = queryRequiredElement(
|
||||
'button.maximize-full-screen',
|
||||
const export4kButton = queryRequiredElement(
|
||||
'[data-control="export"]',
|
||||
HTMLButtonElement
|
||||
);
|
||||
const export4kButton = queryRequiredElement('.export-4k', HTMLButtonElement);
|
||||
|
||||
const splash = new SplashScreen();
|
||||
const paletteControl = new PaletteControl({
|
||||
|
|
@ -103,11 +117,7 @@ const main = async () => {
|
|||
!configPane?.isOpen &&
|
||||
!infoPageHandler.isOpen
|
||||
);
|
||||
new FullScreenHandler(
|
||||
minimizeFullScreenButton,
|
||||
maximizeFullScreenButton,
|
||||
document.documentElement
|
||||
);
|
||||
new FullScreenHandler(fullScreenButton, document.documentElement);
|
||||
|
||||
new VibeNavigator({
|
||||
onChange: ({ vibeId, vibeName, source }) => {
|
||||
|
|
@ -119,16 +129,17 @@ const main = async () => {
|
|||
},
|
||||
});
|
||||
|
||||
restartButton.addEventListener('click', () => game?.destroy());
|
||||
restartButton.addEventListener('click', () => void destroyCurrentGame());
|
||||
|
||||
export4kButton.addEventListener('click', async () => {
|
||||
if (!game || export4kButton.disabled) {
|
||||
const currentGame = game;
|
||||
if (!currentGame || export4kButton.disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
export4kButton.disabled = true;
|
||||
try {
|
||||
await game.exportSnapshot();
|
||||
await currentGame.exportSnapshot();
|
||||
trackExport({ vibeId: activeVibe.id });
|
||||
} catch (error) {
|
||||
ErrorHandler.addException(error, { severity: Severity.WARNING });
|
||||
|
|
@ -168,9 +179,15 @@ const main = async () => {
|
|||
);
|
||||
|
||||
const gpu = await gpuPromise;
|
||||
const gpuNavigator = navigator.gpu;
|
||||
if (!gpuNavigator) {
|
||||
throw new Error('WebGPU is no longer available after initialization.');
|
||||
}
|
||||
const canvasFormat = gpuNavigator.getPreferredCanvasFormat();
|
||||
configPane = new ConfigPane({
|
||||
maxSupportedAgentCount: getMaxSupportedAgentCount(gpu),
|
||||
settingsButton,
|
||||
onOpen: () => infoPageHandler.close(),
|
||||
onConfigChange: () => {
|
||||
game?.onVibeChanged();
|
||||
syncRuntimeUi();
|
||||
|
|
@ -186,13 +203,14 @@ const main = async () => {
|
|||
|
||||
let isFirstStart = true;
|
||||
while (!shouldStop) {
|
||||
game = new GameLoop(canvas, gpu, deltaTimeCalculator, {
|
||||
const loop = new GameLoop(canvas, gpu, canvasFormat, deltaTimeCalculator, {
|
||||
toolbar: toolbarRow,
|
||||
prompt: promptElement,
|
||||
eraserPreview,
|
||||
grainOverlay,
|
||||
exportStatus,
|
||||
});
|
||||
game = loop;
|
||||
syncRuntimeUi();
|
||||
audioControl.render();
|
||||
|
||||
|
|
@ -211,8 +229,11 @@ const main = async () => {
|
|||
requestAnimationFrame(() => document.body.classList.remove('is-loading'))
|
||||
);
|
||||
}
|
||||
game.attachPointerInput();
|
||||
await game.start();
|
||||
loop.attachPointerInput();
|
||||
await loop.start();
|
||||
if (game === loop) {
|
||||
game = null;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
document.body.classList.remove('is-loading');
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue