Enhance CDN packages and playground

Amp-Thread-ID: https://ampcode.com/threads/T-01a02485-5574-707c-bff4-5668d83bee8a
Co-authored-by: Heaust Azure <heaust.azure@gmail.com>
This commit is contained in:
Amp
2026-08-22 06:21:39 +00:00
co-authored by heaust
parent 7070799862
commit d95e099fa4
17 changed files with 1870 additions and 247 deletions
+178 -28
View File
@@ -4,9 +4,22 @@
<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." />
<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>
@@ -14,11 +27,18 @@
<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>
<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="Sky triangle" aria-label="Playground title" />
<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>
@@ -26,6 +46,11 @@
<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>
@@ -39,9 +64,15 @@
<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>
<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>
@@ -50,17 +81,29 @@
<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>
<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>
<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>
<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>
@@ -70,7 +113,13 @@
</footer>
</section>
<div class="resize-handle" id="resize-handle" role="separator" aria-orientation="vertical" aria-label="Resize editor and preview"></div>
<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">
@@ -95,22 +144,73 @@
</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>
<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>
<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-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>
<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 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>
@@ -120,16 +220,66 @@
<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>
<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-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>
<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>