mirror of
https://github.com/misode/misode.github.io.git
synced 2026-04-30 17:49:34 +00:00
Add copy buttons for transformation tool
This commit is contained in:
@@ -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]
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -134,6 +134,8 @@
|
||||
"transformation.left_rotation": "Left rotation",
|
||||
"transformation.scale": "Scale",
|
||||
"transformation.right_rotation": "Right rotation",
|
||||
"transformation.copy_decomposed": "Copy decomposed format",
|
||||
"transformation.copy_composed": "Copy matrix format",
|
||||
"trim_material": "Trim material",
|
||||
"trim_pattern": "Trim pattern",
|
||||
"pack_mcmeta": "Pack.mcmeta",
|
||||
|
||||
@@ -598,6 +598,7 @@ main.has-project {
|
||||
.transformation-title {
|
||||
display: flex;
|
||||
margin-bottom: 2px;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.transformation-title span {
|
||||
@@ -608,7 +609,7 @@ main.has-project {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 2px 3px;
|
||||
padding: 4px 6px;
|
||||
background-color: var(--background-4);
|
||||
border: none;
|
||||
border-radius: 3px;
|
||||
|
||||
Reference in New Issue
Block a user