Add copy buttons for transformation tool

This commit is contained in:
Misode
2023-02-15 21:49:50 +01:00
parent b7d9b83491
commit 9c2c1bbfd0
5 changed files with 26 additions and 5 deletions

View File

@@ -1,4 +1,4 @@
import { useRef, useState } from 'preact/hooks'
import { useCallback, useRef, useState } from 'preact/hooks'
interface ActiveTimeoutOptions {
cooldown?: number,
@@ -9,13 +9,13 @@ export function useActiveTimeout({ cooldown, invert, initial }: ActiveTimeoutOpt
const [active, setActive] = useState(initial)
const timeout = useRef<number | undefined>(undefined)
const trigger = () => {
const trigger = useCallback(() => {
setActive(invert ? false : true)
if (timeout.current !== undefined) clearTimeout(timeout.current)
timeout.current = setTimeout(() => {
setActive(invert ? true : false)
}, cooldown ?? 2000) as any
}
}, [])
return [active, trigger]
}

View File

@@ -4,6 +4,7 @@ import { useCallback, useMemo, useRef, useState } from 'preact/hooks'
import { Footer, NumberInput, Octicon, RangeInput } from '../components/index.js'
import { InteractiveCanvas3D } from '../components/previews/InteractiveCanvas3D.jsx'
import { useLocale, useTitle } from '../contexts/index.js'
import { useActiveTimeout } from '../hooks/useActiveTimout.js'
import { useAsync } from '../hooks/useAsync.js'
import { loadImage } from '../services/DataFetcher.js'
import { composeMatrix, svdDecompose } from '../Utils.js'
@@ -121,6 +122,18 @@ export function Transformation({}: Props) {
renderer.current?.draw(view, usedMatrix.data)
}, [usedMatrix])
const [copiedDecomposed, setCopiedDecomposed] = useActiveTimeout()
const onCopyDecomposed = useCallback(() => {
navigator.clipboard.writeText(`{translation:[${translation.components().map(formatFloat).join(',')}],left_rotation:[${[...leftRotation].map(formatFloat).join(',')}],scale:[${scale.components().map(formatFloat).join(',')}],right_rotation:[${[...rightRotation].map(formatFloat).join(',')}]}`)
.then(() => setCopiedDecomposed())
}, [translation, leftRotation, scale, rightRotation, setCopiedDecomposed])
const [copiedComposed, setCopiedComposed] = useActiveTimeout()
const onCopyComposed = useCallback(() => {
navigator.clipboard.writeText(`[${[...matrix.data].map(formatFloat).join(',')}]`)
.then(() => setCopiedComposed())
}, [matrix, setCopiedComposed])
return <main class="has-preview">
<div class="transformation-editor">
<div class="transformation-decomposition">
@@ -128,6 +141,7 @@ export function Transformation({}: Props) {
<div class="transformation-title">
<span>{locale('transformation.translation')}</span>
<button class="tooltipped tip-se" aria-label={locale('reset')} onClick={() => updateTranslation(new Vector(0, 0, 0))}>{Octicon['history']}</button>
<button class="tooltipped tip-se" aria-label={locale('transformation.copy_decomposed')} onClick={onCopyDecomposed}>{Octicon[copiedDecomposed ? 'check' : 'clippy']}</button>
</div>
{XYZ.map((c) => <div class="transformation-input">
<NumberInput value={translation[c].toFixed(3)} onChange={v => changeTranslation(c, v)} />
@@ -172,6 +186,7 @@ export function Transformation({}: Props) {
<div class="transformation-title">
<span>{locale('transformation.matrix')}</span>
<button class="tooltipped tip-se" aria-label={locale('reset')} onClick={() => updateMatrix(new Matrix4())}>{Octicon['history']}</button>
<button class="tooltipped tip-se" aria-label={locale('transformation.copy_composed')} onClick={onCopyComposed}>{Octicon[copiedComposed ? 'check' : 'clippy']}</button>
<button class="tooltipped tip-se" aria-label={`${useMatrixOverride ? 'Expected' : 'Current'} behavior (see MC-259853)`} onClick={() => setUseMatrixOverride(!useMatrixOverride)}>{Octicon['info']}</button>
</div>
{Array(16).fill(0).map((_, i) => <div class="transformation-input">
@@ -190,6 +205,10 @@ export function Transformation({}: Props) {
</main>
}
function formatFloat(x: number) {
return x.toFixed(3).replace(/\.?0+$/, '') + 'f'
}
const vsMesh = `
attribute vec4 vertPos;
attribute vec2 texCoord;

View File

@@ -9,7 +9,6 @@ export async function shareSnippet(type: string, version: VersionId, jsonData: a
try {
const raw = JSON.stringify(jsonData)
const data = lz.compressToBase64(raw)
console.debug('Compression rate', raw.length / raw.length)
const body = JSON.stringify({ data, type, version, show_preview })
let id = ShareCache.get(body)
if (!id) {