diff --git a/web/src/components/IdeViewer/IdeViewer.js b/web/src/components/IdeViewer/IdeViewer.js index e324c19..8ef3950 100644 --- a/web/src/components/IdeViewer/IdeViewer.js +++ b/web/src/components/IdeViewer/IdeViewer.js @@ -1,10 +1,11 @@ import { IdeContext } from 'src/components/IdeToolbarNew' -import { useRef, useState, useEffect, useContext, useMemo } from 'react' +import { useRef, useState, useEffect, useContext } from 'react' import { Canvas, extend, useFrame, useThree } from 'react-three-fiber' import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls' extend({ OrbitControls }) +let debounceTimeoutId function Controls({ onCameraChange }) { const controls = useRef() const { scene, camera, gl } = useThree() @@ -12,41 +13,48 @@ function Controls({ onCameraChange }) { // init camera position camera.position.x = 16 camera.position.y = 12 - console.log(camera) camera.fov = 22.5 // matches default openscad fov // Order matters with Euler rotations // We want it to rotate around the z or vertical axis first then the x axis to match openscad // in Three.js Y is the vertical axis (Z for openscad) camera.rotation._order = 'YXZ' + const getRotations = () => { + const { x, y, z } = camera.rotation + const rad2Deg = 180 / Math.PI + const scadX = (x + Math.PI / 2) * rad2Deg + const scadZ = y * rad2Deg + const scadY = z * rad2Deg + return [scadX, scadY, scadZ] + } + const getPositions = () => { + const { x: scadX, y: scadZ, z: negScadY } = camera.position + const scale = 10 + const scadY = -negScadY + return [scadX * scale, scadY * scale, scadZ * scale] + } if (controls.current) { - const callback = ({ target }) => { - const getRotations = () => { - const { x, y, z } = target.object.rotation - const rad2Deg = 180 / Math.PI - const scadX = (x + Math.PI / 2) * rad2Deg - const scadZ = y * rad2Deg - const scadY = z * rad2Deg - return [scadX, scadY, scadZ] - } - const getPositions = () => { - const { x: scadX, y: scadZ, z: negScadY } = target.object.position - const scale = 10 - const scadY = -negScadY - return [scadX * scale, scadY * scale, scadZ * scale] - } - const [rx, ry, rz] = getRotations() - const [x, y, z] = getPositions() + const dragCallback = () => { + clearTimeout(debounceTimeoutId) + debounceTimeoutId = setTimeout(() => { + const [rx, ry, rz] = getRotations() + const [x, y, z] = getPositions() - onCameraChange({ - position: { x, y, z }, - rotation: { x: rx, y: ry, z: rz }, - }) + onCameraChange({ + position: { x, y, z }, + rotation: { x: rx, y: ry, z: rz }, + }) + }, 400) } - controls.current.addEventListener('end', callback) + const dragStart = () => clearTimeout(debounceTimeoutId) + controls.current.addEventListener('end', dragCallback) + controls.current.addEventListener('start', dragStart) const oldCurrent = controls.current - return () => oldCurrent.removeEventListener('end', callback) + return () => { + oldCurrent.removeEventListener('end', dragCallback) + oldCurrent.removeEventListener('start', dragStart) + } } }, []) @@ -55,8 +63,6 @@ function Controls({ onCameraChange }) { ) @@ -77,32 +83,39 @@ let currentCode // I have no idea why this works and using state.code is the dis const IdeViewer = () => { const { state, dispatch } = useContext(IdeContext) const [isDragging, setIsDragging] = useState(false) + const [image, setImage] = useState() - const image = useMemo( - () => + useEffect(() => { + setImage( state.objectData?.type === 'png' && - state.objectData?.data && - window.URL.createObjectURL(state.objectData?.data), - [state.objectData] - ) + state.objectData?.data && + window.URL.createObjectURL(state.objectData?.data) + ) + setIsDragging(false) + }, [state.objectData]) currentCode = state.code return (
+ {state.isLoading && ( +
+
+
+ )} {image && (
)}
setIsDragging(true)} - onMouseUp={() => setIsDragging(false)} > { /> - - - + + +
diff --git a/web/src/helpers/hooks/useIdeState.js b/web/src/helpers/hooks/useIdeState.js index 9777dcc..a3e6994 100644 --- a/web/src/helpers/hooks/useIdeState.js +++ b/web/src/helpers/hooks/useIdeState.js @@ -23,6 +23,7 @@ export const useIdeState = () => { splitPercentage: 70, }, }, + isLoading: false, } const reducer = (state, { type, payload }) => { switch (type) { @@ -38,6 +39,7 @@ export const useIdeState = () => { consoleMessages: payload.message ? [...state.consoleMessages, payload.message] : payload.message, + isLoading: false, } case 'errorRender': return { @@ -45,6 +47,7 @@ export const useIdeState = () => { consoleMessages: payload.message ? [...state.consoleMessages, payload.message] : payload.message, + isLoading: false, } case 'setIdeType': return { @@ -56,6 +59,11 @@ export const useIdeState = () => { ...state, layout: payload.message, } + case 'setLoading': + return { + ...state, + isLoading: true, + } default: return state } @@ -83,6 +91,7 @@ export const useIdeState = () => { }) } }) + dispatch({ type: 'setLoading' }) break default: