import React , { VFC } from 'react' ; import TransformControlsModeSelect from './TransformControlsModeSelect' ; import { useEditorStore } from '../store' ; import shallow from 'zustand/shallow' ; import ReferenceWindow from './ReferenceWindow' ; import { saveAs } from 'file-saver' ; import { Vector3 } from 'three' ; import { RiFocus3Line } from '@react-icons/all-files/ri/RiFocus3Line' ; import { GiPocketBow } from '@react-icons/all-files/gi/GiPocketBow' ; import { AiFillEye } from '@react-icons/all-files/ai/AiFillEye' ; import TransformControlsSpaceSelect from './TransformControlsSpaceSelect' ; import ViewportShadingSelect from './ViewportShadingSelect' ; import SceneOutlinePanel from './SceneOutlinePanel' ; import PropertiesPanel from './PropertiesPanel' ; import { IconButton , Button , SettingsButton } from './elements' ; import ViewportSettings from './ViewportSettings' ; const UI = ( ) => { const [ transformControlsMode , transformControlsSpace , viewportShading , setTransformControlsMode , setTransformControlsSpace , setViewportShading , setEditorOpen , setEditableTransform , ] = useEditorStore ( ( state ) => [ state . transformControlsMode , state . transformControlsSpace , state . viewportShading , state . setTransformControlsMode , state . setTransformControlsSpace , state . setViewportShading , state . setEditorOpen , state . setEditableTransform , ] , shallow ) ; return ( < div className = "absolute inset-0 z-50 pointer-events-none" > < div className = "flex h-full" > < div className = "w-min pointer-events-auto" > < SceneOutlinePanel /> < /div> < div className = "relative flex-1 m-5" > < div className = "flex items-start justify-between" > < div className = "flex gap-4" > < div className = "pointer-events-auto" > < TransformControlsModeSelect value = { transformControlsMode } onChange = { ( value ) => setTransformControlsMode ( value ) } /> < /div> < div className = "pointer-events-auto" > < TransformControlsSpaceSelect value = { transformControlsSpace } onChange = { setTransformControlsSpace } / > < /div> < div className = "pointer-events-auto" > < ViewportShadingSelect value = { viewportShading } onChange = { setViewportShading } / > < /div> < div className = "pointer-events-auto" > < IconButton label = "Focus on selected" icon = { < RiFocus3Line / > } onClick = { ( ) => { const orbitControls = useEditorStore . getState ( ) . orbitControlsRef ?. current ; const selected = useEditorStore . getState ( ) . selected ; let focusObject ; if ( selected ) { focusObject = useEditorStore . getState ( ) . editablesSnapshot ! [ selected ] . proxyObject ; } if ( orbitControls && focusObject ) { focusObject . getWorldPosition ( orbitControls . target as Vector3 ) ; } } } /> < /div> < div className = "pointer-events-auto" > < IconButton label = "Align object to view" icon = { < GiPocketBow / > } onClick = { ( ) => { const camera = useEditorStore . getState ( ) . orbitControlsRef ?. current ?. object ; const selected = useEditorStore . getState ( ) . selected ; let proxyObject ; if ( selected ) { proxyObject = useEditorStore . getState ( ) . editablesSnapshot ! [ selected ] . proxyObject ; if ( proxyObject && camera ) { const direction = new Vector3 ( ) ; const position = camera . position . clone ( ) ; camera . getWorldDirection ( direction ) ; proxyObject . position . set ( 0 , 0 , 0 ) ; proxyObject . lookAt ( direction ) ; proxyObject . parent ! . worldToLocal ( position ) ; proxyObject . position . copy ( position ) ; proxyObject . updateMatrix ( ) ; setEditableTransform ( selected , proxyObject . matrix . clone ( ) ) ; } } } } /> < /div> < div className = "pointer-events-auto" > < SettingsButton icon = { < AiFillEye />} label="Viewport settings"> < ViewportSettings / > < /SettingsButton> < /div> < /div> < div className = "absolute right-0 top-0 -z-10" > < ReferenceWindow height = { 120 } /> < /div> < /div> { } < Button className = "absolute left-0 bottom-0 pointer-events-auto" onClick = { ( ) => setEditorOpen ( false ) } > Close < /Button> { } < Button className = "absolute right-0 bottom-0 pointer-events-auto" onClick = { ( ) => { const blob = new Blob ( [ JSON . stringify ( useEditorStore . getState ( ) . serialize ( ) ) ] , { type : 'text/json;charset=utf-8' } ) ; saveAs ( blob , 'editableState.json' ) ; } } > Save < /Button> < /div> < div className = "w-min pointer-events-auto" > < PropertiesPanel /> < /div> < /div> < /div>); } ; export default UI ;