theatre/packages/plugin-r3f/src/components/SnapshotEditor.tsx

178 lines
4.5 KiB
TypeScript
Raw Normal View History

2021-07-16 15:06:15 +02:00
import {useState} from 'react'
import {useLayoutEffect} from 'react'
2021-07-03 15:16:18 +02:00
import React, {useEffect, useRef} from 'react'
2021-06-18 13:05:06 +02:00
import {Canvas} from '@react-three/fiber'
import {useEditorStore} from '../store'
2021-07-03 15:16:18 +02:00
import {OrbitControls} from '@react-three/drei'
2021-06-18 13:05:06 +02:00
import shallow from 'zustand/shallow'
2021-07-04 19:14:00 +02:00
import root from 'react-shadow/styled-components'
2021-06-18 13:05:06 +02:00
import ProxyManager from './ProxyManager'
2021-07-22 21:26:34 +02:00
import studio, {ToolbarIconButton} from '@theatre/studio'
import {useVal} from '@theatre/dataverse-react'
2021-07-13 16:13:15 +02:00
import styled, {createGlobalStyle, StyleSheetManager} from 'styled-components'
2021-07-22 21:26:34 +02:00
import {IoCameraReverseOutline} from 'react-icons/all'
2021-07-04 19:14:00 +02:00
const GlobalStyle = createGlobalStyle`
:host {
contain: strict;
all: initial;
color: white;
font: 11px -apple-system, BlinkMacSystemFont, Segoe WPC, Segoe Editor,
HelveticaNeue-Light, Ubuntu, Droid Sans, sans-serif;
}
* {
padding: 0;
margin: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
list-style: none;
}
`
2021-06-18 13:05:06 +02:00
const EditorScene = () => {
const orbitControlsRef = useRef<typeof OrbitControls>()
2021-07-03 15:16:18 +02:00
const [editorObject, helpersRoot, setOrbitControlsRef] = useEditorStore(
2021-06-18 13:05:06 +02:00
(state) => [
2021-07-03 13:24:39 +02:00
state.editorObject,
2021-06-18 13:05:06 +02:00
state.helpersRoot,
state.setOrbitControlsRef,
],
shallow,
)
const showGrid = useVal(editorObject?.props.viewport.showGrid) ?? true
const showAxes = useVal(editorObject?.props.viewport.showAxes) ?? true
2021-07-03 13:24:39 +02:00
2021-06-18 13:05:06 +02:00
useEffect(() => {
setOrbitControlsRef(orbitControlsRef)
}, [setOrbitControlsRef])
return (
<>
2021-07-13 16:13:15 +02:00
{showGrid && <gridHelper args={[20, 20, '#6e6e6e', '#4a4b4b']} />}
2021-06-18 13:05:06 +02:00
{showAxes && <axesHelper args={[500]} />}
{/* @ts-ignore */}
2021-07-05 18:39:57 +02:00
<OrbitControls ref={orbitControlsRef} enableDamping={false} />
2021-06-18 13:05:06 +02:00
<primitive object={helpersRoot}></primitive>
<ProxyManager orbitControlsRef={orbitControlsRef} />
2021-07-13 16:13:15 +02:00
<color attach="background" args={[0.24, 0.24, 0.24]} />
2021-06-18 13:05:06 +02:00
</>
)
}
2021-07-14 18:37:32 +02:00
const Wrapper = styled.div`
2021-07-04 19:14:00 +02:00
tab-size: 4;
line-height: 1.15; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
margin: 0;
2021-07-14 18:37:32 +02:00
position: absolute;
2021-07-04 19:14:00 +02:00
top: 0px;
right: 0px;
bottom: 0px;
left: 0px;
`
const CanvasWrapper = styled.div`
display: relative;
z-index: 0;
height: 100%;
`
2021-07-16 15:06:15 +02:00
const Overlay = styled.div`
position: absolute;
inset: 0;
z-index: 2;
pointer-events: none;
`
const Tools = styled.div`
position: absolute;
left: 8px;
top: 6px;
pointer-events: auto;
`
2021-07-14 18:37:32 +02:00
2021-07-16 15:06:15 +02:00
const SnapshotEditor: React.FC<{}> = () => {
const [editorObject, sceneSnapshot, initialEditorCamera, createSnapshot] =
useEditorStore(
(state) => [
state.editorObject,
state.sceneSnapshot,
state.initialEditorCamera,
state.createSnapshot,
],
shallow,
)
2021-07-14 18:37:32 +02:00
const editorOpen = true
useLayoutEffect(() => {
2021-07-14 18:37:32 +02:00
let timeout: NodeJS.Timeout | undefined
if (editorOpen) {
2021-07-14 18:37:32 +02:00
// a hack to make sure all the scene's props are
// applied before we take a snapshot
timeout = setTimeout(createSnapshot, 100)
}
return () => {
if (timeout !== undefined) {
clearTimeout(timeout)
}
}
}, [editorOpen])
2021-07-16 15:06:15 +02:00
const [overlay, setOverlay] = useState<HTMLDivElement | null>(null)
if (!editorObject) return <></>
2021-06-18 13:05:06 +02:00
return (
<root.div>
2021-07-13 16:13:15 +02:00
<StyleSheetManager disableVendorPrefixes>
<>
<GlobalStyle />
2021-07-22 21:26:34 +02:00
{/* <PortalContext.Provider value={overlay}> */}
<Wrapper>
<Overlay ref={setOverlay}>
<Tools>
<ToolbarIconButton
icon={<IoCameraReverseOutline />}
label="Refresh Snapshot"
onClick={createSnapshot}
></ToolbarIconButton>
</Tools>
</Overlay>
{sceneSnapshot ? (
<>
<CanvasWrapper>
<Canvas
// @ts-ignore
colorManagement
camera={initialEditorCamera}
onCreated={({gl}) => {
gl.setClearColor('white')
}}
shadowMap
dpr={[1, 2]}
fog={'red'}
onPointerMissed={() =>
studio.__experimental_setSelection([])
}
>
<EditorScene />
</Canvas>
</CanvasWrapper>
</>
) : null}
</Wrapper>
{/* </PortalContext.Provider> */}
2021-07-13 16:13:15 +02:00
</>
</StyleSheetManager>
2021-06-18 13:05:06 +02:00
</root.div>
)
}
2021-07-14 18:37:32 +02:00
export default SnapshotEditor