Files
yawn/server/web/playground.html

289 lines
10 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#f7fbff" />
<meta
name="description"
content="Write, run, profile, and share Yawn WebGPU scenes."
/>
<title>Yawn Playground</title>
<script src="/assets/theme.js"></script>
<link rel="stylesheet" href="/assets/playground.css" />
<link rel="stylesheet" href="/assets/theme.css" />
<script type="importmap">
{
"imports": {
"@yawn/core": "/pkg/core.js",
"@yawn/handles": "/pkg/handles.js"
}
}
</script>
<script src="/assets/monaco/vs/loader.js"></script>
<script type="module" src="/assets/playground.js"></script>
</head>
<body>
<main class="playground-app">
<header class="playground-header">
<a class="playground-brand" href="/" aria-label="Yawn home">
<span class="brand-mark" aria-hidden="true"
><i></i><i></i><i></i></span
><strong>Yawn</strong>
</a>
<div class="header-divider"></div>
<div class="project-name">
<input
id="project-title"
maxlength="80"
value="Three-light icosphere"
aria-label="Playground title"
/>
<span id="dirty-indicator" title="Unsaved changes"></span>
<span id="revision-label">Draft</span>
</div>
<nav class="playground-nav" aria-label="Playground links">
<a href="/docs">Docs</a>
<a href="https://git.heaust.org/heaust/yawn">Source</a>
</nav>
<select class="theme-select" data-theme-select aria-label="Color theme">
<option value="auto">Auto</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
<button id="share-button" class="tool-button" type="button" hidden>
<span aria-hidden="true">↗</span> Share
</button>
<button id="save-button" class="tool-button" type="button">
<span aria-hidden="true">◇</span> Save
</button>
<button id="run-button" class="run-button" type="button">
<span aria-hidden="true">▶</span> Run <kbd>Ctrl ↵</kbd>
</button>
</header>
<div class="playground-tools">
<div class="tool-group">
<button id="snippets-button" type="button">
<span class="braces">{ }</span> Snippets
</button>
<button id="reset-button" type="button">
<span aria-hidden="true">↶</span> Reset
</button>
<button id="format-button" type="button">
<span aria-hidden="true">≡</span> Format
</button>
</div>
<div class="tool-context">
<span class="language-dot"></span>
<span>TypeScript</span>
<span class="context-divider"></span>
<span id="type-status">Starting language service…</span>
</div>
<div class="tool-group tool-group-right">
<button id="inspector-button" type="button" aria-pressed="true">
<span aria-hidden="true">▤</span> Inspector
</button>
<button
id="fullscreen-button"
type="button"
aria-label="Toggle fullscreen"
>
<span aria-hidden="true">⛶</span>
</button>
</div>
</div>
<div class="workbench" id="workbench">
<section class="editor-pane" aria-label="TypeScript editor">
<div class="pane-tabs">
<button class="pane-tab active" type="button">
<span class="ts-icon">TS</span> scene.ts <i id="tab-dirty"></i>
</button>
</div>
<div id="editor" class="editor">
<div class="editor-loading">Loading TypeScript editor…</div>
</div>
<footer class="editor-status">
<span id="cursor-status">Ln 1, Col 1</span>
<span>Spaces: 2</span>
<span>UTF-8</span>
<span class="status-spacer"></span>
<span id="editor-diagnostics"><i></i> No problems</span>
</footer>
</section>
<div
class="resize-handle"
id="resize-handle"
role="separator"
aria-orientation="vertical"
aria-label="Resize editor and preview"
></div>
<section class="stage-pane" aria-label="Yawn output">
<div class="stage-toolbar">
<div class="stage-tabs">
<button type="button" class="active">Preview</button>
</div>
<div class="stage-meta">
<span id="run-status"><i></i> Ready</span>
<span class="stage-divider"></span>
<span id="fps-status">0 FPS</span>
<span class="stage-divider"></span>
<span id="resolution-status">—</span>
</div>
</div>
<div class="preview" id="preview">
<canvas id="canvas" aria-label="Yawn WebGPU preview"></canvas>
<div class="preview-message" id="preview-message">
<span class="preview-message-icon">Y</span>
<strong>Preparing your scene</strong>
<small>The first run compiles the render graph.</small>
</div>
</div>
<div class="inspector" id="inspector">
<div class="inspector-tabs" role="tablist">
<button
type="button"
class="active"
role="tab"
aria-selected="true"
data-panel="console"
>
Console <span id="console-count">0</span>
</button>
<button
type="button"
role="tab"
aria-selected="false"
data-panel="profile"
>
GPU profiler
</button>
<button id="clear-console" class="clear-console" type="button">
Clear
</button>
</div>
<div
class="console-panel inspector-panel active"
id="console-panel"
role="tabpanel"
>
<div class="console-empty" id="console-empty">
<span>›_</span> Output from <code>log()</code> appears here.
</div>
<ol id="console-lines"></ol>
</div>
<div
class="profile-panel inspector-panel"
id="profile-panel"
role="tabpanel"
>
<div class="profile-empty" id="profile-empty">
<span class="pulse-icon">⌁</span>
<div>
<strong>Waiting for GPU timestamps</strong
><small>Run the scene to inspect its physical passes.</small>
</div>
</div>
<div class="profile-results" id="profile-results" hidden>
<div class="profile-summary">
<div>
<small>Total GPU time</small
><strong id="profile-total">—</strong>
</div>
<div>
<small>Readback latency</small
><strong id="profile-latency">—</strong>
</div>
<div>
<small>Adapter</small
><strong id="profile-adapter">—</strong>
</div>
</div>
<table>
<thead>
<tr>
<th>Physical pass</th>
<th>GPU time</th>
</tr>
</thead>
<tbody id="profile-passes"></tbody>
</table>
</div>
</div>
</div>
</section>
</div>
</main>
<dialog id="snippets-dialog" class="snippets-dialog">
<div class="dialog-heading">
<div>
<span>Code library</span>
<h2>Snippets</h2>
<p>Insert a focused building block at your cursor.</p>
</div>
<button type="button" data-close-dialog aria-label="Close snippets">
×
</button>
</div>
<div class="snippet-search">
<span>⌕</span
><input
type="search"
placeholder="Find a snippet"
aria-label="Find a snippet"
/>
</div>
<div class="snippet-grid">
<button type="button" data-snippet="camera">
<span class="snippet-icon">◎</span>
<div>
<strong>Orbit camera</strong
><small>Pointer orbit and wheel zoom</small
><code>ArcRotateCamera</code>
</div>
<b>+</b>
</button>
<button type="button" data-snippet="light">
<span class="snippet-icon">☀</span>
<div>
<strong>Point light</strong><small>Warm, local illumination</small
><code>PointLight</code>
</div>
<b>+</b>
</button>
<button type="button" data-snippet="instances">
<span class="snippet-icon">◇</span>
<div>
<strong>Mesh instances</strong><small>Clone shared geometry</small
><code>mesh.clone()</code>
</div>
<b>+</b>
</button>
<button type="button" data-snippet="rows">
<span class="snippet-icon">≋</span>
<div>
<strong>Shared rows</strong
><small>Add application-owned hot data</small
><code>scene.ensureRows()</code>
</div>
<b>+</b>
</button>
<button type="button" data-snippet="post">
<span class="snippet-icon">✦</span>
<div>
<strong>Post processing</strong><small>Color grading and FXAA</small
><code>batchGraphUpdates()</code>
</div>
<b>+</b>
</button>
</div>
</dialog>
<div class="toast" id="toast" role="status" aria-live="polite"></div>
</body>
</html>