|
1 | 1 | <script lang="ts" module> |
2 | | - export const SupportedPreviewKinds = ['WorldGen__Noise']; |
| 2 | + export const SupportedPreviewKinds = ['Noise']; |
3 | 3 | </script> |
4 | 4 |
|
5 | 5 | <script lang="ts"> |
6 | | - import type { LeafNode } from '../tree/types'; |
| 6 | + import type { MmsSymbol } from '@minecraftmetascript/mms-wasm'; |
| 7 | +
|
7 | 8 | import * as deepslate from 'deepslate'; |
| 9 | + import { debounce } from 'es-toolkit'; |
| 10 | + import type { Action } from 'svelte/action'; |
| 11 | +
|
| 12 | + let { symbol }: { symbol: MmsSymbol } = $props(); |
| 13 | +
|
| 14 | + const deepslatePreview: Action<HTMLCanvasElement, MmsSymbol> = ( |
| 15 | + canvas: HTMLCanvasElement, |
| 16 | + s: MmsSymbol |
| 17 | + ) => { |
| 18 | + let symbol = s; |
| 19 | +
|
| 20 | + const update = debounce(() => { |
| 21 | + const random = new deepslate.XoroshiroRandom([ |
| 22 | + BigInt(Math.floor(performance.now())), |
| 23 | + BigInt(Math.floor(performance.timeOrigin)) |
| 24 | + ]); |
8 | 25 |
|
9 | | - let { node }: { node: LeafNode } = $props(); |
10 | | -
|
11 | | - const random = new deepslate.XoroshiroRandom([ |
12 | | - BigInt(Math.floor(performance.now())), |
13 | | - BigInt(Math.floor(performance.timeOrigin)) |
14 | | - ]); |
15 | | -
|
16 | | - $effect(() => { |
17 | | - if (!canvas) { |
18 | | - console.warn('No Canvas'); |
19 | | - return; |
20 | | - } |
21 | | - if (!node || !node.data) { |
22 | | - console.warn('No Node or Data'); |
23 | | - return; |
24 | | - } |
25 | | - const ctx = canvas.getContext('2d'); |
26 | | - if (!ctx) { |
27 | | - console.warn('No Canvas 2d Context'); |
28 | | - return; |
29 | | - } |
30 | | - const box = canvas.getBoundingClientRect(); |
31 | | - switch (node.data?.kind) { |
32 | | - case 'WorldGen__Noise': { |
33 | | - try { |
34 | | - const normalNoise = new deepslate.NormalNoise(random, node.data.value); |
35 | | - for (let pixelX = 0; pixelX < box.width; pixelX++) { |
36 | | - for (let pixelY = 0; pixelY < box.height; pixelY++) { |
37 | | - ctx.fillStyle = `hsl(${normalNoise.sample(pixelX, pixelY, 0) * 360}, 50%, 50%)`; |
38 | | - ctx.fillRect(pixelX, pixelY, 1, 1); |
| 26 | + if (!canvas) { |
| 27 | + console.warn('No Canvas'); |
| 28 | + return; |
| 29 | + } |
| 30 | + if (!symbol || !symbol.value) { |
| 31 | + console.warn('No Symbol or Value'); |
| 32 | + return; |
| 33 | + } |
| 34 | + const ctx = canvas.getContext('2d'); |
| 35 | + if (!ctx) { |
| 36 | + console.warn('No Canvas 2d Context'); |
| 37 | + return; |
| 38 | + } |
| 39 | + // TypeScript |
| 40 | + const dpr = window.devicePixelRatio || 1; |
| 41 | + const rect = canvas.getBoundingClientRect(); |
| 42 | +
|
| 43 | + // Set intrinsic size to match CSS size * DPR |
| 44 | + canvas.width = Math.floor(rect.width * dpr); |
| 45 | + canvas.height = Math.floor(rect.height * dpr); |
| 46 | +
|
| 47 | + // Scale the context so 1 unit = 1 CSS pixel |
| 48 | + ctx.setTransform(dpr, 0, 0, dpr, 0, 0); |
| 49 | + ctx.scale(3, 3); |
| 50 | +
|
| 51 | + switch (symbol.type) { |
| 52 | + case 'Noise': { |
| 53 | + requestAnimationFrame(() => { |
| 54 | + try { |
| 55 | + console.log(symbol.value); |
| 56 | + const normalNoise = new deepslate.NormalNoise(random, symbol.value as any); |
| 57 | + for (let pixelX = 0; pixelX < rect.width; pixelX += 1) { |
| 58 | + for (let pixelY = 0; pixelY < rect.height; pixelY += 1) { |
| 59 | + const val = normalNoise.sample(pixelX, pixelY, 0); |
| 60 | + const color = `hsl(0, ${val * 50 + 50}%, ${val * 20 + 40}%)`; |
| 61 | + ctx.fillStyle = color; |
| 62 | + ctx.fillRect(pixelX, pixelY, 1, 1); |
| 63 | + } |
| 64 | + } |
| 65 | + } catch (e) { |
| 66 | + console.warn(e); |
39 | 67 | } |
40 | | - } |
41 | | - } catch (e) { |
42 | | - console.warn(e); |
| 68 | + }); |
43 | 69 | } |
44 | 70 | } |
45 | | - } |
46 | | - }); |
| 71 | + }, 250); |
47 | 72 |
|
48 | | - let canvas = $state<HTMLCanvasElement | null>(); |
| 73 | + update(); |
| 74 | +
|
| 75 | + window.addEventListener('resize', update); |
| 76 | +
|
| 77 | + return { |
| 78 | + update(next: MmsSymbol) { |
| 79 | + symbol = next; |
| 80 | + update(); |
| 81 | + }, |
| 82 | + destroy() { |
| 83 | + window.removeEventListener('resize', update); |
| 84 | + } |
| 85 | + }; |
| 86 | + }; |
49 | 87 | </script> |
50 | 88 |
|
51 | | -<canvas class="aspect-square h-full max-h-full w-full max-w-full" bind:this={canvas}></canvas> |
| 89 | +<canvas class="h-full w-full" use:deepslatePreview={symbol}></canvas> |
0 commit comments