mirror of
https://github.com/misode/misode.github.io.git
synced 2026-04-26 08:26:51 +00:00
Support 1.18 (experimental) snapshots (#158)
* Half support 1.18-experimental-snapshot-1 * Fetch 1.18 presets and improve rendering of lists * Noise preview with deepslate * Biome preview with deepslate * Generalize canvas logic in one hook * Simplify useCanvas * Use mcschema for 1.18 * Improve noise settings preview controls * Fix build * Update deepslate and improve preview caching * Cleanup, remove old preview code * Couple seed between model and preview * Limit output to improve performance + copy feedback For the vanilla overworld dimension (200K lines), it took 2+ seconds to write the output to the textarea Now capped at 10K chars * Add surface_relative_threshold to decorator preview * Improve fixed list errors
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
export * from './useCanvas'
|
||||
export * from './useFocus'
|
||||
export * from './useModel'
|
||||
export * from './useOnDrag'
|
||||
export * from './useOnHover'
|
||||
|
||||
89
src/app/hooks/useCanvas.ts
Normal file
89
src/app/hooks/useCanvas.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import type { Inputs } from 'preact/hooks'
|
||||
import { useEffect, useRef } from 'preact/hooks'
|
||||
|
||||
type Vec2 = [number, number]
|
||||
|
||||
export function useCanvas({ size, draw, onDrag, onHover, onLeave }: {
|
||||
size: () => Vec2,
|
||||
draw: (img: ImageData) => Promise<unknown>,
|
||||
onDrag?: (dx: number, dy: number) => Promise<unknown>,
|
||||
onHover?: (x: number, y: number) => unknown,
|
||||
onLeave?: () => unknown,
|
||||
}, inputs?: Inputs) {
|
||||
const canvas = useRef<HTMLCanvasElement>(null)
|
||||
|
||||
const dragStart = useRef<Vec2 | undefined>()
|
||||
const dragRequest = useRef<number>()
|
||||
const dragPending = useRef<Vec2>([0, 0])
|
||||
const dragBusy = useRef(false)
|
||||
|
||||
useEffect(() => {
|
||||
const onMouseDown = (e: MouseEvent) => {
|
||||
dragStart.current = [e.offsetX, e.offsetY]
|
||||
}
|
||||
const onMouseMove = (e: MouseEvent) => {
|
||||
if (dragStart.current === undefined) {
|
||||
const x = e.offsetX / canvas.current.clientWidth
|
||||
const y = e.offsetY / canvas.current.clientHeight
|
||||
onHover?.(x, y)
|
||||
return
|
||||
}
|
||||
if (!onDrag) return
|
||||
const dx = e.offsetX - dragStart.current[0]
|
||||
const dy = e.offsetY - dragStart.current[1]
|
||||
if (!(dx === 0 && dy === 0)) {
|
||||
dragPending.current = [dragPending.current[0] + dx, dragPending.current[1] + dy]
|
||||
if (!dragBusy.current) {
|
||||
cancelAnimationFrame(dragRequest.current)
|
||||
dragRequest.current = requestAnimationFrame(async () => {
|
||||
dragBusy.current = true
|
||||
const dx = dragPending.current[0] / canvas.current.clientWidth
|
||||
const dy = dragPending.current[1] / canvas.current.clientHeight
|
||||
dragPending.current = [0, 0]
|
||||
await onDrag?.(dx, dy)
|
||||
dragBusy.current = false
|
||||
})
|
||||
}
|
||||
}
|
||||
dragStart.current = [e.offsetX, e.offsetY]
|
||||
}
|
||||
const onMouseUp = () => {
|
||||
dragStart.current = undefined
|
||||
}
|
||||
const onMouseLeave = () => {
|
||||
onLeave?.()
|
||||
}
|
||||
|
||||
canvas.current.addEventListener('mousedown', onMouseDown)
|
||||
canvas.current.addEventListener('mousemove', onMouseMove)
|
||||
canvas.current.addEventListener('mouseleave', onMouseLeave)
|
||||
document.body.addEventListener('mouseup', onMouseUp)
|
||||
|
||||
return () => {
|
||||
canvas.current.removeEventListener('mousedown', onMouseDown)
|
||||
canvas.current.removeEventListener('mousemove', onMouseMove)
|
||||
canvas.current.removeEventListener('mouseleave', onMouseLeave)
|
||||
document.body.removeEventListener('mouseup', onMouseUp)
|
||||
}
|
||||
}, [...inputs ?? [], canvas.current])
|
||||
|
||||
const redraw = useRef<() => Promise<unknown>>()
|
||||
const redrawCount = useRef(0)
|
||||
redraw.current = async () => {
|
||||
const ctx = canvas.current.getContext('2d')!
|
||||
const s = size()
|
||||
canvas.current.width = s[0]
|
||||
canvas.current.height = s[1]
|
||||
const img = ctx.getImageData(0, 0, s[0], s[1])
|
||||
const ownCount = redrawCount.current += 1
|
||||
await draw(img)
|
||||
if (ownCount === redrawCount.current) {
|
||||
ctx.putImageData(img, 0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
canvas,
|
||||
redraw: redraw.current,
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
import { useEffect, useRef } from 'preact/hooks'
|
||||
|
||||
export function useOnDrag(element: HTMLElement, drag: (dx: number, dy: number) => unknown) {
|
||||
if (!element) return
|
||||
|
||||
const request = useRef<number>()
|
||||
const dragStart = useRef<[number, number] | undefined>()
|
||||
const pending = useRef<[number, number]>([0, 0])
|
||||
|
||||
useEffect(() => {
|
||||
const onMouseDown = (e: MouseEvent) => {
|
||||
dragStart.current = [e.offsetX, e.offsetY]
|
||||
}
|
||||
const onMouseMove = (e: MouseEvent) => {
|
||||
if (dragStart.current === undefined) return
|
||||
const dx = e.offsetX - dragStart.current[0]
|
||||
const dy = e.offsetY - dragStart.current[1]
|
||||
if (!(dx === 0 && dy === 0)) {
|
||||
cancelAnimationFrame(request.current)
|
||||
pending.current = [pending.current[0] + dx, pending.current[1] + dy]
|
||||
request.current = requestAnimationFrame(() => {
|
||||
drag(...pending.current)
|
||||
pending.current = [0, 0]
|
||||
})
|
||||
}
|
||||
dragStart.current = [e.offsetX, e.offsetY]
|
||||
}
|
||||
const onMouseUp = (_e: MouseEvent) => {
|
||||
dragStart.current = undefined
|
||||
}
|
||||
|
||||
element.addEventListener('mousedown', onMouseDown)
|
||||
element.addEventListener('mousemove', onMouseMove)
|
||||
document.body.addEventListener('mouseup', onMouseUp)
|
||||
return () => {
|
||||
element.removeEventListener('mousedown', onMouseDown)
|
||||
element.removeEventListener('mousemove', onMouseMove)
|
||||
document.body.removeEventListener('mouseup', onMouseUp)
|
||||
}
|
||||
}, [element])
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import { useEffect } from 'preact/hooks'
|
||||
|
||||
export function useOnHover(element: HTMLElement, hover: (x: number | undefined, y: number | undefined) => unknown) {
|
||||
if (!element) return
|
||||
|
||||
const onMouseMove = (e: MouseEvent) => {
|
||||
hover(e.offsetX, e.offsetY)
|
||||
}
|
||||
const onMouseLeave = () => {
|
||||
hover(undefined, undefined)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
element.addEventListener('mousemove', onMouseMove)
|
||||
element.addEventListener('mouseleave', onMouseLeave)
|
||||
return () => {
|
||||
element.removeEventListener('mousemove', onMouseMove)
|
||||
element.removeEventListener('mouseleave', onMouseLeave)
|
||||
}
|
||||
}, [element])
|
||||
}
|
||||
Reference in New Issue
Block a user